diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index baba9c79b..ef72ca352 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,18 +12,13 @@ jobs: strategy: matrix: entry: - - os: ubuntu-22.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 - wasi-backend: Node - target: "wasm32-unknown-wasi" - env: | - JAVASCRIPTKIT_DISABLE_TRACING_TRAIT=1 - os: ubuntu-24.04 toolchain: - download-url: https://download.swift.org/development/ubuntu2404/swift-DEVELOPMENT-SNAPSHOT-2025-12-01-a/swift-DEVELOPMENT-SNAPSHOT-2025-12-01-a-ubuntu24.04.tar.gz + download-url: https://download.swift.org/development/ubuntu2404/swift-DEVELOPMENT-SNAPSHOT-2026-05-27-a/swift-DEVELOPMENT-SNAPSHOT-2026-05-27-a-ubuntu24.04.tar.gz wasi-backend: Node target: "wasm32-unknown-wasip1" + env: | + JAVASCRIPTKIT_DISABLE_TRACING_TRAIT=1 - os: ubuntu-24.04 toolchain: download-url: https://download.swift.org/swift-6.3-branch/ubuntu2404/swift-6.3-DEVELOPMENT-SNAPSHOT-2026-03-05-a/swift-6.3-DEVELOPMENT-SNAPSHOT-2026-03-05-a-ubuntu24.04.tar.gz @@ -31,7 +26,7 @@ jobs: target: "wasm32-unknown-wasip1" - os: ubuntu-22.04 toolchain: - 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 + download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2026-05-27-a/swift-DEVELOPMENT-SNAPSHOT-2026-05-27-a-ubuntu22.04.tar.gz wasi-backend: Node target: "wasm32-unknown-wasip1-threads" @@ -77,10 +72,6 @@ jobs: strategy: matrix: entry: - - image: "swift:6.1.2" - swift-syntax-version: "601.0.0" - - image: "swift:6.2" - swift-syntax-version: "602.0.0" - image: "swift:6.3" swift-syntax-version: "603.0.0" runs-on: ubuntu-latest @@ -110,7 +101,7 @@ jobs: matrix: include: - os: macos-15 - xcode: Xcode_16.4 + xcode: Xcode_26.0.1 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v6 @@ -134,7 +125,7 @@ jobs: format: runs-on: ubuntu-latest container: - image: swift:6.1.2 + image: swift:6.3 steps: - uses: actions/checkout@v6 - run: ./Utilities/format.swift @@ -152,7 +143,7 @@ jobs: - uses: actions/checkout@v6 - uses: ./.github/actions/install-swift with: - 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 + download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2026-05-27-a/swift-DEVELOPMENT-SNAPSHOT-2026-05-27-a-ubuntu22.04.tar.gz - run: make bootstrap - run: ./Utilities/bridge-js-generate.sh - name: Check if BridgeJS generated files are up-to-date @@ -169,16 +160,14 @@ jobs: - uses: actions/checkout@v6 - uses: ./.github/actions/install-swift with: - download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2026-03-09-a/swift-DEVELOPMENT-SNAPSHOT-2026-03-09-a-ubuntu22.04.tar.gz + download-url: https://download.swift.org/development/ubuntu2204/swift-DEVELOPMENT-SNAPSHOT-2026-05-27-a/swift-DEVELOPMENT-SNAPSHOT-2026-05-27-a-ubuntu22.04.tar.gz - uses: swiftwasm/setup-swiftwasm@v2 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: | - swift --version - ./Utilities/build-examples.sh + - 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_wasip1: ${{ steps.setup-wasm32-unknown-wasip1.outputs.swift-sdk-id }} diff --git a/Benchmarks/Sources/Generated/BridgeJS.Macros.swift b/Benchmarks/Sources/Generated/BridgeJS.Macros.swift index 40fc29e91..b107d8d3c 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.Macros.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.Macros.swift @@ -1,3 +1,4 @@ +// swift-format-ignore-file // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index e199e4a29..384ca35a2 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -1,4 +1,5 @@ // bridge-js: skip +// swift-format-ignore-file // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // diff --git a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json index 0bddddfb6..7209c62f7 100644 --- a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json +++ b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.json @@ -3339,6 +3339,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -3355,6 +3356,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -3378,6 +3380,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -3415,5 +3418,8 @@ } ] }, - "moduleName" : "Benchmarks" + "moduleName" : "Benchmarks", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d984555e6..8cb96dec9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,14 +12,37 @@ Thank you for considering contributing to JavaScriptKit! We welcome contribution - Relevant error messages or logs ### Setting Up the Development Environment -1. Clone the repository: - ```bash - git clone https://github.com/swiftwasm/JavaScriptKit.git - cd JavaScriptKit - ``` -2. Install **OSS** Swift toolchain via `swiftly` -3. Install Swift SDK for Wasm corresponding to the Swift version: +Clone the repository: + +```bash +git clone https://github.com/swiftwasm/JavaScriptKit.git +cd JavaScriptKit +``` + +#### Quick start (recommended) + +If you already have an **OSS** Swift toolchain installed via [`swiftly`](https://www.swift.org/install/macos/swiftly), run: + +```bash +./Utilities/setup-dev.sh +``` + +The script verifies prerequisites, installs a matching Wasm Swift SDK from +[swift-sdk-index](https://github.com/swiftwasm/swift-sdk-index), runs `make bootstrap`, +and prints the `SWIFT_SDK_ID` to use with `make unittest`. Re-running it is +idempotent. + +If a `.swift-version` file is present in the repo root, the script will install +that toolchain via `swiftly` automatically. Create one to pin your local dev +toolchain to an indexed release (e.g. `echo 6.3.0 > .swift-version`). The repo +does not track `.swift-version`; if you'd like git to ignore it locally, add it +to `.git/info/exclude`. + +#### Manual setup + +1. Install an **OSS** Swift toolchain via `swiftly`. +2. Install the Swift SDK for Wasm corresponding to the Swift version: ```bash ( set -eo pipefail; \ @@ -35,7 +58,7 @@ Thank you for considering contributing to JavaScriptKit! We welcome contribution jq -r '.["swift-sdks"]["wasm32-unknown-wasip1"]["id"]' ) ``` -4. Install dependencies: +3. Install dependencies: ```bash make bootstrap ``` diff --git a/Examples/ActorOnWebWorker/build.sh b/Examples/ActorOnWebWorker/build.sh index 4def77883..66c10a2c4 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}}" \ +swift package --build-system native --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 -c release diff --git a/Examples/Basic/build.sh b/Examples/Basic/build.sh index 2351f4e2d..07f436c4b 100755 --- a/Examples/Basic/build.sh +++ b/Examples/Basic/build.sh @@ -1,3 +1,3 @@ #!/bin/bash set -euxo pipefail -swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" js --use-cdn -c "${1:-debug}" +swift package --build-system native --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/README.md b/Examples/Embedded/README.md index e99d659ff..97e2490b7 100644 --- a/Examples/Embedded/README.md +++ b/Examples/Embedded/README.md @@ -1,6 +1,6 @@ # Embedded example -Requires a recent DEVELOPMENT-SNAPSHOT toolchain. (tested with swift-6.1-DEVELOPMENT-SNAPSHOT-2025-02-21-a) +Requires a recent DEVELOPMENT-SNAPSHOT toolchain. ```sh $ ./build.sh diff --git a/Examples/Embedded/build.sh b/Examples/Embedded/build.sh index d756d8d1e..486f3581d 100755 --- a/Examples/Embedded/build.sh +++ b/Examples/Embedded/build.sh @@ -1,5 +1,5 @@ #!/bin/bash set -euxo pipefail package_dir="$(cd "$(dirname "$0")" && pwd)" -swift package --package-path "$package_dir" \ +swift package --build-system native --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/MultiModule/Package.swift b/Examples/MultiModule/Package.swift new file mode 100644 index 000000000..870e2a5e8 --- /dev/null +++ b/Examples/MultiModule/Package.swift @@ -0,0 +1,38 @@ +// swift-tools-version:6.0 + +import PackageDescription + +let package = Package( + name: "MultiModule", + platforms: [ + .macOS(.v14) + ], + dependencies: [.package(name: "JavaScriptKit", path: "../../")], + targets: [ + .target( + name: "Core", + dependencies: [ + "JavaScriptKit" + ], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ], + plugins: [ + .plugin(name: "BridgeJS", package: "JavaScriptKit") + ] + ), + .executableTarget( + name: "MultiModule", + dependencies: [ + "Core", + "JavaScriptKit", + ], + swiftSettings: [ + .enableExperimentalFeature("Extern") + ], + plugins: [ + .plugin(name: "BridgeJS", package: "JavaScriptKit") + ] + ), + ] +) diff --git a/Examples/MultiModule/README.md b/Examples/MultiModule/README.md new file mode 100644 index 000000000..741394d6f --- /dev/null +++ b/Examples/MultiModule/README.md @@ -0,0 +1,17 @@ +# MultiModule Example + +This example demonstrates using `@JS` types defined in one module (`Core`) from another module (`App`) within the same Swift package. + +## Building and Running + +1. Build the project: + ```sh + swift package --swift-sdk $SWIFT_SDK_ID js --use-cdn + ``` + +2. Serve the files: + ```sh + npx serve + ``` + +Then open your browser to `http://localhost:3000`. diff --git a/Examples/MultiModule/Sources/Core/Vector3D.swift b/Examples/MultiModule/Sources/Core/Vector3D.swift new file mode 100644 index 000000000..988892bcc --- /dev/null +++ b/Examples/MultiModule/Sources/Core/Vector3D.swift @@ -0,0 +1,17 @@ +import JavaScriptKit + +@JS public struct Vector3D { + public let x: Double + public let y: Double + public let z: Double + + @JS public init(x: Double, y: Double, z: Double) { + self.x = x + self.y = y + self.z = z + } + + @JS public func magnitude() -> Double { + (x * x + y * y + z * z).squareRoot() + } +} diff --git a/Examples/MultiModule/Sources/Core/bridge-js.config.json b/Examples/MultiModule/Sources/Core/bridge-js.config.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/Examples/MultiModule/Sources/Core/bridge-js.config.json @@ -0,0 +1 @@ +{} diff --git a/Examples/MultiModule/Sources/MultiModule/bridge-js.config.json b/Examples/MultiModule/Sources/MultiModule/bridge-js.config.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/Examples/MultiModule/Sources/MultiModule/bridge-js.config.json @@ -0,0 +1 @@ +{} diff --git a/Examples/MultiModule/Sources/MultiModule/main.swift b/Examples/MultiModule/Sources/MultiModule/main.swift new file mode 100644 index 000000000..dd238c00d --- /dev/null +++ b/Examples/MultiModule/Sources/MultiModule/main.swift @@ -0,0 +1,6 @@ +import Core +import JavaScriptKit + +@JS public func currentVelocity() -> Vector3D { + Vector3D(x: 0.1, y: 0.2, z: 0.3) +} diff --git a/Examples/MultiModule/index.html b/Examples/MultiModule/index.html new file mode 100644 index 000000000..d9066820f --- /dev/null +++ b/Examples/MultiModule/index.html @@ -0,0 +1,12 @@ + + + + + MultiModule Example + + + + + + + diff --git a/Examples/MultiModule/index.js b/Examples/MultiModule/index.js new file mode 100644 index 000000000..83e79f16d --- /dev/null +++ b/Examples/MultiModule/index.js @@ -0,0 +1,10 @@ +import { init } from "./.build/plugins/PackageToJS/outputs/Package/index.js"; +const { exports } = await init({}); + +const velocity = exports.currentVelocity(); + +const output = document.createElement("pre"); +output.innerText = + `currentVelocity() = (${velocity.x}, ${velocity.y}, ${velocity.z})\n` + + `magnitude = ${velocity.magnitude()}`; +document.body.appendChild(output); diff --git a/Examples/Multithreading/build.sh b/Examples/Multithreading/build.sh index 4def77883..66c10a2c4 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}}" \ +swift package --build-system native --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 -c release diff --git a/Examples/OffscrenCanvas/build.sh b/Examples/OffscrenCanvas/build.sh index 4def77883..66c10a2c4 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}}" \ +swift package --build-system native --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 -c release diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift index 4a87a6d38..6c9960b02 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.Macros.swift @@ -1,3 +1,4 @@ +// swift-format-ignore-file // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift index 056c1c27d..37b024346 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift @@ -1,4 +1,5 @@ // bridge-js: skip +// swift-format-ignore-file // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // @@ -187,7 +188,7 @@ public func _bjs_PlayBridgeJS_updateDetailed(_ _self: UnsafeMutableRawPointer, _ _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.json b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.json index 1a21916ee..6f1fc940c 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.json +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.json @@ -242,6 +242,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -260,11 +261,13 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -300,5 +303,8 @@ } ] }, - "moduleName" : "PlayBridgeJS" + "moduleName" : "PlayBridgeJS", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/main.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/main.swift index ec9eda774..a30eb3b06 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/main.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/main.swift @@ -45,7 +45,12 @@ import class Foundation.JSONDecoder func _update(swiftSource: String, dtsSource: String) throws -> PlayBridgeJSOutput { let moduleName = "Playground" - let swiftToSkeleton = SwiftToSkeleton(progress: .silent, moduleName: moduleName, exposeToGlobal: false) + let swiftToSkeleton = SwiftToSkeleton( + progress: .silent, + moduleName: moduleName, + exposeToGlobal: false, + externalModuleIndex: .empty + ) swiftToSkeleton.addSourceFile(Parser.parse(source: swiftSource), inputFilePath: "Playground.swift") let ts2swift = try createTS2Swift() diff --git a/Examples/PlayBridgeJS/build.sh b/Examples/PlayBridgeJS/build.sh index 31c07896c..eb444a899 100755 --- a/Examples/PlayBridgeJS/build.sh +++ b/Examples/PlayBridgeJS/build.sh @@ -1,5 +1,5 @@ #!/bin/bash set -euxo pipefail -swift package --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" \ +swift package --build-system native --swift-sdk "${SWIFT_SDK_ID_wasm32_unknown_wasip1:-${SWIFT_SDK_ID:-wasm32-unknown-wasip1}}" \ plugin --allow-writing-to-package-directory \ js --use-cdn --output ./Bundle -c "${1:-debug}" diff --git a/Makefile b/Makefile index 270eb9b36..4b174e347 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ unittest: echo "SWIFT_SDK_ID is not set. Run 'swift sdk list' and pass a matching SDK, e.g. 'make unittest SWIFT_SDK_ID='."; \ exit 2; \ } - swift package --swift-sdk "$(SWIFT_SDK_ID)" \ + swift package --build-system native --swift-sdk "$(SWIFT_SDK_ID)" \ $(TRACING_ARGS) \ --disable-sandbox \ js test --prelude ./Tests/prelude.mjs -Xnode --expose-gc diff --git a/Package@swift-6.1.swift b/Package@swift-6.1.swift deleted file mode 100644 index fe98ec529..000000000 --- a/Package@swift-6.1.swift +++ /dev/null @@ -1,222 +0,0 @@ -// swift-tools-version:6.1 - -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 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"]), - ], - 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") - ] - + (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") - ], - 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 - ), - .testTarget( - name: "BridgeJSIdentityTests", - dependencies: ["JavaScriptKit", "JavaScriptEventLoop"], - exclude: [ - "bridge-js.config.json", - "Generated/JavaScript", - ], - swiftSettings: [ - .enableExperimentalFeature("Extern") - ], - linkerSettings: testingLinkerFlags - ), - ] -) diff --git a/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSBuildPlugin.swift b/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSBuildPlugin.swift index 3cb6dc860..b78f5f9a6 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSBuildPlugin.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSBuildPlugin.swift @@ -63,6 +63,19 @@ struct BridgeJSBuildPlugin: BuildToolPlugin { ]) } + for skeleton in dependencySkeletons(context: context, target: target) { + arguments.append(contentsOf: [ + "--dependency-skeleton", + "\(skeleton.moduleName)=\(skeleton.skeletonURL.path)", + ]) + // We have to use the Swift file, not the skeleton, as the input file, + // since we can’t make the skeleton file an output file without it being + // treated as a resource by the build system (and thus included in the + // resource bundle). We need to use something as the inputFile to maintain + // correct ordering. + inputFiles.append(skeleton.bridgeJSSwiftURL) + } + let allSwiftFiles = inputSwiftFiles + pluginGeneratedSwiftFiles arguments.append(contentsOf: allSwiftFiles.map(\.path)) @@ -74,5 +87,56 @@ struct BridgeJSBuildPlugin: BuildToolPlugin { outputFiles: [outputSwiftPath] ) } + + private struct DependencySkeleton { + let moduleName: String + let skeletonURL: URL + let bridgeJSSwiftURL: URL + } + + /// We only read skeletons from dependencies with a `bridge-js.config.json` file. + /// For the build system to correctly order the plugins, we need to set the skeleton + /// files as input. However, I don’t think we have enough information here to determine + /// whether the plugin which generates this is applied to the dependency, so we use + /// the presence of `bridge-js.config.json` instead. + private func dependencySkeletons( + context: PluginContext, + target: SwiftSourceModuleTarget + ) -> [DependencySkeleton] { + let localTargets: [SwiftSourceModuleTarget] = target.recursiveTargetDependencies + .compactMap { dependency in + guard + let swiftTarget = dependency as? SwiftSourceModuleTarget, + context.package.targets.contains(where: { $0.id == swiftTarget.id }), + FileManager.default.fileExists(atPath: pathToConfigFile(target: swiftTarget).path) + else { + return nil + } + return swiftTarget + } + + var skeletons: [DependencySkeleton] = [] + var seenTargetNames = Set() + for swiftTarget in localTargets where seenTargetNames.insert(swiftTarget.name).inserted { + let skeletonURL = BridgeJSPluginPaths.skeletonURL( + targetName: swiftTarget.name, + packageID: context.package.id, + buildPluginWorkDirectoryURL: context.pluginWorkDirectoryURL + ) + let bridgeJSSwiftURL = BridgeJSPluginPaths.bridgeJSSwiftURL( + targetName: swiftTarget.name, + packageID: context.package.id, + buildPluginWorkDirectoryURL: context.pluginWorkDirectoryURL + ) + skeletons.append( + DependencySkeleton( + moduleName: swiftTarget.name, + skeletonURL: skeletonURL, + bridgeJSSwiftURL: bridgeJSSwiftURL + ) + ) + } + return skeletons + } } #endif diff --git a/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSPluginUtilities b/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSPluginUtilities new file mode 120000 index 000000000..2daaa446e --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSBuildPlugin/BridgeJSPluginUtilities @@ -0,0 +1 @@ +../BridgeJSPluginUtilities \ No newline at end of file diff --git a/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift b/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift index 23fbae567..24b96f53d 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCommandPlugin/BridgeJSCommandPlugin.swift @@ -74,28 +74,62 @@ struct BridgeJSCommandPlugin: CommandPlugin { } extension BridgeJSCommandPlugin.Context { - func runOnTargets( - remainingArguments: [String], - where predicate: (SwiftSourceModuleTarget) -> Bool - ) throws { + private func collectBridgeJSTargets() -> [String: SwiftSourceModuleTarget] { + var bridgeJSTargets: [String: SwiftSourceModuleTarget] = [:] for target in context.package.targets { - guard let target = target as? SwiftSourceModuleTarget else { + guard + let swiftTarget = target as? SwiftSourceModuleTarget, + FileManager.default.fileExists( + atPath: swiftTarget.directoryURL.appending(path: "bridge-js.config.json").path + ) + else { continue } - let configFilePath = target.directoryURL.appending(path: "bridge-js.config.json") - if !FileManager.default.fileExists(atPath: configFilePath.path) { - printVerbose("No bridge-js.config.json found for \(target.name), skipping...") - continue + bridgeJSTargets[swiftTarget.name] = swiftTarget + } + return bridgeJSTargets + } + + private func targetsInDependencyOrder( + _ bridgeJSTargets: [String: SwiftSourceModuleTarget] + ) -> [SwiftSourceModuleTarget] { + var visitedTargetNames = Set() + var orderedTargets: [SwiftSourceModuleTarget] = [] + func visit(_ target: SwiftSourceModuleTarget) { + if !visitedTargetNames.insert(target.name).inserted { + return } - guard predicate(target) else { - continue + for dependency in target.recursiveTargetDependencies { + if let dependencyTarget = bridgeJSTargets[dependency.name] { + visit(dependencyTarget) + } } - try runSingleTarget(target: target, remainingArguments: remainingArguments) + orderedTargets.append(target) + } + for target in bridgeJSTargets.values.sorted(by: { $0.name < $1.name }) { + visit(target) + } + return orderedTargets + } + + func runOnTargets( + remainingArguments: [String], + where predicate: (SwiftSourceModuleTarget) -> Bool + ) throws { + let allBridgeJSTargets = collectBridgeJSTargets() + let requestedTargets = allBridgeJSTargets.filter { predicate($1) } + for target in targetsInDependencyOrder(requestedTargets) { + try runSingleTarget( + target: target, + bridgeJSTargets: allBridgeJSTargets, + remainingArguments: remainingArguments + ) } } private func runSingleTarget( target: SwiftSourceModuleTarget, + bridgeJSTargets: [String: SwiftSourceModuleTarget], remainingArguments: [String] ) throws { printStderr("Generating bridge code for \(target.name)...") @@ -126,6 +160,25 @@ extension BridgeJSCommandPlugin.Context { ]) } + for dependency in target.recursiveTargetDependencies { + guard let dependencyTarget = bridgeJSTargets[dependency.name] else { continue } + let dependencySkeletonPath = dependencyTarget.directoryURL + .appending(path: "Generated/JavaScript/BridgeJS.json") + guard FileManager.default.fileExists(atPath: dependencySkeletonPath.path) else { + throw BridgeJSCommandPluginError( + """ + Dependency '\(dependencyTarget.name)' is configured for BridgeJS, but its AOT skeleton has not been generated yet. \ + Run `swift package bridge-js --target \(dependencyTarget.name)` to generate it first, \ + or run without `--target` to process in dependency order. + """ + ) + } + generateArguments.append(contentsOf: [ + "--dependency-skeleton", + "\(dependencyTarget.name)=\(dependencySkeletonPath.path)", + ]) + } + generateArguments.append( contentsOf: target.sourceFiles.filter { !$0.url.path.hasPrefix(generatedDirectory.path + "/") @@ -162,6 +215,14 @@ private func printStderr(_ message: String) { fputs(message + "\n", stderr) } +struct BridgeJSCommandPluginError: Error, CustomStringConvertible { + let description: String + + init(_ message: String) { + self.description = message + } +} + extension SwiftSourceModuleTarget { func hasDependency(named name: String) -> Bool { return dependencies.contains(where: { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift index f3ed97ba3..45cfb73f1 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift @@ -21,7 +21,10 @@ public struct ClosureCodegen { return "(\(closureParams))\(swiftEffects) -> \(swiftReturnType)" } - func renderClosureHelpers(_ signature: ClosureSignature) throws -> [DeclSyntax] { + func renderClosureHelpers( + _ signature: ClosureSignature, + accessLevel: BridgeJSAccessLevel = .internal + ) throws -> [DeclSyntax] { let mangledName = signature.mangleName let helperName = "_BJS_Closure_\(mangledName)" let swiftClosureType = swiftClosureType(for: signature) @@ -99,9 +102,10 @@ public struct ClosureCodegen { let helperEnumDecl: DeclSyntax = "\(raw: helperEnumDeclPrinter.lines.joined(separator: "\n"))" + let initAccessModifier = accessLevel.modifierKeyword.map { "\($0) " } ?? "" let typedClosureExtension: DeclSyntax = """ extension JSTypedClosure where Signature == \(raw: swiftClosureType) { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping \(raw: swiftClosureType)) { + \(raw: initAccessModifier)init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping \(raw: swiftClosureType)) { self.init( makeClosure: \(raw: externABIName), body: body, @@ -192,12 +196,13 @@ public struct ClosureCodegen { let collector = ClosureSignatureCollectorVisitor(moduleName: skeleton.moduleName) var walker = BridgeSkeletonWalker(visitor: collector) walker.walk(skeleton) - let closureSignatures = walker.visitor.signatures - guard !closureSignatures.isEmpty else { return nil } + let signatureAccessLevels = walker.visitor.signatureAccessLevels + guard !signatureAccessLevels.isEmpty else { return nil } var decls: [DeclSyntax] = [] - for signature in closureSignatures.sorted(by: { $0.mangleName < $1.mangleName }) { - decls.append(contentsOf: try renderClosureHelpers(signature)) + for signature in signatureAccessLevels.keys.sorted(by: { $0.mangleName < $1.mangleName }) { + let accessLevel = signatureAccessLevels[signature] ?? .internal + decls.append(contentsOf: try renderClosureHelpers(signature, accessLevel: accessLevel)) decls.append(try renderClosureInvokeHandler(signature)) } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index b649b244d..90c572b9d 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -90,11 +90,77 @@ public class ExportSwift { decls.append(contentsOf: try renderSingleExportedClass(klass: klass)) } } + + try withSpan("Render Async Promise Helpers") { [self] in + let asyncResolveTypes = skeleton.asyncPromiseResolveReturnTypes + if !asyncResolveTypes.isEmpty { + decls.append(contentsOf: try renderPromiseRejectHelper()) + for type in asyncResolveTypes { + decls.append(contentsOf: try renderPromiseResolveHelper(type)) + } + } + } return withSpan("Format Export Glue") { return decls.map { $0.description }.joined(separator: "\n\n") } } + /// Generates the per-type `Promise_resolve_` settlement helper. + private func renderPromiseResolveHelper(_ type: BridgeType) throws -> [DeclSyntax] { + try renderPromiseSettleHelper( + functionName: "Promise_resolve_\(type.mangleTypeName)", + externName: "promise_resolve_\(moduleName)_\(type.mangleTypeName)", + valueType: type + ) + } + + /// Generates the shared `Promise_reject` settlement helper. + private func renderPromiseRejectHelper() throws -> [DeclSyntax] { + try renderPromiseSettleHelper( + functionName: "Promise_reject", + externName: "promise_reject_\(moduleName)", + valueType: .jsValue + ) + } + + /// Generates a `@JSFunction func (_ promise: JSObject, _ value: T)` and its + /// glue, lowering `value` through the standard imported-parameter ABI. + private func renderPromiseSettleHelper( + functionName: String, + externName: String, + valueType: BridgeType + ) throws -> [DeclSyntax] { + let effects = Effects(isAsync: false, isThrows: true) + // `Void` can't cross the bridge as a parameter, so the void helper takes only the promise. + var parameters = [Parameter(label: nil, name: "promise", type: .jsObject(nil))] + if valueType != .void { + parameters.append(Parameter(label: nil, name: "value", type: valueType)) + } + let builder = try ImportTS.CallJSEmission( + moduleName: "bjs", + abiName: externName, + effects: effects, + returnType: .void, + context: .importTS + ) + for parameter in parameters { + try builder.lowerParameter(param: parameter) + } + try builder.call() + try builder.liftReturnValue() + + let valueParam = valueType == .void ? "" : ", _ value: \(valueType.swiftType)" + let macroDecl: DeclSyntax = + "@JSFunction func \(raw: functionName)(_ promise: JSObject\(raw: valueParam)) throws(JSException)" + let glueDecl = builder.renderThunkDecl( + name: "_$\(functionName)", + parameters: parameters, + returnType: .void, + effects: effects + ) + return [macroDecl, builder.renderImportDecl(), glueDecl] + } + class ExportedThunkBuilder { var body: [CodeBlockItemSyntax] = [] var liftedParameterExprs: [ExprSyntax] = [] @@ -104,8 +170,22 @@ public class ExportSwift { var externDecls: [DeclSyntax] = [] let effects: Effects - init(effects: Effects) { + /// The async return type settled through `_bjs_makePromise`'s `Promise_resolve_` + /// helper. Set for every `async` thunk. + var asyncResolveReturnType: BridgeType? + + /// Stack-using parameter lifts hoisted ahead of the deferred async closure. + var asyncHoistedBindings: [CodeBlockItemSyntax] = [] + + init(effects: Effects, returnType: BridgeType) throws { self.effects = effects + guard effects.isAsync else { return } + guard returnType.isAsyncResolvable else { + throw BridgeJSCoreError( + "Returning '\(returnType.swiftType)' from an async exported function is not yet supported" + ) + } + self.asyncResolveReturnType = returnType } private func append(_ item: CodeBlockItemSyntax) { @@ -200,7 +280,7 @@ public class ExportSwift { } if effects.isAsync, returnType != .void { - return CodeBlockItemSyntax(item: .init(StmtSyntax("return \(raw: callExpr).jsValue"))) + return CodeBlockItemSyntax(item: .init(StmtSyntax("return \(raw: callExpr)"))) } if returnType == .void { @@ -244,6 +324,22 @@ public class ExportSwift { param.type.isStackUsingParameter ? index : nil } + if effects.isAsync { + // Drain stack parameters before the deferred `Task` or the shared stack is corrupted. + for index in stackParamIndices.reversed() { + let param = parameters[index] + let expr = liftedParameterExprs[index] + let varName = "_tmp_\(param.name)" + var binding: CodeBlockItemSyntax = "let \(raw: varName) = \(expr)" + if !asyncHoistedBindings.isEmpty { + binding = binding.with(\.leadingTrivia, .newline) + } + asyncHoistedBindings.append(binding) + liftedParameterExprs[index] = ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(varName))) + } + return + } + guard stackParamIndices.count > 1 else { return } for index in stackParamIndices.reversed() { @@ -293,8 +389,7 @@ public class ExportSwift { 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. + // The async return value is lowered by the generated `Promise_resolve_*` helper. return } @@ -328,25 +423,49 @@ public class ExportSwift { } } + /// A throwing async body needs an explicit closure type, otherwise Swift infers + /// `throws(any Error)` instead of `throws(JSException)`. + /// See: https://github.com/swiftlang/swift/issues/76165 + private func asyncThrowsClosureHead(returnSpelling: String?, forcesCapture: Bool) -> String { + guard effects.isThrows else { return "" } + let returns = returnSpelling.map { " -> \($0)" } ?? "" + let capture = forcesCapture ? "[__bjs_capture] " : "" + return " \(capture)() async throws(JSException)\(returns) in" + } + + /// A captureless throwing async body closure lowers via `thin_to_thick_function`, + /// which miscompiles typed-error calls on wasm32. Forcing a capture that the body + /// reads turns the closure into a partial apply with a context, avoiding the + /// broken convention. An unread capture list entry is dropped by capture analysis, + /// so the body must also read the captured value. + /// See: https://github.com/swiftlang/swift/issues/89320 + private var asyncThrowsBodyForcesCapture: Bool { + effects.isThrows && abiParameterSignatures.isEmpty && asyncHoistedBindings.isEmpty + } + func render(abiName: String) -> DeclSyntax { let body: CodeBlockItemListSyntax - if effects.isAsync { - // Explicit closure type annotation needed when throws is present - // so Swift infers throws(JSException) instead of throws(any Error) - // See: https://github.com/swiftlang/swift/issues/76165 - let closureHead: String - if effects.isThrows { - let hasReturn = self.body.contains { $0.description.contains("return ") } - let ret = hasReturn ? " -> JSValue" : "" - closureHead = " () async throws(JSException)\(ret) in" - } else { - closureHead = "" + if effects.isAsync, let resolveType = asyncResolveReturnType { + let resolveName = "Promise_resolve_\(resolveType.mangleTypeName)" + let forcesCapture = asyncThrowsBodyForcesCapture + let closureHead = asyncThrowsClosureHead( + returnSpelling: resolveType.swiftType, + forcesCapture: forcesCapture + ) + var hoistedBindings = asyncHoistedBindings + var bodyItems = self.body + if forcesCapture { + hoistedBindings.append("let __bjs_capture = 0") + if !bodyItems.isEmpty { + bodyItems[0] = bodyItems[0].with(\.leadingTrivia, .newline) + } + bodyItems.insert("_ = __bjs_capture", at: 0) } body = """ - let ret = JSPromise.async {\(raw: closureHead) - \(CodeBlockItemListSyntax(self.body)) - }.jsObject - return ret.bridgeJSLowerReturn() + \(CodeBlockItemListSyntax(hoistedBindings)) + return _bjs_makePromise(resolve: \(raw: resolveName), reject: Promise_reject) {\(raw: closureHead) + \(CodeBlockItemListSyntax(bodyItems)) + } """ } else if effects.isThrows { body = """ @@ -358,7 +477,7 @@ public class ExportSwift { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -457,7 +576,10 @@ public class ExportSwift { let className = context.className let isStatic = context.isStatic - let getterBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic)) + let getterBuilder = try ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic), + returnType: property.type + ) if !isStatic { try getterBuilder.liftParameter( @@ -476,8 +598,9 @@ public class ExportSwift { // Generate property setter if not readonly if !property.isReadonly { - let setterBuilder = ExportedThunkBuilder( - effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic) + let setterBuilder = try ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic), + returnType: .void ) // Lift parameters based on property type @@ -507,7 +630,7 @@ public class ExportSwift { } func renderSingleExportedFunction(function: ExportedFunction) throws -> DeclSyntax { - let builder = ExportedThunkBuilder(effects: function.effects) + let builder = try ExportedThunkBuilder(effects: function.effects, returnType: function.returnType) for param in function.parameters { try builder.liftParameter(param: param) } @@ -536,7 +659,7 @@ public class ExportSwift { callName: String, returnType: BridgeType ) throws -> DeclSyntax { - let builder = ExportedThunkBuilder(effects: constructor.effects) + let builder = try ExportedThunkBuilder(effects: constructor.effects, returnType: returnType) for param in constructor.parameters { try builder.liftParameter(param: param) } @@ -550,7 +673,7 @@ public class ExportSwift { ownerTypeName: String, instanceSelfType: BridgeType ) throws -> DeclSyntax { - let builder = ExportedThunkBuilder(effects: method.effects) + let builder = try ExportedThunkBuilder(effects: method.effects, returnType: method.returnType) if !method.effects.isStatic { try builder.liftParameter(param: Parameter(label: nil, name: "_self", type: instanceSelfType)) } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExternalModuleIndex.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExternalModuleIndex.swift new file mode 100644 index 000000000..91fd4388a --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExternalModuleIndex.swift @@ -0,0 +1,93 @@ +#if canImport(BridgeJSSkeleton) +import BridgeJSSkeleton +#endif + +/// Index of `@JS` types from dependencies. +public struct ExternalModuleIndex { + public struct ExternalType: Equatable { + public let moduleName: String + public let bridgeType: BridgeType + } + + public enum LookupResult: Equatable { + case unique(ExternalType) + case ambiguous(candidates: [ExternalType]) + } + + public static var empty: ExternalModuleIndex { + ExternalModuleIndex(dependencies: []) + } + + private let byModuleAndPath: [String: [String: ExternalType]] + private let byPath: [String: [ExternalType]] + + public var moduleNames: Set { Set(byModuleAndPath.keys) } + + public init(dependencies: [(moduleName: String, skeleton: BridgeJSSkeleton)]) { + var entriesByModule: [String: [String: ExternalType]] = [:] + var entriesByDotPath: [String: [ExternalType]] = [:] + + for (moduleName, skeleton) in dependencies { + guard let exported = skeleton.exported else { continue } + var moduleEntries = entriesByModule[moduleName] ?? [:] + + func register(dotPath: String, bridgeType: BridgeType) { + let externalType = ExternalType(moduleName: moduleName, bridgeType: bridgeType) + if moduleEntries[dotPath] == nil { + moduleEntries[dotPath] = externalType + entriesByDotPath[dotPath, default: []].append(externalType) + } + } + + for klass in exported.classes { + register(dotPath: klass.swiftCallName, bridgeType: .swiftHeapObject(klass.swiftCallName)) + } + for structDef in exported.structs { + register(dotPath: structDef.swiftCallName, bridgeType: .swiftStruct(structDef.swiftCallName)) + } + for enumDef in exported.enums { + let bridgeType: BridgeType + switch enumDef.enumType { + case .simple: + bridgeType = .caseEnum(enumDef.swiftCallName) + case .rawValue: + guard let rawType = enumDef.rawType else { continue } + bridgeType = .rawValueEnum(enumDef.swiftCallName, rawType) + case .associatedValue: + bridgeType = .associatedValueEnum(enumDef.swiftCallName) + case .namespace: + bridgeType = .namespaceEnum(enumDef.swiftCallName) + } + register(dotPath: enumDef.swiftCallName, bridgeType: bridgeType) + } + for proto in exported.protocols { + register(dotPath: proto.name, bridgeType: .swiftProtocol(proto.name)) + } + + entriesByModule[moduleName] = moduleEntries + } + + self.byModuleAndPath = entriesByModule + self.byPath = entriesByDotPath + } + + public var isEmpty: Bool { byModuleAndPath.isEmpty } + + public func isKnownModule(_ name: String) -> Bool { + byModuleAndPath[name] != nil + } + + public func lookup(dotPath: String) -> LookupResult? { + guard let matches = byPath[dotPath], !matches.isEmpty else { return nil } + if matches.count == 1 { + return .unique(matches[0]) + } + return .ambiguous(candidates: matches) + } + + public func lookup(dotPath: String, module moduleName: String) -> LookupResult? { + guard let moduleEntries = byModuleAndPath[moduleName] else { return nil } + guard let externalType = moduleEntries[dotPath] else { return nil } + return .unique(externalType) + } +} diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index 536c7eeab..a6a73b8f7 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -128,7 +128,9 @@ public struct ImportTS { self.returnType = returnType self.context = context let liftingInfo = try returnType.liftingReturnInfo(context: context) - if effects.isAsync || returnType == .void || returnType.usesSideChannelForOptionalReturn() { + if effects.isAsync || returnType == .void || returnType.usesSideChannelForOptionalReturn() + || liftingInfo.valueToLift == nil + { abiReturnType = nil } else { abiReturnType = liftingInfo.valueToLift @@ -926,12 +928,7 @@ extension BridgeType { return LoweringParameterInfo(loweredParameters: [("objectId", .i32)]) } case .caseEnum: - switch context { - case .importTS: - throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .exportSwift: - return LoweringParameterInfo(loweredParameters: [("value", .i32)]) - } + return LoweringParameterInfo(loweredParameters: [("value", .i32)]) case .rawValueEnum(_, let rawType): if rawType == .string { return .string @@ -939,12 +936,7 @@ extension BridgeType { 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)]) - } + return LoweringParameterInfo(loweredParameters: [("caseId", .i32)]) case .swiftStruct: switch context { case .importTS: @@ -955,6 +947,10 @@ extension BridgeType { } case .namespaceEnum: throw BridgeJSCoreError("Namespace enums cannot be used as parameters") + case .nullable(.swiftStruct, _) where context == .importTS: + // Optional `@JS struct`s bridge through the stack (isSome discriminator + fields), + // like optional arrays/dictionaries, rather than the non-optional object-id ABI. + return LoweringParameterInfo(loweredParameters: [("isSome", .i32)]) case .nullable(let wrappedType, _): let wrappedInfo = try wrappedType.loweringParameterInfo(context: context) var params = [("isSome", WasmCoreType.i32)] @@ -1005,22 +1001,12 @@ extension BridgeType { return LiftingReturnInfo(valueToLift: .i32) } case .caseEnum: - switch context { - case .importTS: - throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .exportSwift: - return LiftingReturnInfo(valueToLift: .i32) - } + 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) - } + return LiftingReturnInfo(valueToLift: .i32) case .swiftStruct: switch context { case .importTS: @@ -1032,6 +1018,14 @@ extension BridgeType { case .namespaceEnum: throw BridgeJSCoreError("Namespace enums cannot be used as return values") case .nullable(let wrappedType, _): + // jsObject and `@JS struct` use the stack ABI for optionals — the thunk returns + // void and the value (plus isSome discriminator) flows through the stacks. + if case .jsObject = wrappedType { + return LiftingReturnInfo(valueToLift: nil) + } + if case .swiftStruct = wrappedType, context == .importTS { + return LiftingReturnInfo(valueToLift: nil) + } let wrappedInfo = try wrappedType.liftingReturnInfo(context: context) return LiftingReturnInfo(valueToLift: wrappedInfo.valueToLift) case .array, .dictionary: diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift index 3d8f417e3..57b9a57df 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift @@ -18,20 +18,38 @@ public final class SwiftToSkeleton { public let exposeToGlobal: Bool public let identityMode: String? - private var sourceFiles: [(sourceFile: SourceFileSyntax, inputFilePath: String)] = [] let typeDeclResolver: TypeDeclResolver + let externalModuleIndex: ExternalModuleIndex - public init(progress: ProgressReporting, moduleName: String, exposeToGlobal: Bool, identityMode: String? = nil) { + private var sourceFiles: [(sourceFile: SourceFileSyntax, inputFilePath: String)] = [] + private var usedExternalModules = Set() + + public init( + progress: ProgressReporting, + moduleName: String, + exposeToGlobal: Bool, + externalModuleIndex: ExternalModuleIndex, + identityMode: String? = nil + ) { self.progress = progress self.moduleName = moduleName self.exposeToGlobal = exposeToGlobal self.identityMode = identityMode self.typeDeclResolver = TypeDeclResolver() + self.externalModuleIndex = externalModuleIndex // Index known types provided by JavaScriptKit self.typeDeclResolver.addSourceFile( """ @JSClass struct JSPromise {} + @JSClass struct JSInt8Array {} + @JSClass struct JSUint8Array {} + @JSClass struct JSInt16Array {} + @JSClass struct JSUint16Array {} + @JSClass struct JSInt32Array {} + @JSClass struct JSUint32Array {} + @JSClass struct JSFloat32Array {} + @JSClass struct JSFloat64Array {} """ ) } @@ -110,14 +128,43 @@ public final class SwiftToSkeleton { }() let exportedSkeleton: ExportedSkeleton? = exported.isEmpty ? nil : exported - return BridgeJSSkeleton(moduleName: moduleName, exported: exportedSkeleton, imported: importedSkeleton) + return BridgeJSSkeleton( + moduleName: moduleName, + exported: exportedSkeleton, + imported: importedSkeleton, + usedExternalModules: usedExternalModules.sorted() + ) } + private static let jsTypedArrayTypealiasNames: [String: String] = [ + "Int8": "JSInt8Array", + "UInt8": "JSUint8Array", + "Int16": "JSInt16Array", + "UInt16": "JSUint16Array", + "Int32": "JSInt32Array", + "UInt32": "JSUint32Array", + "Float": "JSFloat32Array", + "Float32": "JSFloat32Array", + "Double": "JSFloat64Array", + "Float64": "JSFloat64Array", + ] + func lookupType(for type: TypeSyntax, errors: inout [DiagnosticError]) -> BridgeType? { if let attributedType = type.as(AttributedTypeSyntax.self) { return lookupType(for: attributedType.baseType, errors: &errors) } + // JSTypedArray + if let identifierType = type.as(IdentifierTypeSyntax.self), + identifierType.name.text == "JSTypedArray", + let genericArgs = identifierType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let elementName = genericArgs.first?.argument.as(IdentifierTypeSyntax.self)?.name.text, + let typealiasName = Self.jsTypedArrayTypealiasNames[elementName] + { + return .jsObject(typealiasName) + } + if let identifierType = type.as(IdentifierTypeSyntax.self), identifierType.name.text == "JSTypedClosure", let genericArgs = identifierType.genericArgumentClause?.arguments, @@ -303,79 +350,130 @@ public final class SwiftToSkeleton { 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 typeDecl = typeDeclResolver.resolve(type) { + 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 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 + 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 } - return false } + if hasAssociatedValues { + return .associatedValueEnum(swiftCallName) + } else { + return .caseEnum(swiftCallName) } - 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") { + 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) } - return .swiftStruct(swiftCallName) + if let actorDecl = typeDecl.as(ActorDeclSyntax.self), actorDecl.attributes.hasAttribute(name: "JSClass") { + return .jsObject(swiftCallName) + } + + return .swiftHeapObject(swiftCallName) } - guard typeDecl.is(ClassDeclSyntax.self) || typeDecl.is(ActorDeclSyntax.self) else { + if let externalType = resolveExternal(for: type, errors: &errors) { + return externalType + } + + errors.append( + DiagnosticError( + node: type, + message: "Unsupported type '\(type.trimmedDescription)'.", + hint: + "Only primitive types, types defined in the same module, and " + + "`@JS` types from dependency targets that apply the BridgeJS plugin are allowed" + ) + ) + return nil + } + + private func resolveExternal(for type: TypeSyntax, errors: inout [DiagnosticError]) -> BridgeType? { + guard + !externalModuleIndex.isEmpty, + var components = typeDeclResolver.qualifiedComponents(from: type) + 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) + var scopedModule: String? = nil + if components.count >= 2, externalModuleIndex.isKnownModule(components[0]) { + scopedModule = components[0] + components.removeFirst() } - if let actorDecl = typeDecl.as(ActorDeclSyntax.self), actorDecl.attributes.hasAttribute(name: "JSClass") { - return .jsObject(swiftCallName) + + let dotPath = components.joined(separator: ".") + let lookupResult: ExternalModuleIndex.LookupResult? + if let moduleName = scopedModule { + lookupResult = externalModuleIndex.lookup(dotPath: dotPath, module: moduleName) + } else { + lookupResult = externalModuleIndex.lookup(dotPath: dotPath) } - return .swiftHeapObject(swiftCallName) + guard let lookupResult else { return nil } + switch lookupResult { + case .unique(let externalType): + usedExternalModules.insert(externalType.moduleName) + return externalType.bridgeType + case .ambiguous(let candidates): + let moduleNames = candidates.map(\.moduleName).sorted().joined(separator: ", ") + errors.append( + DiagnosticError( + node: type, + message: "ambiguous use of '\(type.trimmedDescription)'", + hint: + "'\(dotPath)' is exported by multiple dependency modules: \(moduleNames). " + + "Qualify with a module name (e.g. '.\(dotPath)') to disambiguate." + ) + ) + return nil + } } fileprivate static func parseUnsafePointerType(_ type: TypeSyntax) -> UnsafePointerType? { @@ -438,6 +536,14 @@ public final class SwiftToSkeleton { enumDecl.attributes.hasJSAttribute() { swiftPath.insert(enumDecl.name.text, at: 0) + } else if let structDecl = parent.as(StructDeclSyntax.self), + structDecl.attributes.hasJSAttribute() + { + swiftPath.insert(structDecl.name.text, at: 0) + } else if let classDecl = parent.as(ClassDeclSyntax.self), + classDecl.attributes.hasJSAttribute() + { + swiftPath.insert(classDecl.name.text, at: 0) } currentNode = parent.parent } @@ -582,6 +688,7 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { var state: State { return stateStack.current } + let parent: SwiftToSkeleton init(parent: SwiftToSkeleton) { @@ -1387,6 +1494,10 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { guard namespaceResult.isValid else { return .skipChildren } + let effectiveNamespace = effectiveNamespace( + resolvedNamespace: namespaceResult.namespace, + parentTypeNamespace: computeParentTypeNamespace(for: node) + ) let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: node, itemName: name) let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( for: node, @@ -1400,10 +1511,10 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { constructor: nil, methods: [], properties: [], - namespace: namespaceResult.namespace, + namespace: effectiveNamespace, identityMode: classIdentityMode ) - let uniqueKey = makeKey(name: name, namespace: namespaceResult.namespace) + let uniqueKey = makeKey(name: name, namespace: effectiveNamespace) stateStack.push(state: .classBody(name: name, key: uniqueKey)) exportedClassByName[uniqueKey] = exportedClass @@ -1492,6 +1603,10 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { guard namespaceResult.isValid else { return .skipChildren } + let effectiveNamespace = effectiveNamespace( + resolvedNamespace: namespaceResult.namespace, + parentTypeNamespace: computeParentTypeNamespace(for: node) + ) let emitStyle = extractEnumStyle(from: jsAttribute) ?? .const let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: node, itemName: name) let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( @@ -1500,7 +1615,7 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { ) let tsFullPath: String - if let namespace = namespaceResult.namespace, !namespace.isEmpty { + if let namespace = effectiveNamespace, !namespace.isEmpty { tsFullPath = namespace.joined(separator: ".") + "." + name } else { tsFullPath = name @@ -1514,13 +1629,13 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { explicitAccessControl: explicitAccessControl, cases: [], // Will be populated in visit(EnumCaseDeclSyntax) rawType: SwiftEnumRawType(rawType), - namespace: namespaceResult.namespace, + namespace: effectiveNamespace, emitStyle: emitStyle, staticMethods: [], staticProperties: [] ) - let enumUniqueKey = makeKey(name: name, namespace: namespaceResult.namespace) + let enumUniqueKey = makeKey(name: name, namespace: effectiveNamespace) exportedEnumByName[enumUniqueKey] = exportedEnum exportedEnumNames.append(enumUniqueKey) @@ -1619,18 +1734,22 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { guard namespaceResult.isValid else { return .skipChildren } + let effectiveNamespace = effectiveNamespace( + resolvedNamespace: namespaceResult.namespace, + parentTypeNamespace: computeParentTypeNamespace(for: node) + ) _ = computeExplicitAtLeastInternalAccessControl( for: node, message: "Protocol visibility must be at least internal" ) - let protocolUniqueKey = makeKey(name: name, namespace: namespaceResult.namespace) + let protocolUniqueKey = makeKey(name: name, namespace: effectiveNamespace) exportedProtocolByName[protocolUniqueKey] = ExportedProtocol( name: name, methods: [], properties: [], - namespace: namespaceResult.namespace + namespace: effectiveNamespace ) stateStack.push(state: .protocolBody(name: name, key: protocolUniqueKey)) @@ -1641,7 +1760,7 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { if let exportedFunction = visitProtocolMethod( node: funcDecl, protocolName: name, - namespace: namespaceResult.namespace + namespace: effectiveNamespace ) { methods.append(exportedFunction) } @@ -1654,7 +1773,7 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { name: name, methods: methods, properties: exportedProtocolByName[protocolUniqueKey]?.properties ?? [], - namespace: namespaceResult.namespace + namespace: effectiveNamespace ) exportedProtocolByName[protocolUniqueKey] = exportedProtocol @@ -1676,6 +1795,10 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { guard namespaceResult.isValid else { return .skipChildren } + let effectiveNamespace = effectiveNamespace( + resolvedNamespace: namespaceResult.namespace, + parentTypeNamespace: computeParentTypeNamespace(for: node) + ) let swiftCallName = SwiftToSkeleton.computeSwiftCallName(for: node, itemName: name) let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( for: node, @@ -1725,7 +1848,7 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { type: fieldType, isReadonly: true, isStatic: false, - namespace: namespaceResult.namespace, + namespace: effectiveNamespace, staticContext: nil ) properties.append(property) @@ -1733,14 +1856,14 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { } } - let structUniqueKey = makeKey(name: name, namespace: namespaceResult.namespace) + let structUniqueKey = makeKey(name: name, namespace: effectiveNamespace) let exportedStruct = ExportedStruct( name: name, swiftCallName: swiftCallName, explicitAccessControl: explicitAccessControl, properties: properties, methods: [], - namespace: namespaceResult.namespace + namespace: effectiveNamespace ) exportedStructByName[structUniqueKey] = exportedStruct @@ -1752,9 +1875,44 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { } override func visitPost(_ node: StructDeclSyntax) { - if case .structBody(_, _) = stateStack.current { + if case .structBody(_, let structKey) = stateStack.current { stateStack.pop() + validateStructInitOrder(node: node, structKey: structKey) + } + } + + private func validateStructInitOrder(node: StructDeclSyntax, structKey: String) { + guard let exportedStruct = exportedStructByName[structKey], + let constructor = exportedStruct.constructor + else { + // No explicit @JS init — synthesized memberwise init is assumed, + // which always matches declaration order. + return } + + let instanceProps = exportedStruct.properties.filter { !$0.isStatic } + let expectedLabels = instanceProps.map(\.name) + let actualLabels = constructor.parameters.compactMap(\.label) + + guard expectedLabels != actualLabels else { return } + + // Find the @JS init node so we can point the diagnostic at it. + let initNode: (any SyntaxProtocol) = + node.memberBlock.members + .compactMap { $0.decl.as(InitializerDeclSyntax.self) } + .first(where: { $0.attributes.hasJSAttribute() }) + ?? node + + let expectedOrder = expectedLabels.joined(separator: ", ") + let actualOrder = actualLabels.joined(separator: ", ") + + diagnose( + node: initNode, + message: + "@JS struct initializer parameters must match stored properties in declaration order. Expected (\(expectedOrder)), got (\(actualOrder))", + hint: + "Reorder the initializer parameters to match the property declaration order, or remove the @JS init to use the synthesized memberwise initializer" + ) } private func visitProtocolMethod( @@ -1969,6 +2127,34 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { return namespace.isEmpty ? nil : namespace } + private func computeParentTypeNamespace(for node: some SyntaxProtocol) -> [String]? { + var path: [String] = [] + var currentNode: Syntax? = node.parent + + while let parent = currentNode { + if let structDecl = parent.as(StructDeclSyntax.self), + structDecl.attributes.hasJSAttribute() + { + path.insert(structDecl.name.text, at: 0) + } else if let classDecl = parent.as(ClassDeclSyntax.self), + classDecl.attributes.hasJSAttribute() + { + path.insert(classDecl.name.text, at: 0) + } + currentNode = parent.parent + } + + return path.isEmpty ? nil : path + } + + private func effectiveNamespace( + resolvedNamespace: [String]?, + parentTypeNamespace: [String]? + ) -> [String]? { + let combined = (parentTypeNamespace ?? []) + (resolvedNamespace ?? []) + return combined.isEmpty ? nil : combined + } + /// Requires the node to have at least internal access control. private func computeExplicitAtLeastInternalAccessControl( for node: some WithModifiersSyntax, @@ -2056,6 +2242,7 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { let name: String let jsName: String? let from: JSImportFrom? + let accessLevel: BridgeJSAccessLevel var constructor: ImportedConstructorSkeleton? var methods: [ImportedFunctionSkeleton] var staticMethods: [ImportedFunctionSkeleton] @@ -2271,6 +2458,7 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { name: typeName, jsName: nil, from: nil, + accessLevel: .internal, constructor: nil, methods: [], staticMethods: [], @@ -2279,12 +2467,18 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { ) } - private func enterJSClass(_ typeName: String, jsName: String?, from: JSImportFrom?) { + private func enterJSClass( + _ typeName: String, + jsName: String?, + from: JSImportFrom?, + accessLevel: BridgeJSAccessLevel + ) { stateStack.append(.jsClassBody(name: typeName)) currentType = CurrentType( name: typeName, jsName: jsName, from: from, + accessLevel: accessLevel, constructor: nil, methods: [], staticMethods: [], @@ -2305,7 +2499,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { staticMethods: type.staticMethods, getters: type.getters, setters: type.setters, - documentation: nil + documentation: nil, + accessLevel: type.accessLevel ) ) currentType = nil @@ -2318,7 +2513,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { 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) + let accessLevel = Self.bridgeAccessLevel(from: node.modifiers) + enterJSClass(node.name.text, jsName: jsName, from: from, accessLevel: accessLevel) } return .visitChildren } @@ -2334,7 +2530,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { 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) + let accessLevel = Self.bridgeAccessLevel(from: node.modifiers) + enterJSClass(node.name.text, jsName: jsName, from: from, accessLevel: accessLevel) } return .visitChildren } @@ -2499,8 +2696,14 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { else { return nil } + // Initializers without an explicit modifier inherit access from the + // enclosing `@JSClass` (the user's example pattern: `public init(...)` + // inside `public struct JSDocument`). + let parentLevel = currentType?.accessLevel ?? .internal + let accessLevel = Self.bridgeAccessLevel(from: initializer.modifiers, default: parentLevel) return ImportedConstructorSkeleton( - parameters: parseParameters(from: initializer.signature.parameterClause) + parameters: parseParameters(from: initializer.signature.parameterClause), + accessLevel: accessLevel ) } @@ -2533,6 +2736,7 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { } else { returnType = .void } + let accessLevel = Self.bridgeAccessLevel(from: node.modifiers) return ImportedFunctionSkeleton( name: name, jsName: jsName, @@ -2540,7 +2744,8 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { parameters: parameters, returnType: returnType, effects: effects, - documentation: nil + documentation: nil, + accessLevel: accessLevel ) } @@ -2572,13 +2777,15 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { let propertyName = SwiftToSkeleton.normalizeIdentifier(identifier.identifier.text) let jsName = AttributeChecker.extractJSName(from: jsGetter) let from = AttributeChecker.extractJSImportFrom(from: jsGetter) + let accessLevel = Self.bridgeAccessLevel(from: node.modifiers) return ImportedGetterSkeleton( name: propertyName, jsName: jsName, from: from, type: propertyType, documentation: nil, - functionName: nil + functionName: nil, + accessLevel: accessLevel ) } @@ -2601,12 +2808,14 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { return nil } + let accessLevel = Self.bridgeAccessLevel(from: node.modifiers) return ImportedSetterSkeleton( name: propertyName, jsName: validation.jsName, type: validation.valueType, documentation: nil, - functionName: "\(functionBaseName)_set" + functionName: "\(functionBaseName)_set", + accessLevel: accessLevel ) } @@ -2652,6 +2861,31 @@ private final class ImportSwiftMacrosAPICollector: SyntaxAnyVisitor { modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) } } + + /// Maps Swift's declaration modifiers to a `BridgeJSAccessLevel` for + /// recording on imported skeleton entries. Falls back to `default` when no + /// access modifier is present (typically `.internal`, but the caller may + /// override — e.g. an `init` inheriting from its enclosing `@JSClass`). + /// `private`/`fileprivate` are mapped to the fallback because the macros + /// already reject those access levels for `@JS*` declarations. + fileprivate static func bridgeAccessLevel( + from modifiers: DeclModifierListSyntax, + default fallback: BridgeJSAccessLevel = .internal + ) -> BridgeJSAccessLevel { + for modifier in modifiers { + switch modifier.name.tokenKind { + case .keyword(.public), .keyword(.open): + return .public + case .keyword(.package): + return .package + case .keyword(.internal): + return .internal + default: + continue + } + } + return fallback + } } extension GenericArgumentListSyntax { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift index 975c0c9dc..ec04421aa 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift @@ -161,7 +161,7 @@ class TypeDeclResolver { return nil } - private func qualifiedComponents(from type: TypeSyntax) -> QualifiedName? { + 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] diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 64a0d2394..9a8442435 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -232,7 +232,9 @@ public struct BridgeJSLink { 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 { + data.topLevelDtsTypeLines.append(contentsOf: dtsType) + } if structDefinition.namespace == nil && (!jsStruct.isEmpty || !dtsExportEntry.isEmpty) { structExportEntries.append((js: jsStruct, dts: dtsExportEntry)) @@ -345,6 +347,7 @@ public struct BridgeJSLink { "let \(JSGlueVariableScope.reservedF32Stack) = [];", "let \(JSGlueVariableScope.reservedF64Stack) = [];", "let \(JSGlueVariableScope.reservedPointerStack) = [];", + "let \(JSGlueVariableScope.reservedTaStack) = [];", "const \(JSGlueVariableScope.reservedEnumHelpers) = {};", "const \(JSGlueVariableScope.reservedStructHelpers) = {};", "", @@ -353,6 +356,40 @@ public struct BridgeJSLink { ] } + /// JS const (in the import glue scope) holding the `Symbol` under which a promise's + /// resolve/reject settlers are stashed. + private static let promiseSettlersSymbol = "__bjs_promiseSettlers" + + /// Renders a `bjs[...]` settlement handler that lifts `(promise, value)` and calls the + /// promise's stashed `resolve` / `reject` settler. + private func renderPromiseSettleHandler( + externName: String, + valueType: BridgeType, + settle: String, + into printer: CodeFragmentPrinter + ) throws { + let builder = ImportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: true), + returnType: .void, + intrinsicRegistry: intrinsicRegistry + ) + try builder.liftParameter(param: Parameter(label: nil, name: "promise", type: .jsObject(nil))) + // `Void` can't cross the bridge as a parameter, so the void resolve settles with `undefined`. + let valueArg: String + if valueType == .void { + valueArg = "" + } else { + try builder.liftParameter(param: Parameter(label: nil, name: "value", type: valueType)) + valueArg = builder.parameterForwardings[1] + } + builder.body.write( + "\(builder.parameterForwardings[0])[\(Self.promiseSettlersSymbol)].\(settle)(\(valueArg));" + ) + var lines = builder.renderFunction(name: nil) + lines[0] = "bjs[\"\(externName)\"] = \(lines[0])" + printer.write(lines: lines) + } + private func generateAddImports(needsImportsObject: Bool) throws -> CodeFragmentPrinter { let printer = CodeFragmentPrinter() let allStructs = skeletons.compactMap { $0.exported?.structs }.flatMap { $0 } @@ -487,12 +524,27 @@ public struct BridgeJSLink { printer.write("return \(JSGlueVariableScope.reservedI64Stack).pop();") } printer.write("}") + // Typed array constructors indexed by kind (must match _BridgedNumericArrayKind) + printer.write( + "const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];" + ) + printer.write("bjs[\"swift_js_push_typed_array\"] = function(kind, ptr, count) {") + printer.indent { + printer.write("const Ctor = taCtors[kind];") + printer.write("const byteLen = count * Ctor.BYTES_PER_ELEMENT;") + // slice() copies the bytes into a new ArrayBuffer that is properly aligned + printer.write( + "const copy = \(JSGlueVariableScope.reservedMemory).buffer.slice(ptr, ptr + byteLen);" + ) + printer.write("\(JSGlueVariableScope.reservedTaStack).push(Array.from(new Ctor(copy)));") + } + printer.write("}") if !allStructs.isEmpty { for structDef in allStructs { printer.write("bjs[\"swift_js_struct_lower_\(structDef.abiName)\"] = function(objectId) {") printer.indent { printer.write( - "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));" + "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.abiName).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));" ) } printer.write("}") @@ -500,7 +552,7 @@ public struct BridgeJSLink { printer.write("bjs[\"swift_js_struct_lift_\(structDef.abiName)\"] = function() {") printer.indent { printer.write( - "const value = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lift();" + "const value = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.abiName).lift();" ) printer.write("return \(JSGlueVariableScope.reservedSwift).memory.retain(value);") } @@ -508,6 +560,39 @@ public struct BridgeJSLink { } } + // Always provided: the runtime's `_bjs_makePromise` imports it unconditionally. + // The settlers are stored under a Symbol to avoid clashing with promise fields. + printer.write("const \(Self.promiseSettlersSymbol) = Symbol(\"JavaScriptKit.promiseSettlers\");") + printer.write("bjs[\"swift_js_make_promise\"] = function() {") + printer.indent { + printer.write("let resolve, reject;") + printer.write("const promise = new Promise((res, rej) => { resolve = res; reject = rej; });") + printer.write("promise[\(Self.promiseSettlersSymbol)] = { resolve, reject };") + printer.write( + "return \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retain(promise);" + ) + } + printer.write("}") + for skeleton in skeletons { + guard let exported = skeleton.exported else { continue } + let asyncResolveTypes = exported.asyncPromiseResolveReturnTypes + guard !asyncResolveTypes.isEmpty else { continue } + for type in asyncResolveTypes { + try renderPromiseSettleHandler( + externName: "promise_resolve_\(skeleton.moduleName)_\(type.mangleTypeName)", + valueType: type, + settle: "resolve", + into: printer + ) + } + try renderPromiseSettleHandler( + externName: "promise_reject_\(skeleton.moduleName)", + valueType: .jsValue, + settle: "reject", + into: printer + ) + } + printer.write("bjs[\"swift_js_return_optional_bool\"] = function(isSome, value) {") printer.indent { printer.write("if (isSome === 0) {") @@ -1005,7 +1090,7 @@ public struct BridgeJSLink { let structScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) let fragment = IntrinsicJSFragment.structHelper(structDefinition: structDef, allStructs: allStructs) _ = try fragment.printCode( - [structDef.name], + [structDef.abiName], IntrinsicJSFragment.PrintCodeContext( scope: structScope, printer: structPrinter, @@ -1159,10 +1244,10 @@ public struct BridgeJSLink { for skeleton in skeletons.compactMap(\.exported) { for structDef in skeleton.structs { printer.write( - "const \(structDef.name)Helpers = __bjs_create\(structDef.name)Helpers();" + "const \(structDef.abiName)Helpers = __bjs_create\(structDef.abiName)Helpers();" ) printer.write( - "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name) = \(structDef.name)Helpers;" + "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.abiName) = \(structDef.abiName)Helpers;" ) printer.nextLine() } @@ -1441,8 +1526,6 @@ public struct BridgeJSLink { } } 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)" @@ -2618,6 +2701,7 @@ extension BridgeJSLink { var functions: [ExportedFunction] = [] var classes: [ExportedClass] = [] var enums: [ExportedEnum] = [] + var structs: [ExportedStruct] = [] var staticProperties: [ExportedProperty] = [] var functionJsLines: [(name: String, lines: [String])] = [] var functionDtsLines: [(name: String, lines: [String])] = [] @@ -2666,6 +2750,14 @@ extension BridgeJSLink { currentNode.content.classes.append(klass) } + for structDef in skeleton.structs where structDef.namespace != nil { + var currentNode = rootNode + for part in structDef.namespace! { + currentNode = currentNode.addChild(part) + } + currentNode.content.structs.append(structDef) + } + for enumDef in skeleton.enums where enumDef.namespace != nil && enumDef.enumType != .namespace { var currentNode = rootNode for part in enumDef.namespace! { @@ -2847,8 +2939,18 @@ extension BridgeJSLink { } } + private func hasExportContent(node: NamespaceNode) -> Bool { + if !node.content.classDtsLines.isEmpty || !node.content.enumDtsLines.isEmpty + || !node.content.functionDtsLines.isEmpty || !node.content.staticProperties.isEmpty + { + return true + } + return node.children.values.contains(where: { hasExportContent(node: $0) }) + } + private func printExportsTypeHierarchy(node: NamespaceNode, printer: CodeFragmentPrinter) { for (childName, childNode) in node.children.sorted(by: { $0.key < $1.key }) { + guard hasExportContent(node: childNode) else { continue } printer.write("\(childName): {") printer.indent { for (_, lines) in childNode.content.classDtsLines.sorted(by: { $0.name < $1.name }) { @@ -2985,8 +3087,8 @@ extension BridgeJSLink { renderTSSignatureCallback: @escaping ([Parameter], BridgeType, Effects) -> String ) { func hasContent(node: NamespaceNode) -> Bool { - // Enums are always included - if !node.content.enums.isEmpty { + // Enums and structs are always included + if !node.content.enums.isEmpty || !node.content.structs.isEmpty { return true } @@ -3166,6 +3268,23 @@ extension BridgeJSLink { } } + // Generate struct interface definitions + let sortedStructs = childNode.content.structs.sorted { $0.name < $1.name } + for structDef in sortedStructs { + let instanceProps = structDef.properties.filter { !$0.isStatic } + printer.write("export interface \(structDef.name) {") + printer.indent { + for property in instanceProps { + let tsType = BridgeJSLink.resolveTypeScriptType( + property.type, + exportedSkeletons: exportedSkeletons + ) + printer.write("\(property.name): \(tsType);") + } + } + printer.write("}") + } + // Only include functions and properties when exposeToGlobal is true if exposeToGlobal { let sortedFunctions = childNode.content.functions.sorted { $0.name < $1.name } @@ -3596,6 +3715,9 @@ extension BridgeType { case .bool: return "boolean" case .jsObject(let name): + if let name, let tsName = Self.jsTypedArrayTSNames[name] { + return tsName + } return name ?? "any" case .jsValue: return "any" @@ -3612,7 +3734,7 @@ extension BridgeType { case .associatedValueEnum(let name): return "\(name)Tag" case .swiftStruct(let name): - return "\(name)Tag" + return name case .namespaceEnum(let name): return name case .swiftProtocol(let name): @@ -3632,12 +3754,27 @@ extension BridgeType { return "Record" } } + + /// Maps JSTypedArray Swift typealias names to their JavaScript TypedArray constructor names. + private static let jsTypedArrayTSNames: [String: String] = [ + "JSInt8Array": "Int8Array", + "JSUint8Array": "Uint8Array", + "JSInt16Array": "Int16Array", + "JSUint16Array": "Uint16Array", + "JSInt32Array": "Int32Array", + "JSUint32Array": "Uint32Array", + "JSFloat32Array": "Float32Array", + "JSFloat64Array": "Float64Array", + ] } extension WasmCoreType { fileprivate var placeholderValue: String { switch self { - case .i32, .i64, .f32, .f64, .pointer: return "0" + // A Wasm `i64` return is a JavaScript `BigInt`, so the error-path placeholder + // must be a BigInt literal rather than a plain number. + case .i64: return "0n" + case .i32, .f32, .f64, .pointer: return "0" } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 599b6df39..ac2144bbc 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -34,6 +34,7 @@ final class JSGlueVariableScope { static let reservedStructHelpers = "structHelpers" static let reservedSwiftClosureRegistry = "swiftClosureRegistry" static let reservedMakeSwiftClosure = "makeClosure" + static let reservedTaStack = "taStack" private let intrinsicRegistry: JSIntrinsicRegistry @@ -63,6 +64,7 @@ final class JSGlueVariableScope { reservedStructHelpers, reservedSwiftClosureRegistry, reservedMakeSwiftClosure, + reservedTaStack, ] init(intrinsicRegistry: JSIntrinsicRegistry) { @@ -667,7 +669,7 @@ struct IntrinsicJSFragment: Sendable { } let innerFragment = - if wrappedType.optionalConvention == .stackABI { + if wrappedType.optionalParameterUsesStackABI { try stackLiftFragment(elementType: wrappedType) } else { try liftParameter(type: wrappedType, context: bridgeContext) @@ -684,7 +686,7 @@ struct IntrinsicJSFragment: Sendable { kind: JSOptionalKind, innerFragment: IntrinsicJSFragment ) -> IntrinsicJSFragment { - let isStackConvention = wrappedType.optionalConvention == .stackABI + let isStackConvention = wrappedType.optionalParameterUsesStackABI let absenceLiteral = kind.absenceLiteral let outerParams: [String] @@ -760,7 +762,7 @@ struct IntrinsicJSFragment: Sendable { } let innerFragment = - if wrappedType.optionalConvention == .stackABI { + if wrappedType.optionalParameterUsesStackABI { try stackLowerFragment(elementType: wrappedType) } else { try lowerParameter(type: wrappedType) @@ -777,7 +779,7 @@ struct IntrinsicJSFragment: Sendable { kind: JSOptionalKind, innerFragment: IntrinsicJSFragment ) throws -> IntrinsicJSFragment { - let isStackConvention = wrappedType.optionalConvention == .stackABI + let isStackConvention = wrappedType.optionalParameterUsesStackABI return IntrinsicJSFragment( parameters: ["value"], @@ -944,7 +946,7 @@ struct IntrinsicJSFragment: Sendable { fullName: String, kind: JSOptionalKind ) -> IntrinsicJSFragment { - let base = fullName.components(separatedBy: ".").last ?? fullName + let base = fullName.replacingOccurrences(of: ".", with: "_") let absenceLiteral = kind.absenceLiteral return IntrinsicJSFragment( parameters: [], @@ -1300,7 +1302,7 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName return .associatedEnumLowerParameter(enumBase: base) case .swiftStruct(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName + let base = fullName.replacingOccurrences(of: ".", with: "_") return swiftStructLowerParameter(structBase: base) case .closure: return IntrinsicJSFragment( @@ -1360,7 +1362,7 @@ struct IntrinsicJSFragment: Sendable { let base = fullName.components(separatedBy: ".").last ?? fullName return .associatedEnumLiftReturn(enumBase: base) case .swiftStruct(let fullName): - let base = fullName.components(separatedBy: ".").last ?? fullName + let base = fullName.replacingOccurrences(of: ".", with: "_") return swiftStructLiftReturn(structBase: base) case .closure: return IntrinsicJSFragment( @@ -1420,33 +1422,25 @@ struct IntrinsicJSFragment: Sendable { return try .optionalLiftParameter(wrappedType: wrappedType, kind: kind, context: context) case .rawValueEnum(_, .string): return .stringLiftParameter 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] - } - ) - } + 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 + let base = fullName.replacingOccurrences(of: ".", with: "_") return IntrinsicJSFragment( parameters: [], printCode: { arguments, context in @@ -1500,15 +1494,7 @@ struct IntrinsicJSFragment: Sendable { return try .optionalLowerReturn(wrappedType: wrappedType, kind: kind) case .rawValueEnum(_, .string): return .stringLowerReturn 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) - } + return associatedValueLowerReturn(fullName: fullName) case .swiftStruct(let fullName): switch context { case .importTS: @@ -1805,7 +1791,7 @@ struct IntrinsicJSFragment: Sendable { } static func swiftStructLowerReturn(fullName: String) -> IntrinsicJSFragment { - swiftStructLower(structBase: fullName.components(separatedBy: ".").last ?? fullName) + swiftStructLower(structBase: fullName.replacingOccurrences(of: ".", with: "_")) } static func swiftStructLowerParameter(structBase: String) -> IntrinsicJSFragment { @@ -1896,20 +1882,31 @@ struct IntrinsicJSFragment: Sendable { 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)++) {") + printer.write("let \(resultVar);") + printer.write("if (\(lenVar) === -1) {") + printer.indent { + // Bulk path: Swift pushed a typed array onto the typed-array stack + printer.write("\(resultVar) = \(JSGlueVariableScope.reservedTaStack).pop();") + } + printer.write("} else {") 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));") + // Element-by-element path (original behavior) + let iVar = scope.variable("i") + printer.write("\(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();") } printer.write("}") - printer.write("\(resultVar).reverse();") return [resultVar] } ) @@ -2008,7 +2005,7 @@ struct IntrinsicJSFragment: Sendable { } ) case .swiftStruct(let fullName): - let structBase = fullName.components(separatedBy: ".").last ?? fullName + let structBase = fullName.replacingOccurrences(of: ".", with: "_") return IntrinsicJSFragment( parameters: [], printCode: { arguments, context in @@ -2130,7 +2127,7 @@ struct IntrinsicJSFragment: Sendable { } ) case .swiftStruct(let fullName): - let structBase = fullName.components(separatedBy: ".").last ?? fullName + let structBase = fullName.replacingOccurrences(of: ".", with: "_") return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in @@ -2426,7 +2423,7 @@ struct IntrinsicJSFragment: Sendable { ) try printer.indent { printer.write( - "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(this);" + "\(JSGlueVariableScope.reservedStructHelpers).\(structDef.abiName).lower(this);" ) var paramForwardings: [String] = [] @@ -2502,7 +2499,7 @@ struct IntrinsicJSFragment: Sendable { let printer = context.printer let value = arguments[0] printer.write( - "\(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lower(\(value));" + "\(JSGlueVariableScope.reservedStructHelpers).\(nestedName.replacingOccurrences(of: ".", with: "_")).lower(\(value));" ) return [] } @@ -2540,7 +2537,7 @@ struct IntrinsicJSFragment: Sendable { let (scope, printer) = (context.scope, context.printer) let structVar = scope.variable("struct") printer.write( - "const \(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName).lift();" + "const \(structVar) = \(JSGlueVariableScope.reservedStructHelpers).\(nestedName.replacingOccurrences(of: ".", with: "_")).lift();" ) return [structVar] } @@ -2590,7 +2587,10 @@ fileprivate extension WasmCoreType { var jsZeroLiteral: String { switch self { case .f32, .f64: return "0.0" - case .i32, .i64, .pointer: return "0" + // A Wasm `i64` parameter is passed as a JavaScript `BigInt`, so its zero + // placeholder must be a BigInt literal rather than a plain number. + case .i64: return "0n" + case .i32, .pointer: return "0" } } } @@ -2648,7 +2648,7 @@ private extension BridgeType { case .string: return .sideChannelReturn(.storage) case .jsObject: - return .sideChannelReturn(.retainedObject) + return .stackABI case .jsValue: return .inlineFlag case .swiftHeapObject: @@ -2683,9 +2683,27 @@ private extension BridgeType { } } + /// Whether an optional of this type pushes its payload onto the bridge stack + /// when passed as a *parameter*. + /// + /// This usually matches `optionalConvention == .stackABI`, but `jsObject` + /// optionals are the exception: their return values travel through the stack + /// while their parameters use the direct `(isSome, objId)` ABI, matching plain + /// `Optional` and exported `@JS class` parameters. + var optionalParameterUsesStackABI: Bool { + switch self { + case .jsObject: + return false + case .nullable(let wrapped, _): + return wrapped.optionalParameterUsesStackABI + default: + return optionalConvention == .stackABI + } + } + var nilSentinel: NilSentinel { switch self { - case .jsObject, .swiftProtocol: + case .swiftProtocol: return .i32(0) case .swiftHeapObject: return .pointer diff --git a/Plugins/BridgeJS/Sources/BridgeJSPluginUtilities/PluginPaths.swift b/Plugins/BridgeJS/Sources/BridgeJSPluginUtilities/PluginPaths.swift new file mode 100644 index 000000000..f95d1adaa --- /dev/null +++ b/Plugins/BridgeJS/Sources/BridgeJSPluginUtilities/PluginPaths.swift @@ -0,0 +1,74 @@ +#if canImport(PackagePlugin) +import struct Foundation.URL + +enum BridgeJSPluginPaths { + static func skeletonURL( + targetName: String, + packageID: String, + buildPluginWorkDirectoryURL workDirectoryURL: URL + ) -> URL { + let pluginsOutputsRootURL = + workDirectoryURL + .deletingLastPathComponent() + .deletingLastPathComponent() + .deletingLastPathComponent() + .deletingLastPathComponent() + return bridgeJSDirectoryURL( + targetName: targetName, + packageID: packageID, + pluginsOutputsRootURL: pluginsOutputsRootURL + ) + .appending(path: "JavaScript/BridgeJS.json") + } + + static func skeletonURL( + targetName: String, + packageID: String, + commandPluginWorkDirectoryURL workDirectoryURL: URL + ) -> URL { + // workDirectoryURL: ".build/plugins/PackageToJS/outputs/" + // .build/plugins/outputs/[package]/[target]/destination/BridgeJS/JavaScript/BridgeJS.json + let pluginsOutputsRootURL = + workDirectoryURL + .deletingLastPathComponent() + .deletingLastPathComponent() + .appending(path: "outputs") + return bridgeJSDirectoryURL( + targetName: targetName, + packageID: packageID, + pluginsOutputsRootURL: pluginsOutputsRootURL + ) + .appending(path: "JavaScript/BridgeJS.json") + } + + static func bridgeJSSwiftURL( + targetName: String, + packageID: String, + buildPluginWorkDirectoryURL workDirectoryURL: URL + ) -> URL { + let pluginsOutputsRootURL = + workDirectoryURL + .deletingLastPathComponent() + .deletingLastPathComponent() + .deletingLastPathComponent() + .deletingLastPathComponent() + return bridgeJSDirectoryURL( + targetName: targetName, + packageID: packageID, + pluginsOutputsRootURL: pluginsOutputsRootURL + ) + .appending(path: "BridgeJS.swift") + } + + private static func bridgeJSDirectoryURL( + targetName: String, + packageID: String, + pluginsOutputsRootURL: URL + ) -> URL { + pluginsOutputsRootURL + .appending(path: packageID) + .appending(path: targetName) + .appending(path: "destination/BridgeJS") + } +} +#endif diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index 03e6d676a..830132481 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -89,6 +89,38 @@ public enum BridgeContext: Sendable { case exportSwift } +/// Access level applied to bridge-generated declarations. +/// +/// Ordering (`Comparable`) reflects visibility breadth, so taking `max` of two +/// levels yields the more permissive one — used to merge a single closure +/// signature seen across surfaces with different declared access. +public enum BridgeJSAccessLevel: String, Codable, Equatable, Hashable, Sendable, Comparable { + case `internal` + case package + case `public` + + public static func < (lhs: BridgeJSAccessLevel, rhs: BridgeJSAccessLevel) -> Bool { + lhs.order < rhs.order + } + + private var order: Int { + switch self { + case .internal: return 0 + case .package: return 1 + case .public: return 2 + } + } + + /// Returns the modifier keyword to emit, or nil for the default (internal). + public var modifierKeyword: String? { + switch self { + case .internal: return nil + case .package: return "package" + case .public: return "public" + } + } +} + public struct ClosureSignature: Codable, Equatable, Hashable, Sendable { public let parameters: [BridgeType] public let returnType: BridgeType @@ -398,17 +430,34 @@ public struct Parameter: Codable, Equatable, Sendable { // MARK: - BridgeSkeleton Visitor public protocol BridgeSkeletonVisitor { - mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) + /// Called when a closure type is encountered during traversal. + /// + /// `accessLevel` reflects the source access of the enclosing declaration, + /// so visitors can derive an appropriate access level for any + /// bridge-generated helpers tied to this signature (e.g. typed closure + /// inits in `ClosureCodegen`). + mutating func visitClosure( + _ signature: ClosureSignature, + useJSTypedClosure: Bool, + accessLevel: BridgeJSAccessLevel + ) mutating func visitImportedFunction(_ function: ImportedFunctionSkeleton) } public extension BridgeSkeletonVisitor { - mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) {} + mutating func visitClosure( + _ signature: ClosureSignature, + useJSTypedClosure: Bool, + accessLevel: BridgeJSAccessLevel + ) {} mutating func visitImportedFunction(_ function: ImportedFunctionSkeleton) {} } public struct BridgeSkeletonWalker { public var visitor: Visitor + /// Tracks the access level of the enclosing declaration during traversal. + /// Saved/restored around each declaration that introduces an access boundary. + private var currentAccessLevel: BridgeJSAccessLevel = .internal public init(visitor: Visitor) { self.visitor = visitor @@ -417,7 +466,11 @@ public struct BridgeSkeletonWalker { public mutating func walk(_ type: BridgeType) { switch type { case .closure(let signature, let useJSTypedClosure): - visitor.visitClosure(signature, useJSTypedClosure: useJSTypedClosure) + visitor.visitClosure( + signature, + useJSTypedClosure: useJSTypedClosure, + accessLevel: currentAccessLevel + ) for paramType in signature.parameters { walk(paramType) } @@ -449,14 +502,16 @@ public struct BridgeSkeletonWalker { 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) + withAccessLevel(klass.explicitAccessControl) { + if let constructor = klass.constructor { + $0.walk(constructor.parameters) + } + for method in klass.methods { + $0.walk(method) + } + for property in klass.properties { + $0.walk(property.type) + } } } for proto in skeleton.protocols { @@ -468,58 +523,66 @@ public struct BridgeSkeletonWalker { } } 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) + withAccessLevel(structDecl.explicitAccessControl) { + for property in structDecl.properties { + $0.walk(property.type) + } + if let constructor = structDecl.constructor { + $0.walk(constructor.parameters) + } + for method in structDecl.methods { + $0.walk(method) + } } } for enumDecl in skeleton.enums { - for enumCase in enumDecl.cases { - for associatedValue in enumCase.associatedValues { - walk(associatedValue.type) + withAccessLevel(enumDecl.explicitAccessControl) { + for enumCase in enumDecl.cases { + for associatedValue in enumCase.associatedValues { + $0.walk(associatedValue.type) + } + } + for method in enumDecl.staticMethods { + $0.walk(method) + } + for property in enumDecl.staticProperties { + $0.walk(property.type) } - } - for method in enumDecl.staticMethods { - walk(method) - } - for property in enumDecl.staticProperties { - walk(property.type) } } } public mutating func walk(_ function: ImportedFunctionSkeleton) { visitor.visitImportedFunction(function) - walk(function.parameters) - walk(function.returnType) + withAccessLevel(function.accessLevel) { + $0.walk(function.parameters) + $0.walk(function.returnType) + } } public mutating func walk(_ skeleton: ImportedModuleSkeleton) { for fileSkeleton in skeleton.children { for getter in fileSkeleton.globalGetters { - walk(getter.type) + withAccessLevel(getter.accessLevel) { $0.walk(getter.type) } } for setter in fileSkeleton.globalSetters { - walk(setter.type) + withAccessLevel(setter.accessLevel) { $0.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) + withAccessLevel(type.accessLevel) { + if let constructor = type.constructor { + $0.withAccessLevel(constructor.accessLevel) { $0.walk(constructor.parameters) } + } + for getter in type.getters { + $0.withAccessLevel(getter.accessLevel) { $0.walk(getter.type) } + } + for setter in type.setters { + $0.withAccessLevel(setter.accessLevel) { $0.walk(setter.type) } + } + for method in type.methods + type.staticMethods { + $0.walk(method) + } } } } @@ -532,6 +595,40 @@ public struct BridgeSkeletonWalker { walk(imported) } } + + /// Sets `currentAccessLevel` to `level` for the duration of `body`, restoring + /// the prior value afterward. A nil level (e.g. for exported decls without + /// an explicit modifier) inherits the outer level rather than overwriting it. + private mutating func withAccessLevel( + _ level: BridgeJSAccessLevel?, + _ body: (inout BridgeSkeletonWalker) -> Void + ) { + let saved = currentAccessLevel + if let level { + currentAccessLevel = level + } + body(&self) + currentAccessLevel = saved + } + + /// String-typed convenience: maps `"public"`/`"package"`/`"internal"` from + /// `Exported*.explicitAccessControl` to the typed enum. Unknown strings + /// (e.g. `"open"`, `"private"`) hit the assert in debug builds and inherit + /// the outer level in release — the `@JSExport` macros reject those cases + /// upstream, so this is a defensive guard against future schema drift. + private mutating func withAccessLevel( + _ rawLevel: String?, + _ body: (inout BridgeSkeletonWalker) -> Void + ) { + let level: BridgeJSAccessLevel? + if let rawLevel { + level = BridgeJSAccessLevel(rawValue: rawLevel) + assert(level != nil, "Unexpected access level string: \(rawLevel)") + } else { + level = nil + } + withAccessLevel(level, body) + } } public struct Effects: Codable, Equatable, Sendable { @@ -930,6 +1027,30 @@ public struct ExportedSkeleton: Codable { public var isEmpty: Bool { functions.isEmpty && classes.isEmpty && enums.isEmpty && structs.isEmpty && protocols.isEmpty } + + /// Distinct `async` return types needing a `Promise_resolve_` helper, deduplicated + /// by mangled name. Shared by the Swift codegen and JS link. + public var asyncPromiseResolveReturnTypes: [BridgeType] { + var seen = Set() + var result: [BridgeType] = [] + func consider(_ returnType: BridgeType, _ effects: Effects) { + guard effects.isAsync, returnType.isAsyncResolvable, + seen.insert(returnType.mangleTypeName).inserted + else { return } + result.append(returnType) + } + for function in functions { consider(function.returnType, function.effects) } + for klass in classes { + for method in klass.methods { consider(method.returnType, method.effects) } + } + for structDef in structs { + for method in structDef.methods { consider(method.returnType, method.effects) } + } + for enumDef in enums { + for method in enumDef.staticMethods { consider(method.returnType, method.effects) } + } + return result + } } // MARK: - Imported Skeleton @@ -951,6 +1072,10 @@ public struct ImportedFunctionSkeleton: Codable { public let returnType: BridgeType public let effects: Effects public let documentation: String? + /// Source access level of the originating Swift declaration. Used to + /// determine the access level of bridge-generated helpers (e.g. typed + /// closure inits) that surface through this function's signature. + public let accessLevel: BridgeJSAccessLevel public init( name: String, @@ -959,7 +1084,8 @@ public struct ImportedFunctionSkeleton: Codable { parameters: [Parameter], returnType: BridgeType, effects: Effects = Effects(isAsync: false, isThrows: true), - documentation: String? = nil + documentation: String? = nil, + accessLevel: BridgeJSAccessLevel = .internal ) { self.name = name self.jsName = jsName @@ -968,6 +1094,23 @@ public struct ImportedFunctionSkeleton: Codable { self.returnType = returnType self.effects = effects self.documentation = documentation + self.accessLevel = accessLevel + } + + private enum CodingKeys: String, CodingKey { + case name, jsName, from, parameters, returnType, effects, documentation, accessLevel + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.name = try container.decode(String.self, forKey: .name) + self.jsName = try container.decodeIfPresent(String.self, forKey: .jsName) + self.from = try container.decodeIfPresent(JSImportFrom.self, forKey: .from) + self.parameters = try container.decode([Parameter].self, forKey: .parameters) + self.returnType = try container.decode(BridgeType.self, forKey: .returnType) + self.effects = try container.decode(Effects.self, forKey: .effects) + self.documentation = try container.decodeIfPresent(String.self, forKey: .documentation) + self.accessLevel = try container.decodeIfPresent(BridgeJSAccessLevel.self, forKey: .accessLevel) ?? .internal } public func abiName(context: ImportedTypeSkeleton?) -> String { @@ -985,9 +1128,23 @@ public struct ImportedFunctionSkeleton: Codable { public struct ImportedConstructorSkeleton: Codable { public let parameters: [Parameter] + /// Source access level of the originating Swift `init`. Inherits from the + /// enclosing `@JSClass` type when not annotated explicitly. + public let accessLevel: BridgeJSAccessLevel - public init(parameters: [Parameter]) { + public init(parameters: [Parameter], accessLevel: BridgeJSAccessLevel = .internal) { self.parameters = parameters + self.accessLevel = accessLevel + } + + private enum CodingKeys: String, CodingKey { + case parameters, accessLevel + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.parameters = try container.decode([Parameter].self, forKey: .parameters) + self.accessLevel = try container.decodeIfPresent(BridgeJSAccessLevel.self, forKey: .accessLevel) ?? .internal } public func abiName(context: ImportedTypeSkeleton) -> String { @@ -1008,6 +1165,8 @@ public struct ImportedGetterSkeleton: Codable { public let documentation: String? /// Name of the getter function if it's a separate function (from @JSGetter) public let functionName: String? + /// Source access level of the originating Swift declaration. + public let accessLevel: BridgeJSAccessLevel public init( name: String, @@ -1015,7 +1174,8 @@ public struct ImportedGetterSkeleton: Codable { from: JSImportFrom? = nil, type: BridgeType, documentation: String? = nil, - functionName: String? = nil + functionName: String? = nil, + accessLevel: BridgeJSAccessLevel = .internal ) { self.name = name self.jsName = jsName @@ -1023,6 +1183,22 @@ public struct ImportedGetterSkeleton: Codable { self.type = type self.documentation = documentation self.functionName = functionName + self.accessLevel = accessLevel + } + + private enum CodingKeys: String, CodingKey { + case name, jsName, from, type, documentation, functionName, accessLevel + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.name = try container.decode(String.self, forKey: .name) + self.jsName = try container.decodeIfPresent(String.self, forKey: .jsName) + self.from = try container.decodeIfPresent(JSImportFrom.self, forKey: .from) + self.type = try container.decode(BridgeType.self, forKey: .type) + self.documentation = try container.decodeIfPresent(String.self, forKey: .documentation) + self.functionName = try container.decodeIfPresent(String.self, forKey: .functionName) + self.accessLevel = try container.decodeIfPresent(BridgeJSAccessLevel.self, forKey: .accessLevel) ?? .internal } public func abiName(context: ImportedTypeSkeleton?) -> String { @@ -1049,19 +1225,37 @@ public struct ImportedSetterSkeleton: Codable { public let documentation: String? /// Name of the setter function if it's a separate function (from @JSSetter) public let functionName: String? + /// Source access level of the originating Swift declaration. + public let accessLevel: BridgeJSAccessLevel public init( name: String, jsName: String? = nil, type: BridgeType, documentation: String? = nil, - functionName: String? = nil + functionName: String? = nil, + accessLevel: BridgeJSAccessLevel = .internal ) { self.name = name self.jsName = jsName self.type = type self.documentation = documentation self.functionName = functionName + self.accessLevel = accessLevel + } + + private enum CodingKeys: String, CodingKey { + case name, jsName, type, documentation, functionName, accessLevel + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.name = try container.decode(String.self, forKey: .name) + self.jsName = try container.decodeIfPresent(String.self, forKey: .jsName) + self.type = try container.decode(BridgeType.self, forKey: .type) + self.documentation = try container.decodeIfPresent(String.self, forKey: .documentation) + self.functionName = try container.decodeIfPresent(String.self, forKey: .functionName) + self.accessLevel = try container.decodeIfPresent(BridgeJSAccessLevel.self, forKey: .accessLevel) ?? .internal } public func abiName(context: ImportedTypeSkeleton?) -> String { @@ -1093,6 +1287,8 @@ public struct ImportedTypeSkeleton: Codable { public let getters: [ImportedGetterSkeleton] public let setters: [ImportedSetterSkeleton] public let documentation: String? + /// Source access level of the originating Swift `@JSClass` declaration. + public let accessLevel: BridgeJSAccessLevel public init( name: String, @@ -1103,7 +1299,8 @@ public struct ImportedTypeSkeleton: Codable { staticMethods: [ImportedFunctionSkeleton] = [], getters: [ImportedGetterSkeleton] = [], setters: [ImportedSetterSkeleton] = [], - documentation: String? = nil + documentation: String? = nil, + accessLevel: BridgeJSAccessLevel = .internal ) { self.name = name self.jsName = jsName @@ -1114,6 +1311,25 @@ public struct ImportedTypeSkeleton: Codable { self.getters = getters self.setters = setters self.documentation = documentation + self.accessLevel = accessLevel + } + + private enum CodingKeys: String, CodingKey { + case name, jsName, from, constructor, methods, staticMethods, getters, setters, documentation, accessLevel + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.name = try container.decode(String.self, forKey: .name) + self.jsName = try container.decodeIfPresent(String.self, forKey: .jsName) + self.from = try container.decodeIfPresent(JSImportFrom.self, forKey: .from) + self.constructor = try container.decodeIfPresent(ImportedConstructorSkeleton.self, forKey: .constructor) + self.methods = try container.decode([ImportedFunctionSkeleton].self, forKey: .methods) + self.staticMethods = try container.decode([ImportedFunctionSkeleton].self, forKey: .staticMethods) + self.getters = try container.decode([ImportedGetterSkeleton].self, forKey: .getters) + self.setters = try container.decode([ImportedSetterSkeleton].self, forKey: .setters) + self.documentation = try container.decodeIfPresent(String.self, forKey: .documentation) + self.accessLevel = try container.decodeIfPresent(BridgeJSAccessLevel.self, forKey: .accessLevel) ?? .internal } } @@ -1180,16 +1396,50 @@ public struct ImportedModuleSkeleton: Codable { // MARK: - Closure signature collection visitor public struct ClosureSignatureCollectorVisitor: BridgeSkeletonVisitor { - public var signatures: Set = [] + /// Each unique closure signature mapped to the most-permissive access level + /// observed across all surfaces that reference it. The codegen reads this + /// to choose the access modifier for the synthesized typed-closure init. + public private(set) var signatureAccessLevels: [ClosureSignature: BridgeJSAccessLevel] = [:] + /// Convenience view for callers (e.g. `BridgeJSLink`) that only need the + /// set of unique signatures, without access metadata. + public var signatures: Set { Set(signatureAccessLevels.keys) } let moduleName: String + /// Convenience for callers that only need to seed signatures without + /// access metadata (e.g. exported-side walking, where closure init access + /// is irrelevant because the synthesized init isn't surfaced to consumers). + /// All seeded signatures default to `.internal`; if a seeded signature is + /// later observed with a more permissive access level, the merge in + /// `recordSignature` upgrades it. public init(moduleName: String, signatures: Set = []) { self.moduleName = moduleName - self.signatures = signatures + for signature in signatures { + signatureAccessLevels[signature] = .internal + } + } + + public mutating func visitClosure( + _ signature: ClosureSignature, + useJSTypedClosure: Bool, + accessLevel: BridgeJSAccessLevel + ) { + recordSignature(signature, accessLevel: accessLevel) } - public mutating func visitClosure(_ signature: ClosureSignature, useJSTypedClosure: Bool) { - signatures.insert(signature) + /// Insert `signature` at `accessLevel`, or upgrade the existing level to + /// the more permissive of the two. Centralizing the merge here keeps + /// `visitClosure` and `recordInjectedSignature` in lockstep — if the + /// merge policy ever needs to change (e.g. adding a diagnostic for + /// conflicting levels), there's only one place to update. + private mutating func recordSignature( + _ signature: ClosureSignature, + accessLevel: BridgeJSAccessLevel + ) { + if let existing = signatureAccessLevels[signature] { + signatureAccessLevels[signature] = max(existing, accessLevel) + } else { + signatureAccessLevels[signature] = accessLevel + } } public mutating func visitImportedFunction(_ function: ImportedFunctionSkeleton) { guard function.effects.isAsync else { return } @@ -1202,34 +1452,48 @@ public struct ClosureSignatureCollectorVisitor: BridgeSkeletonVisitor { // transferred through the checked continuation without Sendable constraints. // Reject callback - signatures.insert( + recordInjectedSignature( ClosureSignature( parameters: [.jsValue], returnType: .void, moduleName: moduleName, sendingParameters: true - ) + ), + for: function ) // Resolve callback (typed per return type) if function.returnType == .void { - signatures.insert( + recordInjectedSignature( ClosureSignature( parameters: [], returnType: .void, moduleName: moduleName - ) + ), + for: function ) } else { - signatures.insert( + recordInjectedSignature( ClosureSignature( parameters: [function.returnType], returnType: .void, moduleName: moduleName, sendingParameters: true - ) + ), + for: function ) } } + + /// Inject a closure signature derived from an async import (e.g. Promise + /// resolve/reject callbacks). The injected signature inherits the access + /// level of the originating function so its synthesized init matches the + /// visibility of the async API surface. + private mutating func recordInjectedSignature( + _ signature: ClosureSignature, + for function: ImportedFunctionSkeleton + ) { + recordSignature(signature, accessLevel: function.accessLevel) + } } // MARK: - Unified Skeleton @@ -1239,11 +1503,18 @@ public struct BridgeJSSkeleton: Codable { public let moduleName: String public let exported: ExportedSkeleton? public let imported: ImportedModuleSkeleton? + public let usedExternalModules: [String] - public init(moduleName: String, exported: ExportedSkeleton? = nil, imported: ImportedModuleSkeleton? = nil) { + public init( + moduleName: String, + exported: ExportedSkeleton? = nil, + imported: ImportedModuleSkeleton? = nil, + usedExternalModules: [String] = [] + ) { self.moduleName = moduleName self.exported = exported self.imported = imported + self.usedExternalModules = usedExternalModules } } @@ -1337,6 +1608,25 @@ extension BridgeType { return false } + /// Whether a value of this type can be passed to a generated `Promise_resolve_` + /// settlement helper, i.e. lowered through the imported-parameter ABI. Every `async` + /// exported return settles through `_bjs_makePromise`; the few types that cannot be lowered + /// (protocols, namespace enums, and their compositions) are diagnosed. + public var isAsyncResolvable: Bool { + switch self { + case .swiftProtocol, .namespaceEnum: + return false + case .nullable(let wrapped, _): + return wrapped.isAsyncResolvable + case .array(let element): + return element.isAsyncResolvable + case .dictionary(let value): + return value.isAsyncResolvable + default: + return true + } + } + /// Simplified Swift ABI-style mangled name /// https://github.com/swiftlang/swift/blob/main/docs/ABI/Mangling.rst#types public var mangleTypeName: String { @@ -1408,7 +1698,7 @@ extension BridgeType { } switch wrappedType { - case .string, .integer, .float, .double, .jsObject, .swiftProtocol: + case .string, .integer, .float, .double, .swiftProtocol: return true case .rawValueEnum(_, let rawType): switch rawType { @@ -1419,7 +1709,7 @@ extension BridgeType { default: return false } - case .bool, .caseEnum, .swiftHeapObject, .associatedValueEnum: + case .bool, .caseEnum, .swiftHeapObject, .associatedValueEnum, .jsObject: return false default: return false diff --git a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift index 3e3f27ea1..005af04a8 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSTool/BridgeJSTool.swift @@ -112,10 +112,18 @@ import BridgeJSUtilities help: "The path to the TypeScript project configuration file (required for .d.ts files)", required: false ), + "dependency-skeleton": OptionRule( + help: "Path to a dependency module's BridgeJS.json, as '='. Repeatable.", + required: false, + repeatable: true + ), ] ) - let (positionalArguments, _, doubleDashOptions) = try parser.parse( - arguments: Array(arguments.dropFirst()) + let parsedArguments = try parser.parse(arguments: Array(arguments.dropFirst())) + let positionalArguments = parsedArguments.positionalArguments + let doubleDashOptions = parsedArguments.doubleDashOptions + let dependencySkeletons = try loadDependencySkeletons( + parsedArguments.repeatedDoubleDashOptions["dependency-skeleton", default: []] ) let progress = ProgressReporting(verbose: doubleDashOptions["verbose"] == "true") let moduleName = doubleDashOptions["module-name"]! @@ -162,10 +170,12 @@ import BridgeJSUtilities inputFiles.append(macrosPath) } } + let externalModuleIndex = ExternalModuleIndex(dependencies: dependencySkeletons) let swiftToSkeleton = SwiftToSkeleton( progress: progress, moduleName: moduleName, exposeToGlobal: config.exposeToGlobal, + externalModuleIndex: externalModuleIndex, identityMode: config.identityMode ) for inputFile in inputFiles.sorted() { @@ -224,7 +234,10 @@ import BridgeJSUtilities // 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 outputSwift = combineGeneratedSwift( + combinedSwift, + importingExternalModules: skeleton.usedExternalModules + ) let shouldWrite = doubleDashOptions["always-write"] == "true" || !outputSwift.isEmpty if shouldWrite { try withSpan("Writing output Swift") { @@ -237,7 +250,14 @@ import BridgeJSUtilities } } - // Write unified skeleton + // Write unified skeleton. + // Note that for the build system to sequence the BridgeJSBuildPlugin correctly, + // the skeleton-to-Swift-output mapping must be injective, i.e. any change to + // the skeleton must produce a change in the Swift output. This is because we + // can’t use the BridgeJS.json file as an outputFile, since it would then be + // treated as a resource and thus included in the generated bundle. The + // invariant currently holds, but if this ever changes the BridgeJS.swift file + // could include a hash of the skeleton to maintain it. let outputSkeletonURL = outputDirectory.appending(path: "JavaScript/BridgeJS.json") try withSpan("Writing output skeleton") { try FileManager.default.createDirectory( @@ -302,14 +322,45 @@ private func writeIfChanged(_ data: Data, to url: URL) throws { try data.write(to: url) } -private func combineGeneratedSwift(_ pieces: [String]) -> String { +private func loadDependencySkeletons( + _ rawArguments: [String] +) throws -> [(moduleName: String, skeleton: BridgeJSSkeleton)] { + var loadedSkeletons: [(moduleName: String, skeleton: BridgeJSSkeleton)] = [] + let decoder = JSONDecoder() + for rawArgument in rawArguments { + guard let equalIndex = rawArgument.firstIndex(of: "="), equalIndex != rawArgument.startIndex else { + throw BridgeJSToolError( + "--dependency-skeleton expects '='; got invalid value '\(rawArgument)'" + ) + } + let moduleName = String(rawArgument[.. 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") + let imports = BridgeJSGeneratedFile.swiftImports(["JavaScriptKit"] + externalModules) + return ([BridgeJSGeneratedFile.swiftHeader, imports] + trimmedPieces).joined(separator: "\n\n") } private func recursivelyCollectSwiftFiles(from directory: URL) -> [URL] { @@ -365,6 +416,7 @@ extension Profiling { struct OptionRule { var help: String var required: Bool = false + var repeatable: Bool = false } struct ArgumentParser { @@ -377,11 +429,12 @@ struct ArgumentParser { self.doubleDashOptions = doubleDashOptions } - typealias ParsedArguments = ( - positionalArguments: [String], - singleDashOptions: [String: String], - doubleDashOptions: [String: String] - ) + struct ParsedArguments { + var positionalArguments: [String] + var singleDashOptions: [String: String] + var doubleDashOptions: [String: String] + var repeatedDoubleDashOptions: [String: [String]] + } func help() -> String { var help = "Usage: \(CommandLine.arguments.first ?? "bridge-js-tool") [options] \n\n" @@ -404,6 +457,7 @@ struct ArgumentParser { var positionalArguments: [String] = [] var singleDashOptions: [String: String] = [:] var doubleDashOptions: [String: String] = [:] + var repeatedDoubleDashOptions: [String: [String]] = [:] var arguments = arguments.makeIterator() @@ -412,7 +466,12 @@ struct ArgumentParser { if arg.starts(with: "--") { let key = String(arg.dropFirst(2)) let value = arguments.next() - doubleDashOptions[key] = value + if self.doubleDashOptions[key]?.repeatable ?? false { + guard let value else { continue } + repeatedDoubleDashOptions[key, default: []].append(value) + } else { + doubleDashOptions[key] = value + } } else { let key = String(arg.dropFirst(1)) let value = arguments.next() @@ -424,11 +483,16 @@ struct ArgumentParser { } for (key, rule) in self.doubleDashOptions { - if rule.required, doubleDashOptions[key] == nil { + if rule.required, doubleDashOptions[key] == nil, repeatedDoubleDashOptions[key] == nil { throw BridgeJSToolError("Option --\(key) is required") } } - return (positionalArguments, singleDashOptions, doubleDashOptions) + return ParsedArguments( + positionalArguments: positionalArguments, + singleDashOptions: singleDashOptions, + doubleDashOptions: doubleDashOptions, + repeatedDoubleDashOptions: repeatedDoubleDashOptions + ) } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSToolInternal/BridgeJSToolInternal.swift b/Plugins/BridgeJS/Sources/BridgeJSToolInternal/BridgeJSToolInternal.swift index 8a6a6b7b4..f4de24093 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSToolInternal/BridgeJSToolInternal.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSToolInternal/BridgeJSToolInternal.swift @@ -48,7 +48,8 @@ import ArgumentParser let swiftToSkeleton = SwiftToSkeleton( progress: ProgressReporting(verbose: false), moduleName: "InternalModule", - exposeToGlobal: false + exposeToGlobal: false, + externalModuleIndex: .empty ) for inputFile in inputFiles.sorted() { let content = try String(decoding: readData(from: inputFile), as: UTF8.self) diff --git a/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift index 68c07f225..cb6e0d0b0 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSUtilities/Utilities.swift @@ -13,19 +13,22 @@ public enum BridgeJSGeneratedFile { content.starts(with: skipLine + "\n") } - public static var swiftPreamble: String { + public static var swiftHeader: String { // The generated Swift file itself should not be processed by BridgeJS again. """ \(skipLine) + // swift-format-ignore-file // 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 """ } + + public static func swiftImports(_ moduleNames: [String]) -> String { + moduleNames.map { "@_spi(BridgeJS) import \($0)" }.joined(separator: "\n") + } } /// A printer for code fragments. diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js index 17086e92e..c5e89c208 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/cli.js @@ -149,6 +149,7 @@ export function run(filePaths, options) { } const prelude = [ + "// swift-format-ignore-file", "// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,", "// DO NOT EDIT.", "//", diff --git a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap index 643ac8441..0cb0e3206 100644 --- a/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap +++ b/Plugins/BridgeJS/Sources/TS2Swift/JavaScript/test/__snapshots__/ts2swift.test.js.snap @@ -1,7 +1,8 @@ // 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, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -24,7 +25,8 @@ exports[`ts2swift > snapshots Swift output for ArrayParameter.d.ts > ArrayParame `; exports[`ts2swift > snapshots Swift output for Async.d.ts > Async 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -49,7 +51,8 @@ exports[`ts2swift > snapshots Swift output for Async.d.ts > Async 1`] = ` `; exports[`ts2swift > snapshots Swift output for CallableConst.d.ts > CallableConst 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -65,7 +68,8 @@ exports[`ts2swift > snapshots Swift output for CallableConst.d.ts > CallableCons `; exports[`ts2swift > snapshots Swift output for Documentation.d.ts > Documentation 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -122,7 +126,8 @@ exports[`ts2swift > snapshots Swift output for Documentation.d.ts > Documentatio `; exports[`ts2swift > snapshots Swift output for ExportAssignment.d.ts > ExportAssignment 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -135,7 +140,8 @@ exports[`ts2swift > snapshots Swift output for ExportAssignment.d.ts > ExportAss `; exports[`ts2swift > snapshots Swift output for Interface.d.ts > Interface 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -153,7 +159,8 @@ exports[`ts2swift > snapshots Swift output for Interface.d.ts > Interface 1`] = `; exports[`ts2swift > snapshots Swift output for InvalidPropertyNames.d.ts > InvalidPropertyNames 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -201,7 +208,8 @@ exports[`ts2swift > snapshots Swift output for InvalidPropertyNames.d.ts > Inval `; exports[`ts2swift > snapshots Swift output for MultipleImportedTypes.d.ts > MultipleImportedTypes 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -238,7 +246,8 @@ exports[`ts2swift > snapshots Swift output for MultipleImportedTypes.d.ts > Mult `; exports[`ts2swift > snapshots Swift output for ObjectLikeTypes.d.ts > ObjectLikeTypes 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -251,7 +260,8 @@ exports[`ts2swift > snapshots Swift output for ObjectLikeTypes.d.ts > ObjectLike `; exports[`ts2swift > snapshots Swift output for OptionalNullUndefined.d.ts > OptionalNullUndefined 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -292,7 +302,8 @@ exports[`ts2swift > snapshots Swift output for OptionalNullUndefined.d.ts > Opti `; exports[`ts2swift > snapshots Swift output for PrimitiveParameters.d.ts > PrimitiveParameters 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -305,7 +316,8 @@ exports[`ts2swift > snapshots Swift output for PrimitiveParameters.d.ts > Primit `; exports[`ts2swift > snapshots Swift output for PrimitiveReturn.d.ts > PrimitiveReturn 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -320,7 +332,8 @@ exports[`ts2swift > snapshots Swift output for PrimitiveReturn.d.ts > PrimitiveR `; exports[`ts2swift > snapshots Swift output for ReExportFrom.d.ts > ReExportFrom 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -338,7 +351,8 @@ exports[`ts2swift > snapshots Swift output for ReExportFrom.d.ts > ReExportFrom `; exports[`ts2swift > snapshots Swift output for RecordDictionary.d.ts > RecordDictionary 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -368,7 +382,8 @@ exports[`ts2swift > snapshots Swift output for RecordDictionary.d.ts > RecordDic `; exports[`ts2swift > snapshots Swift output for StaticProperty.d.ts > StaticProperty 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -384,7 +399,8 @@ exports[`ts2swift > snapshots Swift output for StaticProperty.d.ts > StaticPrope `; exports[`ts2swift > snapshots Swift output for StringEnum.d.ts > StringEnum 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -405,7 +421,8 @@ extension FeatureFlag: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {} `; exports[`ts2swift > snapshots Swift output for StringLiteralUnion.d.ts > StringLiteralUnion 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -426,7 +443,8 @@ extension Direction: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum {} `; exports[`ts2swift > snapshots Swift output for StringParameter.d.ts > StringParameter 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -441,7 +459,8 @@ exports[`ts2swift > snapshots Swift output for StringParameter.d.ts > StringPara `; exports[`ts2swift > snapshots Swift output for StringReturn.d.ts > StringReturn 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -454,7 +473,8 @@ exports[`ts2swift > snapshots Swift output for StringReturn.d.ts > StringReturn `; exports[`ts2swift > snapshots Swift output for TS2SkeletonLike.d.ts > TS2SkeletonLike 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -480,7 +500,8 @@ exports[`ts2swift > snapshots Swift output for TS2SkeletonLike.d.ts > TS2Skeleto `; exports[`ts2swift > snapshots Swift output for TypeAlias.d.ts > TypeAlias 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -493,7 +514,8 @@ exports[`ts2swift > snapshots Swift output for TypeAlias.d.ts > TypeAlias 1`] = `; exports[`ts2swift > snapshots Swift output for TypeAliasObject.d.ts > TypeAliasObject 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -512,7 +534,8 @@ exports[`ts2swift > snapshots Swift output for TypeAliasObject.d.ts > TypeAliasO `; exports[`ts2swift > snapshots Swift output for TypeScriptClass.d.ts > TypeScriptClass 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -533,7 +556,8 @@ exports[`ts2swift > snapshots Swift output for TypeScriptClass.d.ts > TypeScript `; exports[`ts2swift > snapshots Swift output for VoidParameterVoidReturn.d.ts > VoidParameterVoidReturn 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run @@ -546,7 +570,8 @@ exports[`ts2swift > snapshots Swift output for VoidParameterVoidReturn.d.ts > Vo `; exports[`ts2swift > snapshots Swift output for WebIDLDOMDocs.d.ts > WebIDLDOMDocs 1`] = ` -"// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +"// swift-format-ignore-file +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // // To update this file, just rebuild your project or run diff --git a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift index 77dc814eb..c52bc9db0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSMacrosTests/JSClassMacroTests.swift @@ -445,6 +445,64 @@ import BridgeJSMacros ) } + @Test func nestedJSClassStruct() { + let combinedSpecs: [String: MacroSpec] = [ + "JSClass": MacroSpec(type: JSClassMacro.self, conformances: ["_JSBridgedClass"]), + "JSGetter": MacroSpec(type: JSGetterMacro.self), + ] + TestSupport.assertMacroExpansion( + """ + @JSClass + struct User { + @JSGetter + var stats: Stats + + @JSClass + struct Stats { + @JSGetter + var health: Int + } + } + """, + expandedSource: """ + struct User { + var stats: Stats { + get throws(JSException) { + return try _$User_stats_get(self.jsObject) + } + } + struct Stats { + var health: Int { + get throws(JSException) { + return try _$Stats_health_get(self.jsObject) + } + } + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + let jsObject: JSObject + + init(unsafelyWrapping jsObject: JSObject) { + self.jsObject = jsObject + } + } + + extension User.Stats: _JSBridgedClass { + } + + extension User: _JSBridgedClass { + } + """, + macroSpecs: combinedSpecs, + indentationWidth: indentationWidth + ) + } + @Test func fileprivateStructIsRejected() { TestSupport.assertMacroExpansion( """ diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSCodegenTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSCodegenTests.swift index dd0ce5d03..8b8e8b8a2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSCodegenTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSCodegenTests.swift @@ -77,7 +77,12 @@ import Testing 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) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) swiftAPI.addSourceFile(sourceFile, inputFilePath: input) let skeleton = try swiftAPI.finalize() try snapshotCodegen(skeleton: skeleton, name: name) @@ -93,7 +98,12 @@ import Testing 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) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: true, + externalModuleIndex: .empty + ) swiftAPI.addSourceFile(sourceFile, inputFilePath: input) let skeleton = try swiftAPI.finalize() try snapshotCodegen(skeleton: skeleton, name: name + ".Global") @@ -101,7 +111,12 @@ import Testing @Test func codegenCrossFileTypeResolution() throws { - let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) let classBURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileClassB.swift") swiftAPI.addSourceFile( Parser.parse(source: try String(contentsOf: classBURL, encoding: .utf8)), @@ -118,7 +133,12 @@ import Testing @Test func codegenCrossFileTypeResolutionReverseOrder() throws { - let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) let classAURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileClassA.swift") swiftAPI.addSourceFile( Parser.parse(source: try String(contentsOf: classAURL, encoding: .utf8)), @@ -135,7 +155,12 @@ import Testing @Test func codegenCrossFileFunctionTypes() throws { - let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) let functionBURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileFunctionB.swift") swiftAPI.addSourceFile( Parser.parse(source: try String(contentsOf: functionBURL, encoding: .utf8)), @@ -152,7 +177,12 @@ import Testing @Test func codegenCrossFileFunctionTypesReverseOrder() throws { - let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) let functionAURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileFunctionA.swift") swiftAPI.addSourceFile( Parser.parse(source: try String(contentsOf: functionAURL, encoding: .utf8)), @@ -169,7 +199,12 @@ import Testing @Test func codegenCrossFileExtension() throws { - let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) let classURL = Self.multifileInputsDirectory.appendingPathComponent("CrossFileExtensionClass.swift") swiftAPI.addSourceFile( Parser.parse(source: try String(contentsOf: classURL, encoding: .utf8)), @@ -186,7 +221,12 @@ import Testing @Test func codegenSkipsEmptySkeletons() throws { - let swiftAPI = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) let importedURL = Self.multifileInputsDirectory.appendingPathComponent("ImportedFunctions.swift") swiftAPI.addSourceFile( Parser.parse(source: try String(contentsOf: importedURL, encoding: .utf8)), diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift index 64c9ae535..2f3f46fdb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/BridgeJSLinkTests.swift @@ -49,7 +49,12 @@ import Testing let name = url.deletingPathExtension().lastPathComponent let sourceFile = Parser.parse(source: try String(contentsOf: url, encoding: .utf8)) - let importSwift = SwiftToSkeleton(progress: .silent, moduleName: "TestModule", exposeToGlobal: false) + let importSwift = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) importSwift.addSourceFile(sourceFile, inputFilePath: "\(name).swift") let importResult = try importSwift.finalize() var bridgeJSLink = BridgeJSLink(sharedMemory: false) @@ -69,7 +74,12 @@ import Testing 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) + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: true, + externalModuleIndex: .empty + ) swiftAPI.addSourceFile(sourceFile, inputFilePath: inputFile) let name = url.deletingPathExtension().lastPathComponent let outputSkeleton = try swiftAPI.finalize() @@ -86,13 +96,23 @@ import Testing 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) + let globalAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "GlobalModule", + exposeToGlobal: true, + externalModuleIndex: .empty + ) globalAPI.addSourceFile(globalSourceFile, inputFilePath: "MixedGlobal.swift") let globalSkeleton = try globalAPI.finalize() 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) + let privateAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "PrivateModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) privateAPI.addSourceFile(privateSourceFile, inputFilePath: "MixedPrivate.swift") let privateSkeleton = try privateAPI.finalize() @@ -114,6 +134,7 @@ import Testing progress: .silent, moduleName: "TestModule", exposeToGlobal: false, + externalModuleIndex: .empty, identityMode: nil // no config default ) swiftAPI.addSourceFile(sourceFile, inputFilePath: "IdentityModeClass.swift") @@ -140,6 +161,7 @@ import Testing progress: .silent, moduleName: "TestModule", exposeToGlobal: false, + externalModuleIndex: .empty, identityMode: "pointer" // config says pointer for all classes ) swiftAPI.addSourceFile(sourceFile, inputFilePath: "IdentityModeClass.swift") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/CrossModuleResolutionTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/CrossModuleResolutionTests.swift new file mode 100644 index 000000000..4f12a88fa --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/CrossModuleResolutionTests.swift @@ -0,0 +1,491 @@ +import Foundation +import SwiftParser +import SwiftSyntax +import Testing + +@testable import BridgeJSCore +@testable import BridgeJSSkeleton + +@Suite struct CrossModuleResolutionTests { + @Test + func resolvesTopLevelExternalStruct() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: """ + @JS public struct Vector3D { + public let x: Double + public let y: Double + public let z: Double + @JS public init(x: Double, y: Double, z: Double) { + self.x = x; self.y = y; self.z = z + } + } + """ + ) + let app = try resolveApp( + source: """ + import Core + @JS public func currentVelocity() -> Vector3D { + Vector3D(x: 0, y: 0, z: 0) + } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + #expect(app.usedExternalModules == ["Core"]) + let function = try #require(app.exported?.functions.first(where: { $0.name == "currentVelocity" })) + #expect(function.returnType == .swiftStruct("Vector3D")) + } + + @Test + func resolvesTopLevelExternalClass() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: """ + @JS public class Emitter { + @JS public init() {} + @JS public func emit() -> String { "" } + } + """ + ) + let app = try resolveApp( + source: """ + import Core + @JS public func makeEmitter() -> Emitter { Emitter() } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + #expect(app.usedExternalModules == ["Core"]) + let function = try #require(app.exported?.functions.first(where: { $0.name == "makeEmitter" })) + #expect(function.returnType == .swiftHeapObject("Emitter")) + } + + @Test + func resolvesNestedExternalStruct() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: """ + @JS public enum Geometry { + @JS public struct BoundingBox { + public let side: Double + @JS public init(side: Double) { self.side = side } + } + } + """ + ) + let app = try resolveApp( + source: """ + import Core + @JS public func unitBox() -> Geometry.BoundingBox { + Geometry.BoundingBox(side: 1) + } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + #expect(app.usedExternalModules == ["Core"]) + let function = try #require(app.exported?.functions.first(where: { $0.name == "unitBox" })) + #expect(function.returnType == .swiftStruct("Geometry.BoundingBox")) + } + + @Test + func resolvesExplicitModuleQualifier() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: """ + @JS public struct Vector3D { + @JS public init() {} + } + """ + ) + let app = try resolveApp( + source: """ + import Core + @JS public func fromCore() -> Core.Vector3D { Core.Vector3D() } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let function = try #require(app.exported?.functions.first(where: { $0.name == "fromCore" })) + #expect(function.returnType == .swiftStruct("Vector3D")) + } + + @Test + func resolvesExternalTypeInArrayAndOptional() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: """ + @JS public struct Point { + @JS public init() {} + } + """ + ) + let app = try resolveApp( + source: """ + import Core + @JS public func scatter(points: [Point?]) -> Point? { nil } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let function = try #require(app.exported?.functions.first(where: { $0.name == "scatter" })) + #expect(function.returnType == .nullable(.swiftStruct("Point"), .null)) + #expect(function.parameters.first?.type == .array(.nullable(.swiftStruct("Point"), .null))) + } + + // MARK: - Diagnostics + + @Test + func ambiguousExternalNameProducesDiagnostic() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + let graphics = try buildDependencySkeleton( + moduleName: "Graphics", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + + do { + _ = try resolveApp( + source: """ + import Core + import Graphics + @JS public func ambiguous() -> Vector3D { fatalError() } + """, + dependencies: [ + (moduleName: "Core", skeleton: core), + (moduleName: "Graphics", skeleton: graphics), + ] + ) + Issue.record("Expected ambiguity diagnostic, but resolution succeeded") + } catch let error as BridgeJSCoreDiagnosticError { + let combined = error.diagnostics.map(\.diagnostic.message).joined(separator: "\n") + #expect(combined.contains("ambiguous use of 'Vector3D'")) + let combinedHints = error.diagnostics.compactMap(\.diagnostic.hint).joined(separator: "\n") + #expect(combinedHints.contains("Core")) + #expect(combinedHints.contains("Graphics")) + } + } + + @Test + func explicitQualifierResolvesAmbiguity() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + let graphics = try buildDependencySkeleton( + moduleName: "Graphics", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + let app = try resolveApp( + source: """ + import Core + import Graphics + @JS public func fromCore() -> Core.Vector3D { Core.Vector3D() } + """, + dependencies: [ + (moduleName: "Core", skeleton: core), + (moduleName: "Graphics", skeleton: graphics), + ] + ) + #expect(app.usedExternalModules == ["Core"]) + } + + @Test + func localDeclarationShadowsExternalSameName() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + let app = try resolveApp( + source: """ + import Core + @JS public struct Vector3D { + public let id: Int + @JS public init(id: Int) { self.id = id } + } + @JS public func makeLocal() -> Vector3D { Vector3D(id: 42) } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + // Local declaration wins. + #expect(app.usedExternalModules == []) + let exported = try #require(app.exported) + #expect(exported.structs.contains(where: { $0.name == "Vector3D" })) + } + + @Test + func unknownTypeEmitsHintMentioningDependencyTargets() throws { + do { + _ = try resolveApp( + source: """ + @JS public func use() -> MissingType { fatalError() } + """, + dependencies: [] + ) + Issue.record("Expected an unsupported-type diagnostic") + } catch let error as BridgeJSCoreDiagnosticError { + let combinedHints = error.diagnostics.compactMap(\.diagnostic.hint).joined(separator: "\n") + #expect(combinedHints.contains("dependency targets")) + } + } + + // MARK: - Coverage across type categories + + @Test + func resolvesExternalSimpleEnum() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public enum Direction { case north, south }" + ) + let app = try resolveApp( + source: """ + import Core + @JS public func opposite(_ d: Direction) -> Direction { d } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let function = try #require(app.exported?.functions.first(where: { $0.name == "opposite" })) + #expect(function.returnType == .caseEnum("Direction")) + #expect(function.parameters.first?.type == .caseEnum("Direction")) + } + + @Test + func resolvesExternalRawValueEnum() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public enum HTTPMethod: String { case get, post }" + ) + let app = try resolveApp( + source: """ + import Core + @JS public func describe(_ m: HTTPMethod) -> String { "" } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let function = try #require(app.exported?.functions.first(where: { $0.name == "describe" })) + #expect(function.parameters.first?.type == .rawValueEnum("HTTPMethod", .string)) + } + + @Test + func resolvesExternalAssociatedValueEnum() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public enum Shape { case point, circle(radius: Double) }" + ) + let app = try resolveApp( + source: """ + import Core + @JS public func area(_ s: Shape) -> Double { 0 } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let function = try #require(app.exported?.functions.first(where: { $0.name == "area" })) + #expect(function.parameters.first?.type == .associatedValueEnum("Shape")) + } + + @Test + func resolvesExternalNamespaceEnum() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: """ + @JS public enum Utils { + @JS public static func hello() -> String { "hi" } + } + """ + ) + let app = try resolveApp( + source: """ + import Core + @JS public func dummy(_ u: Utils?) -> Utils? { u } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let function = try #require(app.exported?.functions.first(where: { $0.name == "dummy" })) + #expect(function.returnType == .nullable(.namespaceEnum("Utils"), .null)) + } + + // MARK: - Structural positions + + @Test + func resolvesExternalInDictionaryValuePosition() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + let app = try resolveApp( + source: """ + import Core + @JS public func names(_ map: [String: Vector3D]) -> [String] { [] } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let function = try #require(app.exported?.functions.first(where: { $0.name == "names" })) + #expect(function.parameters.first?.type == .dictionary(.swiftStruct("Vector3D"))) + } + + @Test + func resolvesExternalInStructPropertyType() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + let app = try resolveApp( + source: """ + import Core + @JS public struct Particle { + public let position: Vector3D + @JS public init(position: Vector3D) { self.position = position } + } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let particle = try #require(app.exported?.structs.first(where: { $0.name == "Particle" })) + let positionProperty = try #require(particle.properties.first(where: { $0.name == "position" })) + #expect(positionProperty.type == .swiftStruct("Vector3D")) + #expect(app.usedExternalModules == ["Core"]) + } + + // MARK: - Multi-module scenarios + + @Test + func tracksMultipleExternalModulesInSortedOrder() throws { + let alpha = try buildDependencySkeleton( + moduleName: "Alpha", + source: "@JS public struct A { @JS public init() {} }" + ) + let beta = try buildDependencySkeleton( + moduleName: "Beta", + source: "@JS public struct B { @JS public init() {} }" + ) + let app = try resolveApp( + source: """ + import Alpha + import Beta + @JS public func both(_ a: A, _ b: B) -> String { "" } + """, + dependencies: [ + (moduleName: "Beta", skeleton: beta), + (moduleName: "Alpha", skeleton: alpha), + ] + ) + #expect(app.usedExternalModules == ["Alpha", "Beta"]) + } + + @Test + func transitiveDependencyTypesResolve() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + let domain = try buildDependencySkeleton( + moduleName: "Domain", + source: """ + @JS public struct Particle { + public let position: Vector3D + @JS public init(position: Vector3D) { self.position = position } + } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + #expect(domain.usedExternalModules == ["Core"]) + // App can still reference Vector3D through Domain’s transitive dependency on Core. + let app = try resolveApp( + source: """ + import Core + import Domain + @JS public func position(of p: Particle) -> Vector3D { p.position } + """, + dependencies: [ + (moduleName: "Core", skeleton: core), + (moduleName: "Domain", skeleton: domain), + ] + ) + let function = try #require(app.exported?.functions.first(where: { $0.name == "position" })) + #expect(function.returnType == .swiftStruct("Vector3D")) + #expect(function.parameters.first?.type == .swiftStruct("Particle")) + #expect(app.usedExternalModules == ["Core", "Domain"]) + } + + // MARK: - Skeleton serialisation round-trip + + @Test + func skeletonRoundTripsUsedExternalModules() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + let app = try resolveApp( + source: """ + import Core + @JS public func origin() -> Vector3D { Vector3D() } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + let encoder = JSONEncoder() + encoder.outputFormatting = [.sortedKeys] + let data = try encoder.encode(app) + let decoded = try JSONDecoder().decode(BridgeJSSkeleton.self, from: data) + #expect(decoded.usedExternalModules == app.usedExternalModules) + #expect(decoded.moduleName == app.moduleName) + } + + @Test + func externalModuleIndexSkipsDependenciesWithoutExportedTypes() throws { + let empty = BridgeJSSkeleton(moduleName: "Empty") + let index = ExternalModuleIndex(dependencies: [(moduleName: "Empty", skeleton: empty)]) + #expect(index.isEmpty) + #expect(!index.isKnownModule("Empty")) + #expect(index.lookup(dotPath: "Whatever") == nil) + } + + @Test + func moduleQualifierRejectsUnknownModule() throws { + let core = try buildDependencySkeleton( + moduleName: "Core", + source: "@JS public struct Vector3D { @JS public init() {} }" + ) + do { + _ = try resolveApp( + source: """ + import Core + @JS public func useFoundation() -> Foundation.URL { fatalError() } + """, + dependencies: [(moduleName: "Core", skeleton: core)] + ) + Issue.record("Expected unsupported-type diagnostic for Foundation.URL") + } catch let error as BridgeJSCoreDiagnosticError { + let combinedMessages = error.diagnostics.map(\.diagnostic.message).joined(separator: "\n") + #expect(combinedMessages.contains("Foundation.URL")) + } + } + + // MARK: - Utillites + + private func resolveApp( + source appSource: String, + dependencies: [(moduleName: String, skeleton: BridgeJSSkeleton)] + ) throws -> BridgeJSSkeleton { + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "App", + exposeToGlobal: false, + externalModuleIndex: ExternalModuleIndex(dependencies: dependencies) + ) + let sourceFile = Parser.parse(source: appSource) + swiftAPI.addSourceFile(sourceFile, inputFilePath: "App.swift") + return try swiftAPI.finalize() + } + + private func buildDependencySkeleton( + moduleName: String, + source: String, + dependencies: [(moduleName: String, skeleton: BridgeJSSkeleton)] = [] + ) throws -> BridgeJSSkeleton { + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: moduleName, + exposeToGlobal: false, + externalModuleIndex: ExternalModuleIndex(dependencies: dependencies) + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "\(moduleName).swift") + return try swiftAPI.finalize() + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift index 500a5db95..ae12b6566 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift @@ -3,6 +3,7 @@ import SwiftSyntax import Testing @testable import BridgeJSCore +@testable import BridgeJSSkeleton @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. @@ -165,6 +166,194 @@ import Testing #expect(description.contains(":2:")) } + // MARK: - Nested type validation + + @Test + func nestedStructInsideClassSucceeds() throws { + let source = """ + @JS class User { + @JS struct Stats { + var health: Int + } + } + """ + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "test.swift") + let skeleton = try swiftAPI.finalize() + #expect(skeleton.exported != nil) + let structs = skeleton.exported?.structs ?? [] + #expect(structs.count == 1) + #expect(structs.first?.swiftCallName == "User.Stats") + } + + @Test + func nestedClassInsideStructSucceeds() throws { + let source = """ + @JS struct Container { + var value: Int + @JS class Inner { + } + } + """ + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "test.swift") + let skeleton = try swiftAPI.finalize() + #expect(skeleton.exported != nil) + let classes = skeleton.exported?.classes ?? [] + #expect(classes.count == 1) + #expect(classes.first?.swiftCallName == "Container.Inner") + } + + @Test + func structInsideEnumNamespaceSucceeds() throws { + let source = """ + @JS enum API { + @JS struct Point { + var x: Double + var y: Double + } + } + """ + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "test.swift") + let skeleton = try swiftAPI.finalize() + #expect(skeleton.exported != nil) + } + + // MARK: - Struct init order validation + + @Test + func structInitMismatchedOrderProducesDiagnostic() throws { + let source = """ + @JS struct Animal { + var size: Double + var age: Int + + @JS init(age: Int, size: Double) { + self.age = age + self.size = size + } + } + """ + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "test.swift") + #expect(throws: BridgeJSCoreDiagnosticError.self) { + _ = try swiftAPI.finalize() + } + } + + @Test + func structInitMatchingOrderSucceeds() throws { + let source = """ + @JS struct Point { + var x: Double + var y: Double + + @JS init(x: Double, y: Double) { + self.x = x + self.y = y + } + } + """ + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "test.swift") + let skeleton = try swiftAPI.finalize() + #expect(skeleton.exported != nil) + } + + @Test + func structWithoutExplicitInitSucceeds() throws { + let source = """ + @JS struct Point { + var x: Double + var y: Double + } + """ + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "test.swift") + let skeleton = try swiftAPI.finalize() + #expect(skeleton.exported != nil) + } + + // MARK: - Async return validation + + @Test + func asyncReturnOfUnsupportedTypeIsDiagnosed() throws { + // Protocol existentials still can't be lowered through the imported-parameter ABI, so + // an async return of one must still be diagnosed. + let source = """ + @JS protocol PayloadDelegate { + func notify() + } + @JS func loadPayload() async -> PayloadDelegate { + fatalError() + } + """ + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "test.swift") + let skeleton = try swiftAPI.finalize() + let exported = try #require(skeleton.exported) + let exportSwift = ExportSwift(progress: .silent, moduleName: skeleton.moduleName, skeleton: exported) + #expect(throws: BridgeJSCoreError.self) { + _ = try exportSwift.finalize() + } + } + + @Test + func asyncReturnOfConvertibleTypeSucceeds() throws { + let source = """ + @JS func loadCount() async -> Int { + 1 + } + """ + let swiftAPI = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + swiftAPI.addSourceFile(Parser.parse(source: source), inputFilePath: "test.swift") + let skeleton = try swiftAPI.finalize() + let exported = try #require(skeleton.exported) + let exportSwift = ExportSwift(progress: .silent, moduleName: skeleton.moduleName, skeleton: exported) + #expect(try exportSwift.finalize() != nil) + } + @Test func omitsNextLineWhenErrorIsOnLastLine() throws { let source = """ diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Async.swift index 214331b32..742d96ed2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Async.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Async.swift @@ -17,3 +17,70 @@ @JS func asyncRoundTripJSObject(_ v: JSObject) async -> JSObject { return v } + +@JS struct AsyncPoint { + var x: Int + var y: Int +} + +@JS func asyncRoundTripStruct(_ v: AsyncPoint) async -> AsyncPoint { + return v +} + +@JS func asyncRoundTripStructThrows(_ v: AsyncPoint) async throws(JSException) -> AsyncPoint { + return v +} + +@JS func asyncThrowsZeroArg() async throws(JSException) -> String { + return "ok" +} + +@JS func asyncCombineStructs(_ a: AsyncPoint, _ b: AsyncPoint) async -> AsyncPoint { + return AsyncPoint(x: a.x + b.x, y: a.y + b.y) +} + +@JS enum AsyncDirection { + case north + case south +} + +@JS func asyncRoundTripEnum(_ v: AsyncDirection) async -> AsyncDirection { + return v +} + +@JS enum AsyncTheme: String { + case light + case dark +} + +@JS func asyncRoundTripRawEnum(_ v: AsyncTheme) async -> AsyncTheme { + return v +} + +@JS func asyncRoundTripOptionalEnum(_ v: AsyncDirection?) async -> AsyncDirection? { + return v +} + +@JS func asyncRoundTripOptionalRawEnum(_ v: AsyncTheme?) async -> AsyncTheme? { + return v +} + +@JS func asyncRoundTripOptionalStruct(_ v: AsyncPoint?) async -> AsyncPoint? { + return v +} + +@JS func asyncRoundTripStructArray(_ v: [AsyncPoint]) async -> [AsyncPoint] { + return v +} + +@JS func asyncRoundTripEnumArray(_ v: [AsyncDirection]) async -> [AsyncDirection] { + return v +} + +@JS func asyncRoundTripStructDictionary(_ v: [String: AsyncPoint]) async -> [String: AsyncPoint] { + return v +} + +@JS func asyncRoundTripEnumDictionary(_ v: [String: AsyncDirection]) async -> [String: AsyncDirection] { + return v +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/AsyncAssociatedValueEnum.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/AsyncAssociatedValueEnum.swift new file mode 100644 index 000000000..662e01fce --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/AsyncAssociatedValueEnum.swift @@ -0,0 +1,13 @@ +@JS enum AsyncPayloadResult { + case success(String) + case failure(Int) + case idle +} + +@JS func asyncRoundTripAssociatedValueEnum(_ value: AsyncPayloadResult) async -> AsyncPayloadResult { + return value +} + +@JS func asyncRoundTripOptionalAssociatedValueEnum(_ value: AsyncPayloadResult?) async -> AsyncPayloadResult? { + return value +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValueImport.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValueImport.swift new file mode 100644 index 000000000..aa404b72c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValueImport.swift @@ -0,0 +1,14 @@ +@JS enum PayloadSignal { + case start(String) + case stop(Int) + case idle +} + +// Associated-value enums bridge as their `Int32` case ID plus stack payload in imported +// function parameters and return values. +@JSClass struct PayloadSignalControls { + @JSFunction func send(_ signal: PayloadSignal) throws(JSException) + @JSFunction func current() throws(JSException) -> PayloadSignal + @JSFunction static func roundTrip(_ signal: PayloadSignal) throws(JSException) -> PayloadSignal + @JSFunction func roundTripOptional(_ signal: PayloadSignal?) throws(JSException) -> PayloadSignal? +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumCaseImport.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumCaseImport.swift new file mode 100644 index 000000000..a6477be95 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumCaseImport.swift @@ -0,0 +1,12 @@ +@JS enum Signal { + case start + case stop +} + +// Case enums (no raw value) bridge as their `Int32` tag as imported-function +// parameters and return values. +@JSClass struct SignalControls { + @JSFunction func send(_ signal: Signal) throws(JSException) + @JSFunction func current() throws(JSException) -> Signal + @JSFunction static func roundTrip(_ signal: Signal) throws(JSException) -> Signal +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSTypedArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSTypedArrayTypes.swift new file mode 100644 index 000000000..7f308f560 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSTypedArrayTypes.swift @@ -0,0 +1,19 @@ +import JavaScriptKit + +// Using typealiases +@JS func processBytes(_ data: JSUint8Array) -> JSUint8Array { + return data +} + +@JS func processFloats(_ data: JSFloat32Array) -> JSFloat32Array { + return data +} + +// Using generic form directly +@JS func processGenericDoubles(_ data: JSTypedArray) -> JSTypedArray { + return data +} + +@JS func processGenericInts(_ data: JSTypedArray) -> JSTypedArray { + return data +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/NestedType.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/NestedType.swift new file mode 100644 index 000000000..12fccb379 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/NestedType.swift @@ -0,0 +1,21 @@ +@JS class User { + @JS func getName() -> String { + return "test" + } + + @JS struct Stats { + var health: Int + var score: Double + } +} + +@JS class Player { + @JS func getTag() -> String { + return "player" + } + + @JS struct Stats { + var level: Int + var rating: String + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Optionals.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Optionals.swift index 927fac6a0..ea37f5740 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Optionals.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Optionals.swift @@ -30,6 +30,13 @@ class OptionalPropertyHolder { @JS func testOptionalPropertyRoundtrip(_ holder: OptionalPropertyHolder?) -> OptionalPropertyHolder? +// Exported functions taking an optional jsObject use the direct (isSome, objId) +// parameter ABI; the return value travels through the stack ABI. +@JS func roundTripExportedOptionalJSObject(value: JSObject?) -> JSObject? + +// Exported function taking/returning an optional imported @JSClass (issue #751). +@JS func roundTripExportedOptionalJSClass(value: WithOptionalJSClass?) -> WithOptionalJSClass? + @JS func roundTripString(name: String?) -> String? { return name @@ -155,4 +162,10 @@ func testMixedOptionals(firstName: String?, lastName: String?, age: Int?, active @JSSetter func setIntOrUndefined(_ value: JSUndefinedOr) throws(JSException) @JSFunction func roundTripIntOrNull(value: Int?) throws(JSException) -> Int? @JSFunction func roundTripIntOrUndefined(value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr + + @JSGetter var childOrNull: WithOptionalJSClass? + @JSSetter func setChildOrNull(_ value: WithOptionalJSClass?) throws(JSException) + @JSFunction func roundTripChildOrNull( + value: WithOptionalJSClass? + ) throws(JSException) -> WithOptionalJSClass? } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift index 791b1b7a9..6872d7989 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftClosure.swift @@ -8,10 +8,21 @@ import JavaScriptKit } } +@JS public struct Animal { + public let type: String + + @JS public init(type: String) { + self.type = type + } +} + @JS class TestProcessor { @JS init(transform: @escaping (String) -> String) {} } +@JS func roundtripAnimal(_ animalClosure: (Animal) -> Animal) -> (Animal) -> Animal +@JS func roundtripOptionalAnimal(_ animalClosure: (Animal?) -> Animal?) -> (Animal?) -> Animal? + @JS func roundtripString(_ stringClosure: (String) -> String) -> (String) -> String @JS func roundtripInt(_ intClosure: (Int) -> Int) -> (Int) -> Int @JS func roundtripBool(_ boolClosure: (Bool) -> Bool) -> (Bool) -> Bool diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStructImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStructImports.swift index b00fd768a..a1eed686a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStructImports.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftStructImports.swift @@ -5,3 +5,5 @@ struct Point { } @JSFunction func translate(_ point: Point, dx: Int, dy: Int) throws(JSException) -> Point + +@JSFunction func roundTripOptional(_ point: Point?) throws(JSException) -> Point? diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftTypedClosureAccess.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftTypedClosureAccess.swift new file mode 100644 index 000000000..6487d343b --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/SwiftTypedClosureAccess.swift @@ -0,0 +1,26 @@ +// Verifies that `JSTypedClosure` initializers synthesized by BridgeJS adopt the +// access level of the originating `@JSClass`/`@JSFunction` surface, so that +// downstream targets can construct typed closures for public APIs (issue #709). + +@JSClass(jsName: "PublicEvent") public struct JSPublicEvent {} +@JSClass(jsName: "PackageEvent") package struct JSPackageEvent {} +@JSClass(jsName: "InternalEvent") struct JSInternalEvent {} + +@JSClass(jsName: "PublicTarget") public struct JSPublicTarget { + // A public method taking a typed closure must yield a `public` synthesized init, + // since downstream modules may construct the closure value. + @JSFunction public func addPublicListener(_ handler: JSTypedClosure<(JSPublicEvent) -> Void>) throws(JSException) + // Same closure shape on an internal method — the synthesized init merges to public, + // because at most one extension per signature is generated. + @JSFunction func addInternalListener(_ handler: JSTypedClosure<(JSPublicEvent) -> Void>) throws(JSException) +} + +@JSClass(jsName: "PackageTarget") package struct JSPackageTarget { + // A package-level surface yields a `package` synthesized init. + @JSFunction package func addPackageListener(_ handler: JSTypedClosure<(JSPackageEvent) -> Void>) throws(JSException) +} + +@JSClass(jsName: "InternalTarget") struct JSInternalTarget { + // No public/package surface for this signature — the synthesized init stays internal. + @JSFunction func addInternalListener(_ handler: JSTypedClosure<(JSInternalEvent) -> Void>) throws(JSException) +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.json index d071d8c52..d4ac7a15f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ArrayTypes.json @@ -1331,6 +1331,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1354,6 +1355,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1385,6 +1387,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1412,6 +1415,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1432,6 +1436,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1463,6 +1468,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1494,6 +1500,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1531,5 +1538,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index a2b95cc24..8684291f0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.json @@ -4,7 +4,59 @@ ], "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "north" + }, + { + "associatedValues" : [ + + ], + "name" : "south" + } + ], + "emitStyle" : "const", + "name" : "AsyncDirection", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AsyncDirection", + "tsFullPath" : "AsyncDirection" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "light" + }, + { + "associatedValues" : [ + + ], + "name" : "dark" + } + ], + "emitStyle" : "const", + "name" : "AsyncTheme", + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + ], + "swiftCallName" : "AsyncTheme", + "tsFullPath" : "AsyncTheme" + } ], "exposeToGlobal" : false, "functions" : [ @@ -180,14 +232,443 @@ } } + }, + { + "abiName" : "bjs_asyncRoundTripStruct", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripStruct", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripStructThrows", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "asyncRoundTripStructThrows", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + }, + { + "abiName" : "bjs_asyncThrowsZeroArg", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "asyncThrowsZeroArg", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_asyncCombineStructs", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncCombineStructs", + "parameters" : [ + { + "label" : "_", + "name" : "a", + "type" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + }, + { + "label" : "_", + "name" : "b", + "type" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripEnum", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "caseEnum" : { + "_0" : "AsyncDirection" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "AsyncDirection" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripRawEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripRawEnum", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "rawValueEnum" : { + "_0" : "AsyncTheme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "AsyncTheme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripOptionalEnum", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "AsyncDirection" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "AsyncDirection" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalRawEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripOptionalRawEnum", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "AsyncTheme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "AsyncTheme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalStruct", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripOptionalStruct", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripStructArray", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripStructArray", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + } + } + }, + { + "abiName" : "bjs_asyncRoundTripEnumArray", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripEnumArray", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "AsyncDirection" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "AsyncDirection" + } + } + } + } + }, + { + "abiName" : "bjs_asyncRoundTripStructDictionary", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripStructDictionary", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "dictionary" : { + "_0" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "swiftStruct" : { + "_0" : "AsyncPoint" + } + } + } + } + }, + { + "abiName" : "bjs_asyncRoundTripEnumDictionary", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripEnumDictionary", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "dictionary" : { + "_0" : { + "caseEnum" : { + "_0" : "AsyncDirection" + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "caseEnum" : { + "_0" : "AsyncDirection" + } + } + } + } } ], "protocols" : [ ], "structs" : [ + { + "methods" : [ + ], + "name" : "AsyncPoint", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "x", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "y", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "swiftCallName" : "AsyncPoint" + } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index f5230f213..661fbd3a5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift @@ -1,11 +1,96 @@ +extension AsyncDirection: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> AsyncDirection { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> AsyncDirection { + return AsyncDirection(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + @_spi(BridgeJS) @usableFromInline init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .north + case 1: + self = .south + default: + return nil + } + } + + @_spi(BridgeJS) @usableFromInline var bridgeJSRawValue: Int32 { + switch self { + case .north: + return 0 + case .south: + return 1 + } + } +} + +extension AsyncTheme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension AsyncPoint: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> AsyncPoint { + let y = Int.bridgeJSStackPop() + let x = Int.bridgeJSStackPop() + return AsyncPoint(x: x, y: y) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.x.bridgeJSStackPush() + self.y.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_AsyncPoint(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_AsyncPoint())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_AsyncPoint") +fileprivate func _bjs_struct_lower_AsyncPoint_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_AsyncPoint_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_AsyncPoint(_ objectId: Int32) -> Void { + return _bjs_struct_lower_AsyncPoint_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_AsyncPoint") +fileprivate func _bjs_struct_lift_AsyncPoint_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_AsyncPoint_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_AsyncPoint() -> Int32 { + return _bjs_struct_lift_AsyncPoint_extern() +} + @_expose(wasm, "bjs_asyncReturnVoid") @_cdecl("bjs_asyncReturnVoid") public func _bjs_asyncReturnVoid() -> Int32 { #if arch(wasm32) - let ret = JSPromise.async { + return _bjs_makePromise(resolve: Promise_resolve_y, reject: Promise_reject) { await asyncReturnVoid() - }.jsObject - return ret.bridgeJSLowerReturn() + } #else fatalError("Only available on WebAssembly") #endif @@ -15,10 +100,9 @@ public func _bjs_asyncReturnVoid() -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_Si, reject: Promise_reject) { + return await asyncRoundTripInt(_: Int.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -28,10 +112,9 @@ public func _bjs_asyncRoundTripInt(_ v: Int32) -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_SS, reject: Promise_reject) { + return await asyncRoundTripString(_: String.bridgeJSLiftParameter(vBytes, vLength)) + } #else fatalError("Only available on WebAssembly") #endif @@ -41,10 +124,9 @@ public func _bjs_asyncRoundTripString(_ vBytes: Int32, _ vLength: Int32) -> Int3 @_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() + return _bjs_makePromise(resolve: Promise_resolve_Sb, reject: Promise_reject) { + return await asyncRoundTripBool(_: Bool.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -54,10 +136,9 @@ public func _bjs_asyncRoundTripBool(_ v: Int32) -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_Sf, reject: Promise_reject) { + return await asyncRoundTripFloat(_: Float.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -67,10 +148,9 @@ public func _bjs_asyncRoundTripFloat(_ v: Float32) -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_Sd, reject: Promise_reject) { + return await asyncRoundTripDouble(_: Double.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -80,11 +160,557 @@ public func _bjs_asyncRoundTripDouble(_ v: Float64) -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_8JSObjectC, reject: Promise_reject) { + return await asyncRoundTripJSObject(_: JSObject.bridgeJSLiftParameter(v)) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripStruct") +@_cdecl("bjs_asyncRoundTripStruct") +public func _bjs_asyncRoundTripStruct() -> Int32 { + #if arch(wasm32) + let _tmp_v = AsyncPoint.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_10AsyncPointV, reject: Promise_reject) { + return await asyncRoundTripStruct(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripStructThrows") +@_cdecl("bjs_asyncRoundTripStructThrows") +public func _bjs_asyncRoundTripStructThrows() -> Int32 { + #if arch(wasm32) + let _tmp_v = AsyncPoint.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_10AsyncPointV, reject: Promise_reject) { () async throws(JSException) -> AsyncPoint in + return try await asyncRoundTripStructThrows(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncThrowsZeroArg") +@_cdecl("bjs_asyncThrowsZeroArg") +public func _bjs_asyncThrowsZeroArg() -> Int32 { + #if arch(wasm32) + let __bjs_capture = 0 + return _bjs_makePromise(resolve: Promise_resolve_SS, reject: Promise_reject) { [__bjs_capture] () async throws(JSException) -> String in + _ = __bjs_capture + return try await asyncThrowsZeroArg() + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncCombineStructs") +@_cdecl("bjs_asyncCombineStructs") +public func _bjs_asyncCombineStructs() -> Int32 { + #if arch(wasm32) + let _tmp_b = AsyncPoint.bridgeJSLiftParameter() + let _tmp_a = AsyncPoint.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_10AsyncPointV, reject: Promise_reject) { + return await asyncCombineStructs(_: _tmp_a, _: _tmp_b) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripEnum") +@_cdecl("bjs_asyncRoundTripEnum") +public func _bjs_asyncRoundTripEnum(_ v: Int32) -> Int32 { + #if arch(wasm32) + return _bjs_makePromise(resolve: Promise_resolve_14AsyncDirectionO, reject: Promise_reject) { + return await asyncRoundTripEnum(_: AsyncDirection.bridgeJSLiftParameter(v)) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripRawEnum") +@_cdecl("bjs_asyncRoundTripRawEnum") +public func _bjs_asyncRoundTripRawEnum(_ vBytes: Int32, _ vLength: Int32) -> Int32 { + #if arch(wasm32) + return _bjs_makePromise(resolve: Promise_resolve_10AsyncThemeO, reject: Promise_reject) { + return await asyncRoundTripRawEnum(_: AsyncTheme.bridgeJSLiftParameter(vBytes, vLength)) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripOptionalEnum") +@_cdecl("bjs_asyncRoundTripOptionalEnum") +public func _bjs_asyncRoundTripOptionalEnum(_ vIsSome: Int32, _ vValue: Int32) -> Int32 { + #if arch(wasm32) + return _bjs_makePromise(resolve: Promise_resolve_Sq14AsyncDirectionO, reject: Promise_reject) { + return await asyncRoundTripOptionalEnum(_: Optional.bridgeJSLiftParameter(vIsSome, vValue)) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripOptionalRawEnum") +@_cdecl("bjs_asyncRoundTripOptionalRawEnum") +public func _bjs_asyncRoundTripOptionalRawEnum(_ vIsSome: Int32, _ vBytes: Int32, _ vLength: Int32) -> Int32 { + #if arch(wasm32) + return _bjs_makePromise(resolve: Promise_resolve_Sq10AsyncThemeO, reject: Promise_reject) { + return await asyncRoundTripOptionalRawEnum(_: Optional.bridgeJSLiftParameter(vIsSome, vBytes, vLength)) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripOptionalStruct") +@_cdecl("bjs_asyncRoundTripOptionalStruct") +public func _bjs_asyncRoundTripOptionalStruct() -> Int32 { + #if arch(wasm32) + let _tmp_v = Optional.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_Sq10AsyncPointV, reject: Promise_reject) { + return await asyncRoundTripOptionalStruct(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripStructArray") +@_cdecl("bjs_asyncRoundTripStructArray") +public func _bjs_asyncRoundTripStructArray() -> Int32 { + #if arch(wasm32) + let _tmp_v = [AsyncPoint].bridgeJSStackPop() + return _bjs_makePromise(resolve: Promise_resolve_Sa10AsyncPointV, reject: Promise_reject) { + return await asyncRoundTripStructArray(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripEnumArray") +@_cdecl("bjs_asyncRoundTripEnumArray") +public func _bjs_asyncRoundTripEnumArray() -> Int32 { + #if arch(wasm32) + let _tmp_v = [AsyncDirection].bridgeJSStackPop() + return _bjs_makePromise(resolve: Promise_resolve_Sa14AsyncDirectionO, reject: Promise_reject) { + return await asyncRoundTripEnumArray(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripStructDictionary") +@_cdecl("bjs_asyncRoundTripStructDictionary") +public func _bjs_asyncRoundTripStructDictionary() -> Int32 { + #if arch(wasm32) + let _tmp_v = [String: AsyncPoint].bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_SD10AsyncPointV, reject: Promise_reject) { + return await asyncRoundTripStructDictionary(_: _tmp_v) + } #else fatalError("Only available on WebAssembly") #endif +} + +@_expose(wasm, "bjs_asyncRoundTripEnumDictionary") +@_cdecl("bjs_asyncRoundTripEnumDictionary") +public func _bjs_asyncRoundTripEnumDictionary() -> Int32 { + #if arch(wasm32) + let _tmp_v = [String: AsyncDirection].bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_SD14AsyncDirectionO, reject: Promise_reject) { + return await asyncRoundTripEnumDictionary(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@JSFunction func Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_reject_TestModule") +fileprivate func promise_reject_TestModule_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void +#else +fileprivate func promise_reject_TestModule_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_reject_TestModule(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + return promise_reject_TestModule_extern(promise, valueKind, valuePayload1, valuePayload2) +} + +func _$Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueKind, valuePayload1, valuePayload2) = value.bridgeJSLowerParameter() + promise_reject_TestModule(promiseValue, valueKind, valuePayload1, valuePayload2) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_y(_ promise: JSObject) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_y") +fileprivate func promise_resolve_TestModule_y_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_y_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_y(_ promise: Int32) -> Void { + return promise_resolve_TestModule_y_extern(promise) +} + +func _$Promise_resolve_y(_ promise: JSObject) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + promise_resolve_TestModule_y(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Si(_ promise: JSObject, _ value: Int) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Si") +fileprivate func promise_resolve_TestModule_Si_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Si_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Si(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_TestModule_Si_extern(promise, value) +} + +func _$Promise_resolve_Si(_ promise: JSObject, _ value: Int) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Si(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_SS(_ promise: JSObject, _ value: String) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_SS") +fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_SS(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + return promise_resolve_TestModule_SS_extern(promise, valueBytes, valueLength) +} + +func _$Promise_resolve_SS(_ promise: JSObject, _ value: String) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + promise_resolve_TestModule_SS(promiseValue, valueBytes, valueLength) + } + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sb(_ promise: JSObject, _ value: Bool) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sb") +fileprivate func promise_resolve_TestModule_Sb_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sb_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sb(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_TestModule_Sb_extern(promise, value) +} + +func _$Promise_resolve_Sb(_ promise: JSObject, _ value: Bool) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sb(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sf(_ promise: JSObject, _ value: Float) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sf") +fileprivate func promise_resolve_TestModule_Sf_extern(_ promise: Int32, _ value: Float32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sf_extern(_ promise: Int32, _ value: Float32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sf(_ promise: Int32, _ value: Float32) -> Void { + return promise_resolve_TestModule_Sf_extern(promise, value) +} + +func _$Promise_resolve_Sf(_ promise: JSObject, _ value: Float) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sf(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sd(_ promise: JSObject, _ value: Double) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sd") +fileprivate func promise_resolve_TestModule_Sd_extern(_ promise: Int32, _ value: Float64) -> Void +#else +fileprivate func promise_resolve_TestModule_Sd_extern(_ promise: Int32, _ value: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sd(_ promise: Int32, _ value: Float64) -> Void { + return promise_resolve_TestModule_Sd_extern(promise, value) +} + +func _$Promise_resolve_Sd(_ promise: JSObject, _ value: Double) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sd(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_8JSObjectC(_ promise: JSObject, _ value: JSObject) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_8JSObjectC") +fileprivate func promise_resolve_TestModule_8JSObjectC_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_8JSObjectC_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_8JSObjectC(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_TestModule_8JSObjectC_extern(promise, value) +} + +func _$Promise_resolve_8JSObjectC(_ promise: JSObject, _ value: JSObject) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_TestModule_8JSObjectC(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_10AsyncPointV(_ promise: JSObject, _ value: AsyncPoint) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_10AsyncPointV") +fileprivate func promise_resolve_TestModule_10AsyncPointV_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_10AsyncPointV_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_10AsyncPointV(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_TestModule_10AsyncPointV_extern(promise, value) +} + +func _$Promise_resolve_10AsyncPointV(_ promise: JSObject, _ value: AsyncPoint) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueObjectId = value.bridgeJSLowerParameter() + promise_resolve_TestModule_10AsyncPointV(promiseValue, valueObjectId) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_14AsyncDirectionO(_ promise: JSObject, _ value: AsyncDirection) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_14AsyncDirectionO") +fileprivate func promise_resolve_TestModule_14AsyncDirectionO_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_14AsyncDirectionO_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_14AsyncDirectionO(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_TestModule_14AsyncDirectionO_extern(promise, value) +} + +func _$Promise_resolve_14AsyncDirectionO(_ promise: JSObject, _ value: AsyncDirection) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_TestModule_14AsyncDirectionO(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_10AsyncThemeO(_ promise: JSObject, _ value: AsyncTheme) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_10AsyncThemeO") +fileprivate func promise_resolve_TestModule_10AsyncThemeO_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_10AsyncThemeO_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_10AsyncThemeO(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + return promise_resolve_TestModule_10AsyncThemeO_extern(promise, valueBytes, valueLength) +} + +func _$Promise_resolve_10AsyncThemeO(_ promise: JSObject, _ value: AsyncTheme) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + promise_resolve_TestModule_10AsyncThemeO(promiseValue, valueBytes, valueLength) + } + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq14AsyncDirectionO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sq14AsyncDirectionO") +fileprivate func promise_resolve_TestModule_Sq14AsyncDirectionO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sq14AsyncDirectionO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sq14AsyncDirectionO(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + return promise_resolve_TestModule_Sq14AsyncDirectionO_extern(promise, valueIsSome, valueValue) +} + +func _$Promise_resolve_Sq14AsyncDirectionO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sq14AsyncDirectionO(promiseValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq10AsyncThemeO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sq10AsyncThemeO") +fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + return promise_resolve_TestModule_Sq10AsyncThemeO_extern(promise, valueIsSome, valueBytes, valueLength) +} + +func _$Promise_resolve_Sq10AsyncThemeO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in + promise_resolve_TestModule_Sq10AsyncThemeO(promiseValue, valueIsSome, valueBytes, valueLength) + } + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq10AsyncPointV(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sq10AsyncPointV") +fileprivate func promise_resolve_TestModule_Sq10AsyncPointV_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sq10AsyncPointV_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sq10AsyncPointV(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_TestModule_Sq10AsyncPointV_extern(promise, value) +} + +func _$Promise_resolve_Sq10AsyncPointV(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueIsSome = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sq10AsyncPointV(promiseValue, valueIsSome) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sa10AsyncPointV(_ promise: JSObject, _ value: [AsyncPoint]) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sa10AsyncPointV") +fileprivate func promise_resolve_TestModule_Sa10AsyncPointV_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sa10AsyncPointV_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sa10AsyncPointV(_ promise: Int32) -> Void { + return promise_resolve_TestModule_Sa10AsyncPointV_extern(promise) +} + +func _$Promise_resolve_Sa10AsyncPointV(_ promise: JSObject, _ value: [AsyncPoint]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sa10AsyncPointV(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sa14AsyncDirectionO(_ promise: JSObject, _ value: [AsyncDirection]) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sa14AsyncDirectionO") +fileprivate func promise_resolve_TestModule_Sa14AsyncDirectionO_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sa14AsyncDirectionO_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sa14AsyncDirectionO(_ promise: Int32) -> Void { + return promise_resolve_TestModule_Sa14AsyncDirectionO_extern(promise) +} + +func _$Promise_resolve_Sa14AsyncDirectionO(_ promise: JSObject, _ value: [AsyncDirection]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sa14AsyncDirectionO(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_SD10AsyncPointV(_ promise: JSObject, _ value: [String: AsyncPoint]) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_SD10AsyncPointV") +fileprivate func promise_resolve_TestModule_SD10AsyncPointV_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_SD10AsyncPointV_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_SD10AsyncPointV(_ promise: Int32) -> Void { + return promise_resolve_TestModule_SD10AsyncPointV_extern(promise) +} + +func _$Promise_resolve_SD10AsyncPointV(_ promise: JSObject, _ value: [String: AsyncPoint]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_TestModule_SD10AsyncPointV(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_SD14AsyncDirectionO(_ promise: JSObject, _ value: [String: AsyncDirection]) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_SD14AsyncDirectionO") +fileprivate func promise_resolve_TestModule_SD14AsyncDirectionO_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_SD14AsyncDirectionO_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_SD14AsyncDirectionO(_ promise: Int32) -> Void { + return promise_resolve_TestModule_SD14AsyncDirectionO_extern(promise) +} + +func _$Promise_resolve_SD14AsyncDirectionO(_ promise: JSObject, _ value: [String: AsyncDirection]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_TestModule_SD14AsyncDirectionO(promiseValue) + if let error = _swift_js_take_exception() { throw error } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.json new file mode 100644 index 000000000..6b0d70453 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.json @@ -0,0 +1,129 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "AsyncPayloadResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AsyncPayloadResult", + "tsFullPath" : "AsyncPayloadResult" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_asyncRoundTripAssociatedValueEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripAssociatedValueEnum", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalAssociatedValueEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripOptionalAssociatedValueEnum", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.swift new file mode 100644 index 000000000..7ceb8cfe3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.swift @@ -0,0 +1,116 @@ +extension AsyncPayloadResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AsyncPayloadResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown AsyncPayloadResult 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 .idle: + return Int32(2) + } + } +} + +@_expose(wasm, "bjs_asyncRoundTripAssociatedValueEnum") +@_cdecl("bjs_asyncRoundTripAssociatedValueEnum") +public func _bjs_asyncRoundTripAssociatedValueEnum(_ value: Int32) -> Int32 { + #if arch(wasm32) + let _tmp_value = AsyncPayloadResult.bridgeJSLiftParameter(value) + return _bjs_makePromise(resolve: Promise_resolve_18AsyncPayloadResultO, reject: Promise_reject) { + return await asyncRoundTripAssociatedValueEnum(_: _tmp_value) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripOptionalAssociatedValueEnum") +@_cdecl("bjs_asyncRoundTripOptionalAssociatedValueEnum") +public func _bjs_asyncRoundTripOptionalAssociatedValueEnum(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 { + #if arch(wasm32) + let _tmp_value = Optional.bridgeJSLiftParameter(valueIsSome, valueCaseId) + return _bjs_makePromise(resolve: Promise_resolve_Sq18AsyncPayloadResultO, reject: Promise_reject) { + return await asyncRoundTripOptionalAssociatedValueEnum(_: _tmp_value) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@JSFunction func Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_reject_TestModule") +fileprivate func promise_reject_TestModule_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void +#else +fileprivate func promise_reject_TestModule_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_reject_TestModule(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + return promise_reject_TestModule_extern(promise, valueKind, valuePayload1, valuePayload2) +} + +func _$Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueKind, valuePayload1, valuePayload2) = value.bridgeJSLowerParameter() + promise_reject_TestModule(promiseValue, valueKind, valuePayload1, valuePayload2) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_18AsyncPayloadResultO") +fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_TestModule_18AsyncPayloadResultO_extern(promise, value) +} + +func _$Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueCaseId = value.bridgeJSLowerParameter() + promise_resolve_TestModule_18AsyncPayloadResultO(promiseValue, valueCaseId) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sq18AsyncPayloadResultO") +fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + return promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(promise, valueIsSome, valueCaseId) +} + +func _$Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueIsSome, valueCaseId) = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sq18AsyncPayloadResultO(promiseValue, valueIsSome, valueCaseId) + if let error = _swift_js_take_exception() { throw error } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncImport.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncImport.json index 263578d20..7f66bede4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncImport.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncImport.json @@ -4,6 +4,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -20,6 +21,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -49,6 +51,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -72,6 +75,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -95,6 +99,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -118,6 +123,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -147,5 +153,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncStaticImport.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncStaticImport.json index 972a532c6..2aea1c115 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncStaticImport.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncStaticImport.json @@ -7,6 +7,7 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -19,6 +20,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -42,6 +44,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -63,5 +66,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileExtension.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileExtension.json index f77d39ad9..4c8d575b0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileExtension.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileExtension.json @@ -78,5 +78,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 9b056b650..6c589de87 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.ReverseOrder.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.ReverseOrder.json @@ -148,5 +148,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index d76a1622d..9bec040f1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileFunctionTypes.json @@ -148,5 +148,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index a0c2c80c6..ff90a4cab 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileSkipsEmptySkeletons.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileSkipsEmptySkeletons.json @@ -4,6 +4,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -29,5 +30,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 59fb8484a..edf8177c1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.ReverseOrder.json @@ -61,5 +61,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index cc10331a4..58bfadab7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/CrossFileTypeResolution.json @@ -61,5 +61,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index f8a23c33d..e7874c072 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DefaultParameters.json @@ -1312,5 +1312,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index e18586e1c..b1185c644 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/DictionaryTypes.json @@ -300,6 +300,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -337,5 +338,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index b92cee954..873c5c49f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValue.json @@ -1455,5 +1455,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.json new file mode 100644 index 000000000..23cb1b0f0 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.json @@ -0,0 +1,194 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "start" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "stop" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "PayloadSignal", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "PayloadSignal", + "tsFullPath" : "PayloadSignal" + } + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "accessLevel" : "internal", + "getters" : [ + + ], + "methods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "send", + "parameters" : [ + { + "name" : "signal", + "type" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "current", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "roundTripOptional", + "parameters" : [ + { + "name" : "signal", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "PayloadSignalControls", + "setters" : [ + + ], + "staticMethods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "roundTrip", + "parameters" : [ + { + "name" : "signal", + "type" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + } + } + ] + } + ] + } + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.swift new file mode 100644 index 000000000..5e1db5c72 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.swift @@ -0,0 +1,112 @@ +extension PayloadSignal: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> PayloadSignal { + switch caseId { + case 0: + return .start(String.bridgeJSStackPop()) + case 1: + return .stop(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown PayloadSignal case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .start(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .stop(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .idle: + return Int32(2) + } + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PayloadSignalControls_roundTrip_static") +fileprivate func bjs_PayloadSignalControls_roundTrip_static_extern(_ signal: Int32) -> Int32 +#else +fileprivate func bjs_PayloadSignalControls_roundTrip_static_extern(_ signal: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_PayloadSignalControls_roundTrip_static(_ signal: Int32) -> Int32 { + return bjs_PayloadSignalControls_roundTrip_static_extern(signal) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PayloadSignalControls_send") +fileprivate func bjs_PayloadSignalControls_send_extern(_ self: Int32, _ signal: Int32) -> Void +#else +fileprivate func bjs_PayloadSignalControls_send_extern(_ self: Int32, _ signal: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_PayloadSignalControls_send(_ self: Int32, _ signal: Int32) -> Void { + return bjs_PayloadSignalControls_send_extern(self, signal) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PayloadSignalControls_current") +fileprivate func bjs_PayloadSignalControls_current_extern(_ self: Int32) -> Int32 +#else +fileprivate func bjs_PayloadSignalControls_current_extern(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_PayloadSignalControls_current(_ self: Int32) -> Int32 { + return bjs_PayloadSignalControls_current_extern(self) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PayloadSignalControls_roundTripOptional") +fileprivate func bjs_PayloadSignalControls_roundTripOptional_extern(_ self: Int32, _ signalIsSome: Int32, _ signalCaseId: Int32) -> Int32 +#else +fileprivate func bjs_PayloadSignalControls_roundTripOptional_extern(_ self: Int32, _ signalIsSome: Int32, _ signalCaseId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_PayloadSignalControls_roundTripOptional(_ self: Int32, _ signalIsSome: Int32, _ signalCaseId: Int32) -> Int32 { + return bjs_PayloadSignalControls_roundTripOptional_extern(self, signalIsSome, signalCaseId) +} + +func _$PayloadSignalControls_roundTrip(_ signal: PayloadSignal) throws(JSException) -> PayloadSignal { + let signalCaseId = signal.bridgeJSLowerParameter() + let ret = bjs_PayloadSignalControls_roundTrip_static(signalCaseId) + if let error = _swift_js_take_exception() { + throw error + } + return PayloadSignal.bridgeJSLiftReturn(ret) +} + +func _$PayloadSignalControls_send(_ self: JSObject, _ signal: PayloadSignal) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let signalCaseId = signal.bridgeJSLowerParameter() + bjs_PayloadSignalControls_send(selfValue, signalCaseId) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$PayloadSignalControls_current(_ self: JSObject) throws(JSException) -> PayloadSignal { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_PayloadSignalControls_current(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return PayloadSignal.bridgeJSLiftReturn(ret) +} + +func _$PayloadSignalControls_roundTripOptional(_ self: JSObject, _ signal: Optional) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + let (signalIsSome, signalCaseId) = signal.bridgeJSLowerParameter() + let ret = bjs_PayloadSignalControls_roundTripOptional(selfValue, signalIsSome, signalCaseId) + 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/EnumCase.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.json index ea32ad739..c4095b502 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCase.json @@ -323,5 +323,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCaseImport.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCaseImport.json new file mode 100644 index 000000000..71bf8679e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCaseImport.json @@ -0,0 +1,139 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "start" + }, + { + "associatedValues" : [ + + ], + "name" : "stop" + } + ], + "emitStyle" : "const", + "name" : "Signal", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Signal", + "tsFullPath" : "Signal" + } + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "accessLevel" : "internal", + "getters" : [ + + ], + "methods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "send", + "parameters" : [ + { + "name" : "signal", + "type" : { + "caseEnum" : { + "_0" : "Signal" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "current", + "parameters" : [ + + ], + "returnType" : { + "caseEnum" : { + "_0" : "Signal" + } + } + } + ], + "name" : "SignalControls", + "setters" : [ + + ], + "staticMethods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "roundTrip", + "parameters" : [ + { + "name" : "signal", + "type" : { + "caseEnum" : { + "_0" : "Signal" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Signal" + } + } + } + ] + } + ] + } + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCaseImport.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCaseImport.swift new file mode 100644 index 000000000..3487ad425 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumCaseImport.swift @@ -0,0 +1,97 @@ +extension Signal: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Signal { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Signal { + return Signal(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } + + @_spi(BridgeJS) @usableFromInline init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .start + case 1: + self = .stop + default: + return nil + } + } + + @_spi(BridgeJS) @usableFromInline var bridgeJSRawValue: Int32 { + switch self { + case .start: + return 0 + case .stop: + return 1 + } + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_SignalControls_roundTrip_static") +fileprivate func bjs_SignalControls_roundTrip_static_extern(_ signal: Int32) -> Int32 +#else +fileprivate func bjs_SignalControls_roundTrip_static_extern(_ signal: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_SignalControls_roundTrip_static(_ signal: Int32) -> Int32 { + return bjs_SignalControls_roundTrip_static_extern(signal) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_SignalControls_send") +fileprivate func bjs_SignalControls_send_extern(_ self: Int32, _ signal: Int32) -> Void +#else +fileprivate func bjs_SignalControls_send_extern(_ self: Int32, _ signal: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_SignalControls_send(_ self: Int32, _ signal: Int32) -> Void { + return bjs_SignalControls_send_extern(self, signal) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_SignalControls_current") +fileprivate func bjs_SignalControls_current_extern(_ self: Int32) -> Int32 +#else +fileprivate func bjs_SignalControls_current_extern(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_SignalControls_current(_ self: Int32) -> Int32 { + return bjs_SignalControls_current_extern(self) +} + +func _$SignalControls_roundTrip(_ signal: Signal) throws(JSException) -> Signal { + let signalValue = signal.bridgeJSLowerParameter() + let ret = bjs_SignalControls_roundTrip_static(signalValue) + if let error = _swift_js_take_exception() { + throw error + } + return Signal.bridgeJSLiftReturn(ret) +} + +func _$SignalControls_send(_ self: JSObject, _ signal: Signal) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let signalValue = signal.bridgeJSLowerParameter() + bjs_SignalControls_send(selfValue, signalValue) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$SignalControls_current(_ self: JSObject) throws(JSException) -> Signal { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_SignalControls_current(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Signal.bridgeJSLiftReturn(ret) +} \ 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 index 46dbe8917..103a67999 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.json @@ -639,5 +639,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 5bde4ff93..4f588f6c7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.swift @@ -117,7 +117,7 @@ public func _bjs_Services_Graph_GraphOperations_static_validate(_ graphId: Int32 _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.json index a57703b09..f9890d36b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.json @@ -639,5 +639,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 5bde4ff93..4f588f6c7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.swift @@ -117,7 +117,7 @@ public func _bjs_Services_Graph_GraphOperations_static_validate(_ graphId: Int32 _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.json index fc4a7ae52..1cf99cd39 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.json @@ -1526,6 +1526,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1550,6 +1551,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1573,5 +1575,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/FixedWidthIntegers.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/FixedWidthIntegers.json index 15a20f72e..1186ad27d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/FixedWidthIntegers.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/FixedWidthIntegers.json @@ -269,6 +269,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -298,6 +299,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -327,6 +329,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -356,6 +359,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -385,6 +389,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -414,6 +419,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -443,6 +449,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -472,6 +479,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -507,5 +515,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index f750fc6a5..83353291c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.json @@ -7,6 +7,7 @@ ], "globalGetters" : [ { + "accessLevel" : "internal", "name" : "console", "type" : { "jsObject" : { @@ -17,11 +18,13 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -57,5 +60,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 809a9ad99..5f6a08da9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.json @@ -4,6 +4,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -31,6 +32,7 @@ ], "globalGetters" : [ { + "accessLevel" : "internal", "from" : "global", "name" : "console", "type" : { @@ -42,11 +44,13 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -79,7 +83,9 @@ ] }, { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "url", @@ -97,6 +103,7 @@ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -125,5 +132,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/IdentityModeClass.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/IdentityModeClass.json index d7a9064dc..f4a4440c6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/IdentityModeClass.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/IdentityModeClass.json @@ -144,5 +144,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 3f9cb8e32..7bf447ad5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.json @@ -4,6 +4,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -41,6 +42,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -74,5 +76,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index f57e77d21..600ae8c89 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.json @@ -175,7 +175,9 @@ ], "types" : [ { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ ] @@ -198,5 +200,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index f3c3f2fc1..62f9a3b68 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportedTypeInExportedInterface.swift @@ -59,7 +59,7 @@ public func _bjs_makeFoo() -> Int32 { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.json index 1ad99f397..7cc1d81a8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.json @@ -4,6 +4,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20,6 +21,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -38,8 +40,10 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ { + "accessLevel" : "internal", "name" : "normalProperty", "type" : { "string" : { @@ -48,6 +52,7 @@ } }, { + "accessLevel" : "internal", "jsName" : "property-with-dashes", "name" : "property_with_dashes", "type" : { @@ -57,6 +62,7 @@ } }, { + "accessLevel" : "internal", "jsName" : "123invalidStart", "name" : "_123invalidStart", "type" : { @@ -66,6 +72,7 @@ } }, { + "accessLevel" : "internal", "jsName" : "property with spaces", "name" : "property_with_spaces", "type" : { @@ -75,6 +82,7 @@ } }, { + "accessLevel" : "internal", "jsName" : "@specialChar", "name" : "_specialChar", "type" : { @@ -84,6 +92,7 @@ } }, { + "accessLevel" : "internal", "name" : "constructor", "type" : { "string" : { @@ -92,6 +101,7 @@ } }, { + "accessLevel" : "internal", "name" : "for", "type" : { "string" : { @@ -100,6 +110,7 @@ } }, { + "accessLevel" : "internal", "name" : "Any", "type" : { "string" : { @@ -110,6 +121,7 @@ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -126,6 +138,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -145,6 +158,7 @@ "name" : "WeirdNaming", "setters" : [ { + "accessLevel" : "internal", "functionName" : "normalProperty_set", "name" : "normalProperty", "type" : { @@ -154,6 +168,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "property_with_dashes_set", "jsName" : "property-with-dashes", "name" : "property_with_dashes", @@ -164,6 +179,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "_123invalidStart_set", "jsName" : "123invalidStart", "name" : "_123invalidStart", @@ -174,6 +190,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "property_with_spaces_set", "jsName" : "property with spaces", "name" : "property_with_spaces", @@ -184,6 +201,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "_specialChar_set", "jsName" : "@specialChar", "name" : "_specialChar", @@ -194,6 +212,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "constructor_set", "name" : "constructor", "type" : { @@ -203,6 +222,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "for_set", "name" : "for", "type" : { @@ -212,6 +232,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "any_set", "jsName" : "Any", "name" : "any", @@ -227,7 +248,9 @@ ] }, { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ ] @@ -238,6 +261,7 @@ "jsName" : "$Weird", "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -267,5 +291,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index ef8eba9ba..2455e5e6d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.json @@ -4,6 +4,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -22,7 +23,9 @@ ], "types" : [ { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "name", @@ -36,6 +39,7 @@ }, "getters" : [ { + "accessLevel" : "internal", "name" : "name", "type" : { "string" : { @@ -44,6 +48,7 @@ } }, { + "accessLevel" : "internal", "name" : "age", "type" : { "double" : { @@ -54,6 +59,7 @@ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -70,6 +76,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -96,6 +103,7 @@ "name" : "Greeter", "setters" : [ { + "accessLevel" : "internal", "functionName" : "name_set", "name" : "name", "type" : { @@ -110,11 +118,13 @@ ] }, { + "accessLevel" : "internal", "getters" : [ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -146,6 +156,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -181,5 +192,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 18f7cfaac..363e8d875 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClassStaticFunctions.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClassStaticFunctions.json @@ -7,11 +7,13 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -34,6 +36,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -57,6 +60,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -73,6 +77,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -89,6 +94,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -108,7 +114,9 @@ ] }, { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "value", @@ -132,6 +140,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -160,5 +169,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSTypedArrayTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSTypedArrayTypes.json new file mode 100644 index 000000000..a7b9c8623 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSTypedArrayTypes.json @@ -0,0 +1,123 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_processBytes", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processBytes", + "parameters" : [ + { + "label" : "_", + "name" : "data", + "type" : { + "jsObject" : { + "_0" : "JSUint8Array" + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "JSUint8Array" + } + } + }, + { + "abiName" : "bjs_processFloats", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processFloats", + "parameters" : [ + { + "label" : "_", + "name" : "data", + "type" : { + "jsObject" : { + "_0" : "JSFloat32Array" + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "JSFloat32Array" + } + } + }, + { + "abiName" : "bjs_processGenericDoubles", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processGenericDoubles", + "parameters" : [ + { + "label" : "_", + "name" : "data", + "type" : { + "jsObject" : { + "_0" : "JSFloat64Array" + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "JSFloat64Array" + } + } + }, + { + "abiName" : "bjs_processGenericInts", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processGenericInts", + "parameters" : [ + { + "label" : "_", + "name" : "data", + "type" : { + "jsObject" : { + "_0" : "JSInt32Array" + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "JSInt32Array" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSTypedArrayTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSTypedArrayTypes.swift new file mode 100644 index 000000000..4777af058 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSTypedArrayTypes.swift @@ -0,0 +1,43 @@ +@_expose(wasm, "bjs_processBytes") +@_cdecl("bjs_processBytes") +public func _bjs_processBytes(_ data: Int32) -> Int32 { + #if arch(wasm32) + let ret = processBytes(_: JSUint8Array.bridgeJSLiftParameter(data)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processFloats") +@_cdecl("bjs_processFloats") +public func _bjs_processFloats(_ data: Int32) -> Int32 { + #if arch(wasm32) + let ret = processFloats(_: JSFloat32Array.bridgeJSLiftParameter(data)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processGenericDoubles") +@_cdecl("bjs_processGenericDoubles") +public func _bjs_processGenericDoubles(_ data: Int32) -> Int32 { + #if arch(wasm32) + let ret = processGenericDoubles(_: JSFloat64Array.bridgeJSLiftParameter(data)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_processGenericInts") +@_cdecl("bjs_processGenericInts") +public func _bjs_processGenericInts(_ data: Int32) -> Int32 { + #if arch(wasm32) + let ret = processGenericInts(_: JSInt32Array.bridgeJSLiftParameter(data)) + 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/JSValue.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.json index fb8601ae7..f0cd29565 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.json @@ -321,6 +321,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -344,6 +345,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -381,5 +383,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index f140fd007..0d30063ee 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedGlobal.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedGlobal.json @@ -75,5 +75,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 9e9dc445e..e6bcf2e5c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedPrivate.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/MixedPrivate.json @@ -75,5 +75,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 080f9f959..4b6b720f1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json @@ -289,5 +289,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index d471eeaca..3c07b7dcf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json @@ -289,5 +289,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/NestedType.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/NestedType.json new file mode 100644 index 000000000..f924b3eba --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/NestedType.json @@ -0,0 +1,156 @@ +{ + "exported" : { + "classes" : [ + { + "methods" : [ + { + "abiName" : "bjs_User_getName", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getName", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "User", + "properties" : [ + + ], + "swiftCallName" : "User" + }, + { + "methods" : [ + { + "abiName" : "bjs_Player_getTag", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTag", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Player", + "properties" : [ + + ], + "swiftCallName" : "Player" + } + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "Stats", + "namespace" : [ + "User" + ], + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "health", + "namespace" : [ + "User" + ], + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "score", + "namespace" : [ + "User" + ], + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "User.Stats" + }, + { + "methods" : [ + + ], + "name" : "Stats", + "namespace" : [ + "Player" + ], + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "level", + "namespace" : [ + "Player" + ], + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "rating", + "namespace" : [ + "Player" + ], + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "Player.Stats" + } + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/NestedType.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/NestedType.swift new file mode 100644 index 000000000..ed1a080e9 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/NestedType.swift @@ -0,0 +1,179 @@ +extension User.Stats: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> User.Stats { + let score = Double.bridgeJSStackPop() + let health = Int.bridgeJSStackPop() + return User.Stats(health: health, score: score) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.health.bridgeJSStackPush() + self.score.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_User_Stats(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_User_Stats())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_User_Stats") +fileprivate func _bjs_struct_lower_User_Stats_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_User_Stats_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_User_Stats(_ objectId: Int32) -> Void { + return _bjs_struct_lower_User_Stats_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_User_Stats") +fileprivate func _bjs_struct_lift_User_Stats_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_User_Stats_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_User_Stats() -> Int32 { + return _bjs_struct_lift_User_Stats_extern() +} + +extension Player.Stats: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Player.Stats { + let rating = String.bridgeJSStackPop() + let level = Int.bridgeJSStackPop() + return Player.Stats(level: level, rating: rating) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.level.bridgeJSStackPush() + self.rating.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_Player_Stats(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Player_Stats())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Player_Stats") +fileprivate func _bjs_struct_lower_Player_Stats_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_Player_Stats_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_Player_Stats(_ objectId: Int32) -> Void { + return _bjs_struct_lower_Player_Stats_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Player_Stats") +fileprivate func _bjs_struct_lift_Player_Stats_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_Player_Stats_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_Player_Stats() -> Int32 { + return _bjs_struct_lift_Player_Stats_extern() +} + +@_expose(wasm, "bjs_User_getName") +@_cdecl("bjs_User_getName") +public func _bjs_User_getName(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = User.bridgeJSLiftParameter(_self).getName() + 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, _BridgedSwiftProtocolExportable { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_User_wrap(Unmanaged.passRetained(self).toOpaque())))) + } + consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { + _bjs_User_wrap(Unmanaged.passRetained(self).toOpaque()) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_User_wrap") +fileprivate func _bjs_User_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_User_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_User_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_User_wrap_extern(pointer) +} + +@_expose(wasm, "bjs_Player_getTag") +@_cdecl("bjs_Player_getTag") +public func _bjs_Player_getTag(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Player.bridgeJSLiftParameter(_self).getTag() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Player_deinit") +@_cdecl("bjs_Player_deinit") +public func _bjs_Player_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Player: ConvertibleToJSValue, _BridgedSwiftHeapObject, _BridgedSwiftProtocolExportable { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Player_wrap(Unmanaged.passRetained(self).toOpaque())))) + } + consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { + _bjs_Player_wrap(Unmanaged.passRetained(self).toOpaque()) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Player_wrap") +fileprivate func _bjs_Player_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Player_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_Player_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_Player_wrap_extern(pointer) +} \ 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 index 3e6d6c60c..e9d78cbbc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.json @@ -239,6 +239,76 @@ } } }, + { + "abiName" : "bjs_roundTripExportedOptionalJSObject", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripExportedOptionalJSObject", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_roundTripExportedOptionalJSClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripExportedOptionalJSClass", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "WithOptionalJSClass" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "WithOptionalJSClass" + } + }, + "_1" : "null" + } + } + }, { "abiName" : "bjs_roundTripString", "effects" : { @@ -1008,7 +1078,9 @@ ], "types" : [ { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "valueOrNull", @@ -1040,6 +1112,7 @@ }, "getters" : [ { + "accessLevel" : "internal", "name" : "stringOrNull", "type" : { "nullable" : { @@ -1053,6 +1126,7 @@ } }, { + "accessLevel" : "internal", "name" : "stringOrUndefined", "type" : { "nullable" : { @@ -1066,6 +1140,7 @@ } }, { + "accessLevel" : "internal", "name" : "doubleOrNull", "type" : { "nullable" : { @@ -1079,6 +1154,7 @@ } }, { + "accessLevel" : "internal", "name" : "doubleOrUndefined", "type" : { "nullable" : { @@ -1092,6 +1168,7 @@ } }, { + "accessLevel" : "internal", "name" : "boolOrNull", "type" : { "nullable" : { @@ -1105,6 +1182,7 @@ } }, { + "accessLevel" : "internal", "name" : "boolOrUndefined", "type" : { "nullable" : { @@ -1118,6 +1196,7 @@ } }, { + "accessLevel" : "internal", "name" : "intOrNull", "type" : { "nullable" : { @@ -1134,6 +1213,7 @@ } }, { + "accessLevel" : "internal", "name" : "intOrUndefined", "type" : { "nullable" : { @@ -1148,10 +1228,25 @@ "_1" : "undefined" } } + }, + { + "accessLevel" : "internal", + "name" : "childOrNull", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "WithOptionalJSClass" + } + }, + "_1" : "null" + } + } } ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1185,6 +1280,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1218,6 +1314,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1251,6 +1348,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1284,6 +1382,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1317,6 +1416,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1350,6 +1450,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1389,6 +1490,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -1426,11 +1528,46 @@ "_1" : "undefined" } } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "roundTripChildOrNull", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "WithOptionalJSClass" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "WithOptionalJSClass" + } + }, + "_1" : "null" + } + } } ], "name" : "WithOptionalJSClass", "setters" : [ { + "accessLevel" : "internal", "functionName" : "stringOrNull_set", "name" : "stringOrNull", "type" : { @@ -1445,6 +1582,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "stringOrUndefined_set", "name" : "stringOrUndefined", "type" : { @@ -1459,6 +1597,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "doubleOrNull_set", "name" : "doubleOrNull", "type" : { @@ -1473,6 +1612,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "doubleOrUndefined_set", "name" : "doubleOrUndefined", "type" : { @@ -1487,6 +1627,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "boolOrNull_set", "name" : "boolOrNull", "type" : { @@ -1501,6 +1642,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "boolOrUndefined_set", "name" : "boolOrUndefined", "type" : { @@ -1515,6 +1657,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "intOrNull_set", "name" : "intOrNull", "type" : { @@ -1532,6 +1675,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "intOrUndefined_set", "name" : "intOrUndefined", "type" : { @@ -1547,6 +1691,21 @@ "_1" : "undefined" } } + }, + { + "accessLevel" : "internal", + "functionName" : "childOrNull_set", + "name" : "childOrNull", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "WithOptionalJSClass" + } + }, + "_1" : "null" + } + } } ], "staticMethods" : [ @@ -1557,5 +1716,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 0c6a79bf5..65380d1e3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift @@ -20,6 +20,28 @@ public func _bjs_testOptionalPropertyRoundtrip(_ holderIsSome: Int32, _ holderVa #endif } +@_expose(wasm, "bjs_roundTripExportedOptionalJSObject") +@_cdecl("bjs_roundTripExportedOptionalJSObject") +public func _bjs_roundTripExportedOptionalJSObject(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripExportedOptionalJSObject(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripExportedOptionalJSClass") +@_cdecl("bjs_roundTripExportedOptionalJSClass") +public func _bjs_roundTripExportedOptionalJSClass(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripExportedOptionalJSClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + 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 { @@ -526,6 +548,18 @@ fileprivate func bjs_WithOptionalJSClass_intOrUndefined_get_extern(_ self: Int32 return bjs_WithOptionalJSClass_intOrUndefined_get_extern(self) } +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_childOrNull_get") +fileprivate func bjs_WithOptionalJSClass_childOrNull_get_extern(_ self: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_childOrNull_get_extern(_ self: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_WithOptionalJSClass_childOrNull_get(_ self: Int32) -> Void { + return bjs_WithOptionalJSClass_childOrNull_get_extern(self) +} + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_stringOrNull_set") fileprivate func bjs_WithOptionalJSClass_stringOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void @@ -622,6 +656,18 @@ fileprivate func bjs_WithOptionalJSClass_intOrUndefined_set_extern(_ self: Int32 return bjs_WithOptionalJSClass_intOrUndefined_set_extern(self, newValueIsSome, newValueValue) } +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_childOrNull_set") +fileprivate func bjs_WithOptionalJSClass_childOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_childOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_WithOptionalJSClass_childOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void { + return bjs_WithOptionalJSClass_childOrNull_set_extern(self, newValueIsSome, newValueValue) +} + #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripStringOrNull") fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void @@ -718,6 +764,18 @@ fileprivate func bjs_WithOptionalJSClass_roundTripIntOrUndefined_extern(_ self: return bjs_WithOptionalJSClass_roundTripIntOrUndefined_extern(self, valueIsSome, valueValue) } +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripChildOrNull") +fileprivate func bjs_WithOptionalJSClass_roundTripChildOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func bjs_WithOptionalJSClass_roundTripChildOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripChildOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + return bjs_WithOptionalJSClass_roundTripChildOrNull_extern(self, valueIsSome, valueValue) +} + func _$WithOptionalJSClass_init(_ valueOrNull: Optional, _ valueOrUndefined: JSUndefinedOr) throws(JSException) -> JSObject { let ret0 = valueOrNull.bridgeJSWithLoweredParameter { (valueOrNullIsSome, valueOrNullBytes, valueOrNullLength) in let ret1 = valueOrUndefined.bridgeJSWithLoweredParameter { (valueOrUndefinedIsSome, valueOrUndefinedBytes, valueOrUndefinedLength) in @@ -805,6 +863,15 @@ func _$WithOptionalJSClass_intOrUndefined_get(_ self: JSObject) throws(JSExcepti return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() } +func _$WithOptionalJSClass_childOrNull_get(_ self: JSObject) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_childOrNull_get(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn() +} + func _$WithOptionalJSClass_stringOrNull_set(_ self: JSObject, _ newValue: Optional) throws(JSException) -> Void { let selfValue = self.bridgeJSLowerParameter() newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueBytes, newValueLength) in @@ -879,6 +946,15 @@ func _$WithOptionalJSClass_intOrUndefined_set(_ self: JSObject, _ newValue: JSUn } } +func _$WithOptionalJSClass_childOrNull_set(_ self: JSObject, _ newValue: Optional) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_childOrNull_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() value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in @@ -959,4 +1035,14 @@ func _$WithOptionalJSClass_roundTripIntOrUndefined(_ self: JSObject, _ value: JS throw error } return JSUndefinedOr.bridgeJSLiftReturnFromSideChannel() +} + +func _$WithOptionalJSClass_roundTripChildOrNull(_ self: JSObject, _ value: Optional) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_WithOptionalJSClass_roundTripChildOrNull(selfValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn() } \ 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 index cf76f3878..320499ff3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveParameters.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveParameters.json @@ -88,6 +88,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -125,5 +126,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index b0398c161..414fedbbd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveReturn.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PrimitiveReturn.json @@ -112,6 +112,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -128,6 +129,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -150,5 +152,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 24e3f44cd..281538dd6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PropertyTypes.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/PropertyTypes.json @@ -377,5 +377,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index b46d1125e..feca4615b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.json @@ -970,5 +970,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ProtocolInClosure.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ProtocolInClosure.json index 36d6941d3..70273f8b3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ProtocolInClosure.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ProtocolInClosure.json @@ -282,5 +282,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index e20af8a3b..800018440 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.Global.json @@ -483,5 +483,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index ded6f7602..36110488c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticFunctions.json @@ -483,5 +483,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index d14f9b0a3..1cbe44619 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.Global.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.Global.json @@ -351,5 +351,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 35d740dff..8fc0667b0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StaticProperties.json @@ -351,5 +351,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 75462af81..d9dc0ec43 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.json @@ -71,6 +71,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -94,6 +95,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -131,5 +133,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 1088a5cab..e2cf9ffac 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringReturn.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringReturn.json @@ -38,6 +38,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -60,5 +61,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json index ceda64904..a3ddab63e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClass.json @@ -213,6 +213,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -236,6 +237,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -275,5 +277,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 41662e48b..ac18f6dc2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.json @@ -284,6 +284,152 @@ ], "exposeToGlobal" : false, "functions" : [ + { + "abiName" : "bjs_roundtripAnimal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAnimal", + "parameters" : [ + { + "label" : "_", + "name" : "animalClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule6AnimalV_6AnimalV", + "moduleName" : "TestModule", + "parameters" : [ + { + "swiftStruct" : { + "_0" : "Animal" + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Animal" + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule6AnimalV_6AnimalV", + "moduleName" : "TestModule", + "parameters" : [ + { + "swiftStruct" : { + "_0" : "Animal" + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Animal" + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_roundtripOptionalAnimal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripOptionalAnimal", + "parameters" : [ + { + "label" : "_", + "name" : "animalClosure", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq6AnimalV_Sq6AnimalV", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Animal" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Animal" + } + }, + "_1" : "null" + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModuleSq6AnimalV_Sq6AnimalV", + "moduleName" : "TestModule", + "parameters" : [ + { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Animal" + } + }, + "_1" : "null" + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Animal" + } + }, + "_1" : "null" + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false + } + } + }, { "abiName" : "bjs_roundtripString", "effects" : { @@ -1872,8 +2018,49 @@ ], "structs" : [ + { + "constructor" : { + "abiName" : "bjs_Animal_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "type", + "name" : "type", + "type" : { + "string" : { + } + } + } + ] + }, + "explicitAccessControl" : "public", + "methods" : [ + + ], + "name" : "Animal", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "type", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "Animal" + } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 348f9a788..4eb7c8da4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift @@ -127,6 +127,69 @@ public func _invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(_ boxPt #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule6AnimalV_6AnimalV") +fileprivate func invoke_js_callback_TestModule_10TestModule6AnimalV_6AnimalV_extern(_ callback: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModule6AnimalV_6AnimalV_extern(_ callback: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModule6AnimalV_6AnimalV(_ callback: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModule6AnimalV_6AnimalV_extern(callback) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV") +fileprivate func make_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_10TestModule6AnimalV_6AnimalV { + static func bridgeJSLift(_ callbackId: Int32) -> (Animal) -> Animal { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let _ = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModule6AnimalV_6AnimalV(callbackValue) + return Animal.bridgeJSLiftReturn() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Animal) -> Animal { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Animal) -> Animal) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV") +@_cdecl("invoke_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV") +public func _invoke_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV(_ boxPtr: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Animal) -> Animal>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Animal.bridgeJSLiftParameter()) + 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_extern(_ callback: Int32, _ param0: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer @@ -761,6 +824,69 @@ public func _invoke_swift_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ b #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV") +fileprivate func invoke_js_callback_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV_extern(_ callback: Int32, _ param0: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV_extern(_ callback: Int32, _ param0: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV(_ callback: Int32, _ param0: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV_extern(callback, param0) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV") +fileprivate func make_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_10TestModuleSq6AnimalV_Sq6AnimalV { + 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 = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV(callbackValue, param0IsSome) + return Optional.bridgeJSLiftReturn() + #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_10TestModuleSq6AnimalV_Sq6AnimalV, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV") +@_cdecl("invoke_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV") +public func _invoke_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV(_ boxPtr: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Optional) -> Optional>>.fromOpaque(boxPtr).takeUnretainedValue().closure + let result = closure(Optional.bridgeJSLiftParameter()) + 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_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer @@ -1358,6 +1484,85 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum { } } +extension Animal: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Animal { + let type = String.bridgeJSStackPop() + return Animal(type: type) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.type.bridgeJSStackPush() + } + + public init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_Animal(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + public func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Animal())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Animal") +fileprivate func _bjs_struct_lower_Animal_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_Animal_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_Animal(_ objectId: Int32) -> Void { + return _bjs_struct_lower_Animal_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Animal") +fileprivate func _bjs_struct_lift_Animal_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_Animal_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_Animal() -> Int32 { + return _bjs_struct_lift_Animal_extern() +} + +@_expose(wasm, "bjs_Animal_init") +@_cdecl("bjs_Animal_init") +public func _bjs_Animal_init(_ typeBytes: Int32, _ typeLength: Int32) -> Void { + #if arch(wasm32) + let ret = Animal(type: String.bridgeJSLiftParameter(typeBytes, typeLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripAnimal") +@_cdecl("bjs_roundtripAnimal") +public func _bjs_roundtripAnimal(_ animalClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripAnimal(_: _BJS_Closure_10TestModule6AnimalV_6AnimalV.bridgeJSLift(animalClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalAnimal") +@_cdecl("bjs_roundtripOptionalAnimal") +public func _bjs_roundtripOptionalAnimal(_ animalClosure: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripOptionalAnimal(_: _BJS_Closure_10TestModuleSq6AnimalV_Sq6AnimalV.bridgeJSLift(animalClosure)) + return JSTypedClosure(ret).bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_roundtripString") @_cdecl("bjs_roundtripString") public func _bjs_roundtripString(_ stringClosure: Int32) -> Int32 { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json index a78b1bf5d..a84441bb4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.json @@ -4,6 +4,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -66,6 +67,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -123,5 +125,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 4c1ef582b..bfde01318 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStruct.json @@ -712,5 +712,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index ccd3043ac..a9b0d22bf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.json @@ -56,6 +56,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -99,6 +100,40 @@ "_0" : "Point" } } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "roundTripOptional", + "parameters" : [ + { + "name" : "point", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } } ], "types" : [ @@ -107,5 +142,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index fe79f786c..cec50ffca 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftStructImports.swift @@ -67,4 +67,25 @@ func _$translate(_ point: Point, _ dx: Int, _ dy: Int) throws(JSException) -> Po throw error } return Point.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_roundTripOptional") +fileprivate func bjs_roundTripOptional_extern(_ point: Int32) -> Void +#else +fileprivate func bjs_roundTripOptional_extern(_ point: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_roundTripOptional(_ point: Int32) -> Void { + return bjs_roundTripOptional_extern(point) +} + +func _$roundTripOptional(_ point: Optional) throws(JSException) -> Optional { + let pointIsSome = point.bridgeJSLowerParameter() + bjs_roundTripOptional(pointIsSome) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn() } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftTypedClosureAccess.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftTypedClosureAccess.json new file mode 100644 index 000000000..f6c0c6fe1 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftTypedClosureAccess.json @@ -0,0 +1,288 @@ +{ + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "accessLevel" : "public", + "getters" : [ + + ], + "jsName" : "PublicEvent", + "methods" : [ + + ], + "name" : "JSPublicEvent", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "accessLevel" : "package", + "getters" : [ + + ], + "jsName" : "PackageEvent", + "methods" : [ + + ], + "name" : "JSPackageEvent", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "accessLevel" : "internal", + "getters" : [ + + ], + "jsName" : "InternalEvent", + "methods" : [ + + ], + "name" : "JSInternalEvent", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "accessLevel" : "public", + "getters" : [ + + ], + "jsName" : "PublicTarget", + "methods" : [ + { + "accessLevel" : "public", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "addPublicListener", + "parameters" : [ + { + "name" : "handler", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule13JSPublicEventC_y", + "moduleName" : "TestModule", + "parameters" : [ + { + "jsObject" : { + "_0" : "JSPublicEvent" + } + } + ], + "returnType" : { + "void" : { + + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "addInternalListener", + "parameters" : [ + { + "name" : "handler", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule13JSPublicEventC_y", + "moduleName" : "TestModule", + "parameters" : [ + { + "jsObject" : { + "_0" : "JSPublicEvent" + } + } + ], + "returnType" : { + "void" : { + + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "JSPublicTarget", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "accessLevel" : "package", + "getters" : [ + + ], + "jsName" : "PackageTarget", + "methods" : [ + { + "accessLevel" : "package", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "addPackageListener", + "parameters" : [ + { + "name" : "handler", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule14JSPackageEventC_y", + "moduleName" : "TestModule", + "parameters" : [ + { + "jsObject" : { + "_0" : "JSPackageEvent" + } + } + ], + "returnType" : { + "void" : { + + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "JSPackageTarget", + "setters" : [ + + ], + "staticMethods" : [ + + ] + }, + { + "accessLevel" : "internal", + "getters" : [ + + ], + "jsName" : "InternalTarget", + "methods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "addInternalListener", + "parameters" : [ + { + "name" : "handler", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "10TestModule15JSInternalEventC_y", + "moduleName" : "TestModule", + "parameters" : [ + { + "jsObject" : { + "_0" : "JSInternalEvent" + } + } + ], + "returnType" : { + "void" : { + + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : true + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "JSInternalTarget", + "setters" : [ + + ], + "staticMethods" : [ + + ] + } + ] + } + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftTypedClosureAccess.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftTypedClosureAccess.swift new file mode 100644 index 000000000..fbd181fcc --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftTypedClosureAccess.swift @@ -0,0 +1,266 @@ +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule13JSPublicEventC_y") +fileprivate func invoke_js_callback_TestModule_10TestModule13JSPublicEventC_y_extern(_ callback: Int32, _ param0: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModule13JSPublicEventC_y_extern(_ callback: Int32, _ param0: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModule13JSPublicEventC_y(_ callback: Int32, _ param0: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModule13JSPublicEventC_y_extern(callback, param0) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule13JSPublicEventC_y") +fileprivate func make_swift_closure_TestModule_10TestModule13JSPublicEventC_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule13JSPublicEventC_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_TestModule_10TestModule13JSPublicEventC_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_TestModule_10TestModule13JSPublicEventC_y_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_10TestModule13JSPublicEventC_y { + static func bridgeJSLift(_ callbackId: Int32) -> (JSPublicEvent) -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModule13JSPublicEventC_y(callbackValue, param0Value) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (JSPublicEvent) -> Void { + public init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (JSPublicEvent) -> Void) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule13JSPublicEventC_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule13JSPublicEventC_y") +@_cdecl("invoke_swift_closure_TestModule_10TestModule13JSPublicEventC_y") +public func _invoke_swift_closure_TestModule_10TestModule13JSPublicEventC_y(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(JSPublicEvent) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(JSPublicEvent.bridgeJSLiftParameter(param0)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule14JSPackageEventC_y") +fileprivate func invoke_js_callback_TestModule_10TestModule14JSPackageEventC_y_extern(_ callback: Int32, _ param0: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModule14JSPackageEventC_y_extern(_ callback: Int32, _ param0: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModule14JSPackageEventC_y(_ callback: Int32, _ param0: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModule14JSPackageEventC_y_extern(callback, param0) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule14JSPackageEventC_y") +fileprivate func make_swift_closure_TestModule_10TestModule14JSPackageEventC_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule14JSPackageEventC_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_TestModule_10TestModule14JSPackageEventC_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_TestModule_10TestModule14JSPackageEventC_y_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_10TestModule14JSPackageEventC_y { + static func bridgeJSLift(_ callbackId: Int32) -> (JSPackageEvent) -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModule14JSPackageEventC_y(callbackValue, param0Value) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (JSPackageEvent) -> Void { + package init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (JSPackageEvent) -> Void) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule14JSPackageEventC_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule14JSPackageEventC_y") +@_cdecl("invoke_swift_closure_TestModule_10TestModule14JSPackageEventC_y") +public func _invoke_swift_closure_TestModule_10TestModule14JSPackageEventC_y(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(JSPackageEvent) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(JSPackageEvent.bridgeJSLiftParameter(param0)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule15JSInternalEventC_y") +fileprivate func invoke_js_callback_TestModule_10TestModule15JSInternalEventC_y_extern(_ callback: Int32, _ param0: Int32) -> Void +#else +fileprivate func invoke_js_callback_TestModule_10TestModule15JSInternalEventC_y_extern(_ callback: Int32, _ param0: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModule15JSInternalEventC_y(_ callback: Int32, _ param0: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModule15JSInternalEventC_y_extern(callback, param0) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_TestModule_10TestModule15JSInternalEventC_y") +fileprivate func make_swift_closure_TestModule_10TestModule15JSInternalEventC_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_TestModule_10TestModule15JSInternalEventC_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_TestModule_10TestModule15JSInternalEventC_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_TestModule_10TestModule15JSInternalEventC_y_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_10TestModule15JSInternalEventC_y { + static func bridgeJSLift(_ callbackId: Int32) -> (JSInternalEvent) -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + invoke_js_callback_TestModule_10TestModule15JSInternalEventC_y(callbackValue, param0Value) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (JSInternalEvent) -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (JSInternalEvent) -> Void) { + self.init( + makeClosure: make_swift_closure_TestModule_10TestModule15JSInternalEventC_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_TestModule_10TestModule15JSInternalEventC_y") +@_cdecl("invoke_swift_closure_TestModule_10TestModule15JSInternalEventC_y") +public func _invoke_swift_closure_TestModule_10TestModule15JSInternalEventC_y(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(JSInternalEvent) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(JSInternalEvent.bridgeJSLiftParameter(param0)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_JSPublicTarget_addPublicListener") +fileprivate func bjs_JSPublicTarget_addPublicListener_extern(_ self: Int32, _ handler: Int32) -> Void +#else +fileprivate func bjs_JSPublicTarget_addPublicListener_extern(_ self: Int32, _ handler: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSPublicTarget_addPublicListener(_ self: Int32, _ handler: Int32) -> Void { + return bjs_JSPublicTarget_addPublicListener_extern(self, handler) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_JSPublicTarget_addInternalListener") +fileprivate func bjs_JSPublicTarget_addInternalListener_extern(_ self: Int32, _ handler: Int32) -> Void +#else +fileprivate func bjs_JSPublicTarget_addInternalListener_extern(_ self: Int32, _ handler: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSPublicTarget_addInternalListener(_ self: Int32, _ handler: Int32) -> Void { + return bjs_JSPublicTarget_addInternalListener_extern(self, handler) +} + +func _$JSPublicTarget_addPublicListener(_ self: JSObject, _ handler: JSTypedClosure<(JSPublicEvent) -> Void>) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let handlerFuncRef = handler.bridgeJSLowerParameter() + bjs_JSPublicTarget_addPublicListener(selfValue, handlerFuncRef) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$JSPublicTarget_addInternalListener(_ self: JSObject, _ handler: JSTypedClosure<(JSPublicEvent) -> Void>) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let handlerFuncRef = handler.bridgeJSLowerParameter() + bjs_JSPublicTarget_addInternalListener(selfValue, handlerFuncRef) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_JSPackageTarget_addPackageListener") +fileprivate func bjs_JSPackageTarget_addPackageListener_extern(_ self: Int32, _ handler: Int32) -> Void +#else +fileprivate func bjs_JSPackageTarget_addPackageListener_extern(_ self: Int32, _ handler: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSPackageTarget_addPackageListener(_ self: Int32, _ handler: Int32) -> Void { + return bjs_JSPackageTarget_addPackageListener_extern(self, handler) +} + +func _$JSPackageTarget_addPackageListener(_ self: JSObject, _ handler: JSTypedClosure<(JSPackageEvent) -> Void>) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let handlerFuncRef = handler.bridgeJSLowerParameter() + bjs_JSPackageTarget_addPackageListener(selfValue, handlerFuncRef) + if let error = _swift_js_take_exception() { + throw error + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_JSInternalTarget_addInternalListener") +fileprivate func bjs_JSInternalTarget_addInternalListener_extern(_ self: Int32, _ handler: Int32) -> Void +#else +fileprivate func bjs_JSInternalTarget_addInternalListener_extern(_ self: Int32, _ handler: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSInternalTarget_addInternalListener(_ self: Int32, _ handler: Int32) -> Void { + return bjs_JSInternalTarget_addInternalListener_extern(self, handler) +} + +func _$JSInternalTarget_addInternalListener(_ self: JSObject, _ handler: JSTypedClosure<(JSInternalEvent) -> Void>) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let handlerFuncRef = handler.bridgeJSLowerParameter() + bjs_JSInternalTarget_addInternalListener(selfValue, handlerFuncRef) + if let error = _swift_js_take_exception() { + throw error + } +} \ 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 index 02796479f..942e5fb45 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.json @@ -33,5 +33,8 @@ ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.swift index 37f6d9c96..91787a642 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Throws.swift @@ -10,7 +10,7 @@ public func _bjs_throwsSomething() -> Void { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.json index 1eb9e47ec..a382778e9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/UnsafePointer.json @@ -412,5 +412,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 7f19c18bf..d31f775fb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/VoidParameterVoidReturn.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/VoidParameterVoidReturn.json @@ -38,6 +38,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -60,5 +61,8 @@ } ] }, - "moduleName" : "TestModule" + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] } \ 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 index 8359220c9..75d961e98 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -38,6 +38,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -123,6 +124,13 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } bjs["swift_js_struct_lower_Point"] = function(objectId) { structHelpers.Point.lower(swift.memory.getObject(objectId)); } @@ -130,6 +138,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.Point.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -250,12 +265,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = f64Stack.pop(); + arrayResult.push(f64); + } + arrayResult.reverse(); } - arrayResult.reverse(); imports.importProcessNumbers(arrayResult); } catch (error) { setException(error); @@ -275,12 +295,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = f64Stack.pop(); + arrayResult.push(f64); + } + arrayResult.reverse(); } - arrayResult.reverse(); let ret = imports.importTransformNumbers(arrayResult); for (const elem of ret) { f64Stack.push(elem); @@ -293,12 +318,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); } - arrayResult.reverse(); let ret = imports.importProcessStrings(arrayResult); for (const elem of ret) { const bytes = textEncoder.encode(elem); @@ -314,12 +344,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const bool = i32Stack.pop() !== 0; + arrayResult.push(bool); + } + arrayResult.reverse(); } - arrayResult.reverse(); let ret = imports.importProcessBooleans(arrayResult); for (const elem of ret) { i32Stack.push(elem ? 1 : 0); @@ -423,23 +458,33 @@ export async function createInstantiator(options, swift) { get numbers() { instance.exports.bjs_MultiArrayContainer_numbers_get(this.pointer); const arrayLen = i32Stack.pop(); - const arrayResult = []; - for (let i = 0; i < arrayLen; i++) { - const int = i32Stack.pop(); - arrayResult.push(int); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; } get strings() { instance.exports.bjs_MultiArrayContainer_strings_get(this.pointer); const arrayLen = i32Stack.pop(); - const arrayResult = []; - for (let i = 0; i < arrayLen; i++) { - const string = strStack.pop(); - arrayResult.push(string); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; } } @@ -456,12 +501,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processStringArray: function bjs_processStringArray(values) { @@ -474,12 +524,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processDoubleArray: function bjs_processDoubleArray(values) { @@ -489,12 +544,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = f64Stack.pop(); + arrayResult.push(f64); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processBoolArray: function bjs_processBoolArray(values) { @@ -504,12 +564,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const bool = i32Stack.pop() !== 0; + arrayResult.push(bool); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processPointArray: function bjs_processPointArray(points) { @@ -519,12 +584,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const struct = structHelpers.Point.lift(); + arrayResult.push(struct); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processDirectionArray: function bjs_processDirectionArray(directions) { @@ -534,12 +604,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const caseId = i32Stack.pop(); + arrayResult.push(caseId); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processStatusArray: function bjs_processStatusArray(statuses) { @@ -549,12 +624,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const rawValue = i32Stack.pop(); + arrayResult.push(rawValue); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, sumIntArray: function bjs_sumIntArray(values) { @@ -583,12 +663,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = ptrStack.pop(); + arrayResult.push(pointer); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processUnsafeMutableRawPointerArray: function bjs_processUnsafeMutableRawPointerArray(values) { @@ -598,12 +683,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = ptrStack.pop(); + arrayResult.push(pointer); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processOpaquePointerArray: function bjs_processOpaquePointerArray(values) { @@ -613,12 +703,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const pointer = ptrStack.pop(); + arrayResult.push(pointer); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processOptionalIntArray: function bjs_processOptionalIntArray(values) { @@ -632,19 +727,24 @@ export async function createInstantiator(options, swift) { 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; + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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.push(optValue); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processOptionalStringArray: function bjs_processOptionalStringArray(values) { @@ -661,19 +761,24 @@ export async function createInstantiator(options, swift) { 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; + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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.push(optValue); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processOptionalArray: function bjs_processOptionalArray(values) { @@ -690,12 +795,17 @@ export async function createInstantiator(options, swift) { let optResult; if (isSome1) { const arrayLen = i32Stack.pop(); - const arrayResult = []; - for (let i = 0; i < arrayLen; i++) { - const int = i32Stack.pop(); - arrayResult.push(int); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); optResult = arrayResult; } else { optResult = null; @@ -713,19 +823,24 @@ export async function createInstantiator(options, swift) { 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; + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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.push(optValue); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processOptionalDirectionArray: function bjs_processOptionalDirectionArray(directions) { @@ -739,19 +854,24 @@ export async function createInstantiator(options, swift) { 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; + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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.push(optValue); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processOptionalStatusArray: function bjs_processOptionalStatusArray(statuses) { @@ -765,19 +885,24 @@ export async function createInstantiator(options, swift) { 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; + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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.push(optValue); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processNestedIntArray: function bjs_processNestedIntArray(values) { @@ -790,18 +915,28 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + let arrayResult1; + if (arrayLen1 === -1) { + arrayResult1 = taStack.pop(); + } else { + arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const int = i32Stack.pop(); + arrayResult1.push(int); + } + arrayResult1.reverse(); + } + arrayResult.push(arrayResult1); } - arrayResult1.reverse(); - arrayResult.push(arrayResult1); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processNestedStringArray: function bjs_processNestedStringArray(values) { @@ -817,18 +952,28 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + let arrayResult1; + if (arrayLen1 === -1) { + arrayResult1 = taStack.pop(); + } else { + arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const string = strStack.pop(); + arrayResult1.push(string); + } + arrayResult1.reverse(); + } + arrayResult.push(arrayResult1); } - arrayResult1.reverse(); - arrayResult.push(arrayResult1); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processNestedPointArray: function bjs_processNestedPointArray(points) { @@ -841,18 +986,28 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + let arrayResult1; + if (arrayLen1 === -1) { + arrayResult1 = taStack.pop(); + } else { + arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const struct = structHelpers.Point.lift(); + arrayResult1.push(struct); + } + arrayResult1.reverse(); + } + arrayResult.push(arrayResult1); } - arrayResult1.reverse(); - arrayResult.push(arrayResult1); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processItemArray: function bjs_processItemArray(items) { @@ -862,13 +1017,18 @@ export async function createInstantiator(options, swift) { 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 = Item.__construct(ptr); - arrayResult.push(obj); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = ptrStack.pop(); + const obj = Item.__construct(ptr); + arrayResult.push(obj); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processNestedItemArray: function bjs_processNestedItemArray(items) { @@ -881,19 +1041,29 @@ export async function createInstantiator(options, swift) { 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 = Item.__construct(ptr); - arrayResult1.push(obj); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + let arrayResult1; + if (arrayLen1 === -1) { + arrayResult1 = taStack.pop(); + } else { + arrayResult1 = []; + for (let i1 = 0; i1 < arrayLen1; i1++) { + const ptr = ptrStack.pop(); + const obj = Item.__construct(ptr); + arrayResult1.push(obj); + } + arrayResult1.reverse(); + } + arrayResult.push(arrayResult1); } - arrayResult1.reverse(); - arrayResult.push(arrayResult1); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processJSObjectArray: function bjs_processJSObjectArray(objects) { @@ -904,14 +1074,19 @@ export async function createInstantiator(options, swift) { 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(); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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(); + } return arrayResult; }, processOptionalJSObjectArray: function bjs_processOptionalJSObjectArray(objects) { @@ -926,21 +1101,26 @@ export async function createInstantiator(options, swift) { 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; + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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.push(optValue); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, processNestedJSObjectArray: function bjs_processNestedJSObjectArray(objects) { @@ -954,20 +1134,30 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const arrayLen1 = i32Stack.pop(); + let arrayResult1; + if (arrayLen1 === -1) { + arrayResult1 = taStack.pop(); + } else { + 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); } - arrayResult1.reverse(); - arrayResult.push(arrayResult1); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, multiArrayParams: function bjs_multiArrayParams(nums, strs) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.d.ts index aecab090e..507a96d4a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.d.ts @@ -4,6 +4,26 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. +export const AsyncDirectionValues: { + readonly North: 0; + readonly South: 1; +}; +export type AsyncDirectionTag = typeof AsyncDirectionValues[keyof typeof AsyncDirectionValues]; + +export const AsyncThemeValues: { + readonly Light: "light"; + readonly Dark: "dark"; +}; +export type AsyncThemeTag = typeof AsyncThemeValues[keyof typeof AsyncThemeValues]; + +export interface AsyncPoint { + x: number; + y: number; +} +export type AsyncDirectionObject = typeof AsyncDirectionValues; + +export type AsyncThemeObject = typeof AsyncThemeValues; + export type Exports = { asyncReturnVoid(): Promise; asyncRoundTripInt(v: number): Promise; @@ -12,6 +32,21 @@ export type Exports = { asyncRoundTripFloat(v: number): Promise; asyncRoundTripDouble(v: number): Promise; asyncRoundTripJSObject(v: any): Promise; + asyncRoundTripStruct(v: AsyncPoint): Promise; + asyncRoundTripStructThrows(v: AsyncPoint): Promise; + asyncThrowsZeroArg(): Promise; + asyncCombineStructs(a: AsyncPoint, b: AsyncPoint): Promise; + asyncRoundTripEnum(v: AsyncDirectionTag): Promise; + asyncRoundTripRawEnum(v: AsyncThemeTag): Promise; + asyncRoundTripOptionalEnum(v: AsyncDirectionTag | null): Promise; + asyncRoundTripOptionalRawEnum(v: AsyncThemeTag | null): Promise; + asyncRoundTripOptionalStruct(v: AsyncPoint | null): Promise; + asyncRoundTripStructArray(v: AsyncPoint[]): Promise; + asyncRoundTripEnumArray(v: AsyncDirectionTag[]): Promise; + asyncRoundTripStructDictionary(v: Record): Promise>; + asyncRoundTripEnumDictionary(v: Record): Promise>; + AsyncDirection: AsyncDirectionObject + AsyncTheme: AsyncThemeObject } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js index bf368738e..9319cdd7e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js @@ -4,6 +4,16 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. +export const AsyncDirectionValues = { + North: 0, + South: 1, +}; + +export const AsyncThemeValues = { + Light: "light", + Dark: "dark", +}; + export async function createInstantiator(options, swift) { let instance; let memory; @@ -25,11 +35,112 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; 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; + } + + const __bjs_createAsyncPointHelpers = () => ({ + lower: (value) => { + i32Stack.push((value.x | 0)); + i32Stack.push((value.y | 0)); + }, + lift: () => { + const int = i32Stack.pop(); + const int1 = i32Stack.pop(); + return { x: int1, y: int }; + } + }); return { /** @@ -98,6 +209,210 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + bjs["swift_js_struct_lower_AsyncPoint"] = function(objectId) { + structHelpers.AsyncPoint.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_AsyncPoint"] = function() { + const value = structHelpers.AsyncPoint.lift(); + return swift.memory.retain(value); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + bjs["promise_resolve_TestModule_y"] = function(promise) { + try { + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Si"] = function(promise, value) { + try { + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(value); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_SS"] = function(promise, valueBytes, valueCount) { + try { + const string = decodeString(valueBytes, valueCount); + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(string); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sb"] = function(promise, value) { + try { + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(value !== 0); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sf"] = function(promise, value) { + try { + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(value); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sd"] = function(promise, value) { + try { + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(value); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_8JSObjectC"] = function(promise, value) { + try { + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(swift.memory.getObject(value)); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_10AsyncPointV"] = function(promise, value) { + try { + const value1 = swift.memory.getObject(value); + swift.memory.release(value); + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(value1); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_14AsyncDirectionO"] = function(promise, value) { + try { + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(value); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_10AsyncThemeO"] = function(promise, valueBytes, valueCount) { + try { + const string = decodeString(valueBytes, valueCount); + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(string); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sq14AsyncDirectionO"] = function(promise, valueIsSome, valueWrappedValue) { + try { + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(valueIsSome ? valueWrappedValue : null); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sq10AsyncThemeO"] = function(promise, valueIsSome, valueBytes, valueCount) { + try { + let optResult; + if (valueIsSome) { + const string = decodeString(valueBytes, valueCount); + optResult = string; + } else { + optResult = null; + } + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(optResult); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sq10AsyncPointV"] = function(promise, value) { + try { + let optResult; + if (value) { + const struct = structHelpers.AsyncPoint.lift(); + optResult = struct; + } else { + optResult = null; + } + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(optResult); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sa10AsyncPointV"] = function(promise) { + try { + const arrayLen = i32Stack.pop(); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const struct = structHelpers.AsyncPoint.lift(); + arrayResult.push(struct); + } + arrayResult.reverse(); + } + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(arrayResult); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sa14AsyncDirectionO"] = function(promise) { + try { + const arrayLen = i32Stack.pop(); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const caseId = i32Stack.pop(); + arrayResult.push(caseId); + } + arrayResult.reverse(); + } + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(arrayResult); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_SD10AsyncPointV"] = function(promise) { + try { + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const struct = structHelpers.AsyncPoint.lift(); + const string = strStack.pop(); + dictResult[string] = struct; + } + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(dictResult); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_SD14AsyncDirectionO"] = function(promise) { + try { + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const caseId = i32Stack.pop(); + const string = strStack.pop(); + dictResult[string] = caseId; + } + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(dictResult); + } catch (error) { + setException(error); + } + } + bjs["promise_reject_TestModule"] = function(promise, valueKind, valuePayload1, valuePayload2) { + try { + const jsValue = __bjs_jsValueLift(valueKind, valuePayload1, valuePayload2); + swift.memory.getObject(promise)[__bjs_promiseSettlers].reject(jsValue); + } catch (error) { + setException(error); + } + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -202,6 +517,9 @@ export async function createInstantiator(options, swift) { /** @param {WebAssembly.Instance} instance */ createExports: (instance) => { const js = swift.memory.heap; + const AsyncPointHelpers = __bjs_createAsyncPointHelpers(); + structHelpers.AsyncPoint = AsyncPointHelpers; + const exports = { asyncReturnVoid: function bjs_asyncReturnVoid() { const ret = instance.exports.bjs_asyncReturnVoid(); @@ -247,6 +565,149 @@ export async function createInstantiator(options, swift) { swift.memory.release(ret); return ret1; }, + asyncRoundTripStruct: function bjs_asyncRoundTripStruct(v) { + structHelpers.AsyncPoint.lower(v); + const ret = instance.exports.bjs_asyncRoundTripStruct(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripStructThrows: function bjs_asyncRoundTripStructThrows(v) { + structHelpers.AsyncPoint.lower(v); + const ret = instance.exports.bjs_asyncRoundTripStructThrows(); + 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; + }, + asyncThrowsZeroArg: function bjs_asyncThrowsZeroArg() { + const ret = instance.exports.bjs_asyncThrowsZeroArg(); + 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; + }, + asyncCombineStructs: function bjs_asyncCombineStructs(a, b) { + structHelpers.AsyncPoint.lower(a); + structHelpers.AsyncPoint.lower(b); + const ret = instance.exports.bjs_asyncCombineStructs(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripEnum: function bjs_asyncRoundTripEnum(v) { + const ret = instance.exports.bjs_asyncRoundTripEnum(v); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripRawEnum: function bjs_asyncRoundTripRawEnum(v) { + const vBytes = textEncoder.encode(v); + const vId = swift.memory.retain(vBytes); + const ret = instance.exports.bjs_asyncRoundTripRawEnum(vId, vBytes.length); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripOptionalEnum: function bjs_asyncRoundTripOptionalEnum(v) { + const isSome = v != null; + const ret = instance.exports.bjs_asyncRoundTripOptionalEnum(+isSome, isSome ? v : 0); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripOptionalRawEnum: function bjs_asyncRoundTripOptionalRawEnum(v) { + const isSome = v != null; + let result, result1; + if (isSome) { + const vBytes = textEncoder.encode(v); + const vId = swift.memory.retain(vBytes); + result = vId; + result1 = vBytes.length; + } else { + result = 0; + result1 = 0; + } + const ret = instance.exports.bjs_asyncRoundTripOptionalRawEnum(+isSome, result, result1); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripOptionalStruct: function bjs_asyncRoundTripOptionalStruct(v) { + const isSome = v != null; + if (isSome) { + structHelpers.AsyncPoint.lower(v); + } + i32Stack.push(+isSome); + const ret = instance.exports.bjs_asyncRoundTripOptionalStruct(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripStructArray: function bjs_asyncRoundTripStructArray(v) { + for (const elem of v) { + structHelpers.AsyncPoint.lower(elem); + } + i32Stack.push(v.length); + const ret = instance.exports.bjs_asyncRoundTripStructArray(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripEnumArray: function bjs_asyncRoundTripEnumArray(v) { + for (const elem of v) { + i32Stack.push((elem | 0)); + } + i32Stack.push(v.length); + const ret = instance.exports.bjs_asyncRoundTripEnumArray(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripStructDictionary: function bjs_asyncRoundTripStructDictionary(v) { + const entries = Object.entries(v); + 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); + structHelpers.AsyncPoint.lower(value); + } + i32Stack.push(entries.length); + const ret = instance.exports.bjs_asyncRoundTripStructDictionary(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripEnumDictionary: function bjs_asyncRoundTripEnumDictionary(v) { + const entries = Object.entries(v); + 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); + const ret = instance.exports.bjs_asyncRoundTripEnumDictionary(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + AsyncDirection: AsyncDirectionValues, + AsyncTheme: AsyncThemeValues, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.d.ts new file mode 100644 index 000000000..d25336ef7 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.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`. + +export const AsyncPayloadResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Idle: 2; + }; +}; + +export type AsyncPayloadResultTag = + { tag: typeof AsyncPayloadResultValues.Tag.Success; param0: string } | { tag: typeof AsyncPayloadResultValues.Tag.Failure; param0: number } | { tag: typeof AsyncPayloadResultValues.Tag.Idle } + +export type AsyncPayloadResultObject = typeof AsyncPayloadResultValues; + +export type Exports = { + asyncRoundTripAssociatedValueEnum(value: AsyncPayloadResultTag): Promise; + asyncRoundTripOptionalAssociatedValueEnum(value: AsyncPayloadResultTag | null): Promise; + AsyncPayloadResult: AsyncPayloadResultObject +} +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/AsyncAssociatedValueEnum.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js new file mode 100644 index 000000000..69e4a4928 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js @@ -0,0 +1,414 @@ +// 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 AsyncPayloadResultValues = { + Tag: { + Success: 0, + Failure: 1, + Idle: 2, + }, +}; +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + let decodeString; + 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 i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + 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; + } + + const __bjs_createAsyncPayloadResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case AsyncPayloadResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return AsyncPayloadResultValues.Tag.Success; + } + case AsyncPayloadResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + return AsyncPayloadResultValues.Tag.Failure; + } + case AsyncPayloadResultValues.Tag.Idle: { + return AsyncPayloadResultValues.Tag.Idle; + } + default: throw new Error("Unknown AsyncPayloadResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case AsyncPayloadResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: AsyncPayloadResultValues.Tag.Success, param0: string }; + } + case AsyncPayloadResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: AsyncPayloadResultValues.Tag.Failure, param0: int }; + } + case AsyncPayloadResultValues.Tag.Idle: return { tag: AsyncPayloadResultValues.Tag.Idle }; + default: throw new Error("Unknown AsyncPayloadResultValues 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) { + tmpRetString = decodeString(ptr, len); + } + 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) { + return swift.memory.retain(decodeString(ptr, len)); + } + 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 value = decodeString(ptr, len); + 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_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + bjs["promise_resolve_TestModule_18AsyncPayloadResultO"] = function(promise, value) { + try { + const enumValue = enumHelpers.AsyncPayloadResult.lift(value); + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(enumValue); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sq18AsyncPayloadResultO"] = function(promise, valueIsSome, valueCaseId) { + try { + let optResult; + if (valueIsSome) { + const enumValue = enumHelpers.AsyncPayloadResult.lift(valueCaseId); + optResult = enumValue; + } else { + optResult = null; + } + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(optResult); + } catch (error) { + setException(error); + } + } + bjs["promise_reject_TestModule"] = function(promise, valueKind, valuePayload1, valuePayload2) { + try { + const jsValue = __bjs_jsValueLift(valueKind, valuePayload1, valuePayload2); + swift.memory.getObject(promise)[__bjs_promiseSettlers].reject(jsValue); + } catch (error) { + setException(error); + } + } + 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 { + tmpRetString = decodeString(ptr, len); + } + } + 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; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const AsyncPayloadResultHelpers = __bjs_createAsyncPayloadResultValuesHelpers(); + enumHelpers.AsyncPayloadResult = AsyncPayloadResultHelpers; + + const exports = { + asyncRoundTripAssociatedValueEnum: function bjs_asyncRoundTripAssociatedValueEnum(value) { + const valueCaseId = enumHelpers.AsyncPayloadResult.lower(value); + const ret = instance.exports.bjs_asyncRoundTripAssociatedValueEnum(valueCaseId); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripOptionalAssociatedValueEnum: function bjs_asyncRoundTripOptionalAssociatedValueEnum(value) { + const isSome = value != null; + let result; + if (isSome) { + const valueCaseId = enumHelpers.AsyncPayloadResult.lower(value); + result = valueCaseId; + } else { + result = 0; + } + const ret = instance.exports.bjs_asyncRoundTripOptionalAssociatedValueEnum(+isSome, result); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + AsyncPayloadResult: AsyncPayloadResultValues, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js index 89ab29827..27e53b8d7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -213,6 +214,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js index 7fd6a0d6b..789379a32 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -212,6 +213,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index cafd250b0..4b13bb633 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -31,6 +31,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -140,6 +141,13 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } bjs["swift_js_struct_lower_Config"] = function(objectId) { structHelpers.Config.lower(swift.memory.getObject(objectId)); } @@ -154,6 +162,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.MathOperations.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -550,12 +565,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, testStringArrayDefault: function bjs_testStringArrayDefault(names = ["a", "b", "c"]) { @@ -568,12 +588,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, testDoubleArrayDefault: function bjs_testDoubleArrayDefault(values = [1.5, 2.5, 3.5]) { @@ -583,12 +608,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const f64 = f64Stack.pop(); + arrayResult.push(f64); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, testBoolArrayDefault: function bjs_testBoolArrayDefault(flags = [true, false, true]) { @@ -598,12 +628,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const bool = i32Stack.pop() !== 0; + arrayResult.push(bool); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, testEmptyArrayDefault: function bjs_testEmptyArrayDefault(items = []) { @@ -613,12 +648,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, testMixedWithArrayDefault: function bjs_testMixedWithArrayDefault(name = "test", values = [10, 20, 30], enabled = true) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index 920017972..2021f1c96 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -139,6 +140,13 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } bjs["swift_js_struct_lower_Counters"] = function(objectId) { structHelpers.Counters.lower(swift.memory.getObject(objectId)); } @@ -146,6 +154,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.Counters.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -420,12 +435,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i1 = 0; i1 < arrayLen; i1++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); const string = strStack.pop(); dictResult[string] = arrayResult; } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js index 3d2230c6c..d97e4ef11 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -106,6 +106,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -623,12 +624,17 @@ export async function createInstantiator(options, swift) { } case AllTypesResultValues.Tag.ArrayPayload: { const arrayLen = i32Stack.pop(); - const arrayResult = []; - for (let i = 0; i < arrayLen; i++) { - const int = i32Stack.pop(); - arrayResult.push(int); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); return { tag: AllTypesResultValues.Tag.ArrayPayload, param0: arrayResult }; } case AllTypesResultValues.Tag.Empty: return { tag: AllTypesResultValues.Tag.Empty }; @@ -748,12 +754,17 @@ export async function createInstantiator(options, swift) { optValue = null; } else { const arrayLen = i32Stack.pop(); - const arrayResult = []; - for (let i = 0; i < arrayLen; i++) { - const int = i32Stack.pop(); - arrayResult.push(int); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); optValue = arrayResult; } return { tag: OptionalAllTypesResultValues.Tag.OptArray, param0: optValue }; @@ -831,6 +842,13 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } bjs["swift_js_struct_lower_Point"] = function(objectId) { structHelpers.Point.lower(swift.memory.getObject(objectId)); } @@ -838,6 +856,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.Point.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.d.ts new file mode 100644 index 000000000..d29256af4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.d.ts @@ -0,0 +1,39 @@ +// 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 PayloadSignalValues: { + readonly Tag: { + readonly Start: 0; + readonly Stop: 1; + readonly Idle: 2; + }; +}; + +export type PayloadSignalTag = + { tag: typeof PayloadSignalValues.Tag.Start; param0: string } | { tag: typeof PayloadSignalValues.Tag.Stop; param0: number } | { tag: typeof PayloadSignalValues.Tag.Idle } + +export type PayloadSignalObject = typeof PayloadSignalValues; + +export interface PayloadSignalControls { + send(signal: PayloadSignalTag): void; + current(): PayloadSignalTag; + roundTripOptional(signal: PayloadSignalTag | null): PayloadSignalTag | null; +} +export type Exports = { + PayloadSignal: PayloadSignalObject +} +export type Imports = { + PayloadSignalControls: { + roundTrip(signal: PayloadSignalTag): PayloadSignalTag; + } +} +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/EnumAssociatedValueImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js new file mode 100644 index 000000000..1688dc94d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js @@ -0,0 +1,323 @@ +// 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 PayloadSignalValues = { + Tag: { + Start: 0, + Stop: 1, + Idle: 2, + }, +}; +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + let decodeString; + 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 i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPayloadSignalValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case PayloadSignalValues.Tag.Start: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return PayloadSignalValues.Tag.Start; + } + case PayloadSignalValues.Tag.Stop: { + i32Stack.push((value.param0 | 0)); + return PayloadSignalValues.Tag.Stop; + } + case PayloadSignalValues.Tag.Idle: { + return PayloadSignalValues.Tag.Idle; + } + default: throw new Error("Unknown PayloadSignalValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case PayloadSignalValues.Tag.Start: { + const string = strStack.pop(); + return { tag: PayloadSignalValues.Tag.Start, param0: string }; + } + case PayloadSignalValues.Tag.Stop: { + const int = i32Stack.pop(); + return { tag: PayloadSignalValues.Tag.Stop, param0: int }; + } + case PayloadSignalValues.Tag.Idle: return { tag: PayloadSignalValues.Tag.Idle }; + default: throw new Error("Unknown PayloadSignalValues 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) { + tmpRetString = decodeString(ptr, len); + } + 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) { + return swift.memory.retain(decodeString(ptr, len)); + } + 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 value = decodeString(ptr, len); + 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_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + 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 { + tmpRetString = decodeString(ptr, len); + } + } + 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_PayloadSignalControls_roundTrip_static"] = function bjs_PayloadSignalControls_roundTrip_static(signal) { + try { + const enumValue = enumHelpers.PayloadSignal.lift(signal); + let ret = imports.PayloadSignalControls.roundTrip(enumValue); + const caseId = enumHelpers.PayloadSignal.lower(ret); + return caseId; + } catch (error) { + setException(error); + } + } + TestModule["bjs_PayloadSignalControls_send"] = function bjs_PayloadSignalControls_send(self, signal) { + try { + const enumValue = enumHelpers.PayloadSignal.lift(signal); + swift.memory.getObject(self).send(enumValue); + } catch (error) { + setException(error); + } + } + TestModule["bjs_PayloadSignalControls_current"] = function bjs_PayloadSignalControls_current(self) { + try { + let ret = swift.memory.getObject(self).current(); + const caseId = enumHelpers.PayloadSignal.lower(ret); + return caseId; + } catch (error) { + setException(error); + } + } + TestModule["bjs_PayloadSignalControls_roundTripOptional"] = function bjs_PayloadSignalControls_roundTripOptional(self, signalIsSome, signalCaseId) { + try { + let optResult; + if (signalIsSome) { + const enumValue = enumHelpers.PayloadSignal.lift(signalCaseId); + optResult = enumValue; + } else { + optResult = null; + } + let ret = swift.memory.getObject(self).roundTripOptional(optResult); + const isSome = ret != null; + if (isSome) { + const caseId = enumHelpers.PayloadSignal.lower(ret); + return caseId; + } else { + return -1; + } + } catch (error) { + setException(error); + } + } + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const PayloadSignalHelpers = __bjs_createPayloadSignalValuesHelpers(); + enumHelpers.PayloadSignal = PayloadSignalHelpers; + + const exports = { + PayloadSignal: PayloadSignalValues, + }; + _exports = exports; + return 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 index fe94c046f..b4c5870b6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js @@ -49,6 +49,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -122,6 +123,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.d.ts new file mode 100644 index 000000000..fe48c9174 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.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`. + +export const SignalValues: { + readonly Start: 0; + readonly Stop: 1; +}; +export type SignalTag = typeof SignalValues[keyof typeof SignalValues]; + +export type SignalObject = typeof SignalValues; + +export interface SignalControls { + send(signal: SignalTag): void; + current(): SignalTag; +} +export type Exports = { + Signal: SignalObject +} +export type Imports = { + SignalControls: { + roundTrip(signal: SignalTag): SignalTag; + } +} +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/EnumCaseImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js new file mode 100644 index 000000000..dc1b3c6b3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js @@ -0,0 +1,258 @@ +// 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 SignalValues = { + Start: 0, + Stop: 1, +}; + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + let decodeString; + 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 i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + 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) { + tmpRetString = decodeString(ptr, len); + } + 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) { + return swift.memory.retain(decodeString(ptr, len)); + } + 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 value = decodeString(ptr, len); + 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_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + 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 { + tmpRetString = decodeString(ptr, len); + } + } + 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_SignalControls_roundTrip_static"] = function bjs_SignalControls_roundTrip_static(signal) { + try { + let ret = imports.SignalControls.roundTrip(signal); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + TestModule["bjs_SignalControls_send"] = function bjs_SignalControls_send(self, signal) { + try { + swift.memory.getObject(self).send(signal); + } catch (error) { + setException(error); + } + } + TestModule["bjs_SignalControls_current"] = function bjs_SignalControls_current(self) { + try { + let ret = swift.memory.getObject(self).current(); + return ret; + } catch (error) { + setException(error); + return 0 + } + } + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + 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 = { + Signal: SignalValues, + }; + _exports = exports; + return 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 index 10fe31f64..050c16b18 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -69,6 +69,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -142,6 +143,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index a6aeee4b0..9f2f4122c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -50,6 +50,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -123,6 +124,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js index 7e5334811..2ab98b31b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js @@ -100,6 +100,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -174,6 +175,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -432,7 +447,7 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalFileSize: function bjs_roundTripOptionalFileSize(input) { const isSome = input != null; - instance.exports.bjs_roundTripOptionalFileSize(+isSome, isSome ? input : 0); + instance.exports.bjs_roundTripOptionalFileSize(+isSome, isSome ? input : 0n); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { @@ -480,7 +495,7 @@ export async function createInstantiator(options, swift) { }, roundTripOptionalSessionId: function bjs_roundTripOptionalSessionId(input) { const isSome = input != null; - instance.exports.bjs_roundTripOptionalSessionId(+isSome, isSome ? input : 0); + instance.exports.bjs_roundTripOptionalSessionId(+isSome, isSome ? input : 0n); const isSome1 = i32Stack.pop(); let optResult; if (isSome1) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js index 53ddd7301..94bfe89cd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -250,7 +265,7 @@ export async function createInstantiator(options, swift) { return ret; } catch (error) { setException(error); - return 0 + return 0n } } TestModule["bjs_roundTripUInt64"] = function bjs_roundTripUInt64(v) { @@ -259,7 +274,7 @@ export async function createInstantiator(options, swift) { return ret; } catch (error) { setException(error); - return 0 + return 0n } } }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js index 346b74eac..174c9b430 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js index f74095374..e8a89c6e4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js index c2490c0ea..99c0bb4ea 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js index d970c5d77..82458b81a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js index d970c5d77..82458b81a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js index 06cf6550e..8ebcbda28 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -193,12 +208,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); } - arrayResult.reverse(); let ret = imports.roundtrip(arrayResult); for (const elem of ret) { i32Stack.push((elem | 0)); @@ -211,12 +231,17 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const string = strStack.pop(); + arrayResult.push(string); + } + arrayResult.reverse(); } - arrayResult.reverse(); imports.logStrings(arrayResult); } catch (error) { setException(error); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js index c469fcb58..710eebe36 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -137,6 +138,13 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } bjs["swift_js_struct_lower_FooContainer"] = function(objectId) { structHelpers.FooContainer.lower(swift.memory.getObject(objectId)); } @@ -144,6 +152,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.FooContainer.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -281,14 +296,19 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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(); } - arrayResult.reverse(); return arrayResult; }, processOptionalFooArray: function bjs_processOptionalFooArray(foos) { @@ -303,21 +323,26 @@ export async function createInstantiator(options, swift) { 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; + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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.push(optValue); + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; }, roundtripFooContainer: function bjs_roundtripFooContainer(container) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js index 952197c2a..605359fb8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js index 88a5adb38..e24b5dac5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js index 10fafb7a0..b936636a9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.d.ts new file mode 100644 index 000000000..b842e7d7d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.d.ts @@ -0,0 +1,21 @@ +// 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 = { + processBytes(data: Uint8Array): Uint8Array; + processFloats(data: Float32Array): Float32Array; + processGenericDoubles(data: Float64Array): Float64Array; + processGenericInts(data: Int32Array): Int32Array; +} +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/JSTypedArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js new file mode 100644 index 000000000..c5c37a512 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js @@ -0,0 +1,250 @@ +// 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; + let decodeString; + 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 i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + 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) { + tmpRetString = decodeString(ptr, len); + } + 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) { + return swift.memory.retain(decodeString(ptr, len)); + } + 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 value = decodeString(ptr, len); + 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_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + 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 { + tmpRetString = decodeString(ptr, len); + } + } + 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; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + 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 = { + processBytes: function bjs_processBytes(data) { + const ret = instance.exports.bjs_processBytes(swift.memory.retain(data)); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + processFloats: function bjs_processFloats(data) { + const ret = instance.exports.bjs_processFloats(swift.memory.retain(data)); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + processGenericDoubles: function bjs_processGenericDoubles(data) { + const ret = instance.exports.bjs_processGenericDoubles(swift.memory.retain(data)); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + processGenericInts: function bjs_processGenericInts(data) { + const ret = instance.exports.bjs_processGenericInts(swift.memory.retain(data)); + 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/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index 0258b63b6..e8f617e5b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -188,6 +189,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -302,15 +317,20 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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(); } - arrayResult.reverse(); let ret = imports.jsEchoJSValueArray(arrayResult); for (const elem of ret) { const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem); @@ -553,15 +573,20 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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(); } - arrayResult.reverse(); return arrayResult; }, roundTripOptionalJSValueArray: function bjs_roundTripOptionalJSValueArray(values) { @@ -581,15 +606,20 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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(); } - arrayResult.reverse(); optResult = arrayResult; } else { optResult = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index 195eef468..3abacf371 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index ca54493f6..a2dc23d68 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index 3551caab2..7fdf9b4c8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js index a63df44be..09a6ace60 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -341,13 +356,18 @@ export async function createInstantiator(options, swift) { getItems() { instance.exports.bjs_Collections_Container_getItems(this.pointer); const arrayLen = i32Stack.pop(); - const arrayResult = []; - for (let i = 0; i < arrayLen; i++) { - const ptr = ptrStack.pop(); - const obj = Greeter.__construct(ptr); - arrayResult.push(obj); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = ptrStack.pop(); + const obj = Greeter.__construct(ptr); + arrayResult.push(obj); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; } addItem(item) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js index 32a325bda..1c9287a08 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -341,13 +356,18 @@ export async function createInstantiator(options, swift) { getItems() { instance.exports.bjs_Collections_Container_getItems(this.pointer); const arrayLen = i32Stack.pop(); - const arrayResult = []; - for (let i = 0; i < arrayLen; i++) { - const ptr = ptrStack.pop(); - const obj = Greeter.__construct(ptr); - arrayResult.push(obj); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = ptrStack.pop(); + const obj = Greeter.__construct(ptr); + arrayResult.push(obj); + } + arrayResult.reverse(); } - arrayResult.reverse(); return arrayResult; } addItem(item) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.d.ts new file mode 100644 index 000000000..4e966661e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.d.ts @@ -0,0 +1,46 @@ +// 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 namespace Player { + export interface Stats { + level: number; + rating: string; + } +} +export namespace User { + export interface Stats { + health: number; + score: 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 User extends SwiftHeapObject { + getName(): string; +} +export interface Player extends SwiftHeapObject { + getTag(): string; +} +export type Exports = { + User: { + } + Player: { + } +} +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/NestedType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js new file mode 100644 index 000000000..7c2751964 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js @@ -0,0 +1,364 @@ +// 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; + let decodeString; + 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 i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createUser_StatsHelpers = () => ({ + lower: (value) => { + i32Stack.push((value.health | 0)); + f64Stack.push(value.score); + }, + lift: () => { + const f64 = f64Stack.pop(); + const int = i32Stack.pop(); + return { health: int, score: f64 }; + } + }); + const __bjs_createPlayer_StatsHelpers = () => ({ + lower: (value) => { + i32Stack.push((value.level | 0)); + const bytes = textEncoder.encode(value.rating); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + }, + lift: () => { + const string = strStack.pop(); + const int = i32Stack.pop(); + return { level: int, rating: string }; + } + }); + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + tmpRetString = decodeString(ptr, len); + } + 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) { + return swift.memory.retain(decodeString(ptr, len)); + } + 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 value = decodeString(ptr, len); + 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_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + bjs["swift_js_struct_lower_User_Stats"] = function(objectId) { + structHelpers.User_Stats.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_User_Stats"] = function() { + const value = structHelpers.User_Stats.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Player_Stats"] = function(objectId) { + structHelpers.Player_Stats.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_Player_Stats"] = function() { + const value = structHelpers.Player_Stats.lift(); + return swift.memory.retain(value); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + 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 { + tmpRetString = decodeString(ptr, len); + } + } + 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_Player_wrap"] = function(pointer) { + const obj = _exports['Player'].__construct(pointer); + return swift.memory.retain(obj); + }; + 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; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + 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.identityMap?.delete(state.pointer); + state.deinit(state.pointer); + }); + + /// Represents a Swift heap object like a class instance or an actor instance. + class SwiftHeapObject { + static __wrap(pointer, deinit, prototype, identityCache) { + const makeFresh = (identityMap) => { + const obj = Object.create(prototype); + const state = { pointer, deinit, hasReleased: false, identityMap }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + if (identityMap) { + identityMap.set(pointer, new WeakRef(obj)); + } + return obj; + }; + + if (!identityCache) { + return makeFresh(null); + } + + const cached = identityCache.get(pointer)?.deref(); + if (cached && !cached.__swiftHeapObjectState.hasReleased) { + deinit(pointer); + return cached; + } + if (identityCache.has(pointer)) { + identityCache.delete(pointer); + } + + return makeFresh(identityCache); + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.identityMap?.delete(state.pointer); + state.deinit(state.pointer); + } + } + class User extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_User_deinit, User.prototype, null); + } + + getName() { + instance.exports.bjs_User_getName(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + class Player extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Player_deinit, Player.prototype, null); + } + + getTag() { + instance.exports.bjs_Player_getTag(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + const User_StatsHelpers = __bjs_createUser_StatsHelpers(); + structHelpers.User_Stats = User_StatsHelpers; + + const Player_StatsHelpers = __bjs_createPlayer_StatsHelpers(); + structHelpers.Player_Stats = Player_StatsHelpers; + + const exports = { + User, + Player, + Player: { + }, + User: { + }, + }; + _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 index a5a6e16fb..c4a22ac0c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.d.ts @@ -30,6 +30,7 @@ export interface WithOptionalJSClass { roundTripBoolOrUndefined(value: boolean | undefined): boolean | undefined; roundTripIntOrNull(value: number | null): number | null; roundTripIntOrUndefined(value: number | undefined): number | undefined; + roundTripChildOrNull(value: WithOptionalJSClass | null): WithOptionalJSClass | null; stringOrNull: string | null; stringOrUndefined: string | undefined; doubleOrNull: number | null; @@ -38,6 +39,7 @@ export interface WithOptionalJSClass { boolOrUndefined: boolean | undefined; intOrNull: number | null; intOrUndefined: number | undefined; + childOrNull: WithOptionalJSClass | null; } export type Exports = { Greeter: { @@ -48,6 +50,8 @@ export type Exports = { } roundTripOptionalClass(value: Greeter | null): Greeter | null; testOptionalPropertyRoundtrip(holder: OptionalPropertyHolder | null): OptionalPropertyHolder | null; + roundTripExportedOptionalJSObject(value: any | null): any | null; + roundTripExportedOptionalJSClass(value: WithOptionalJSClass | null): WithOptionalJSClass | null; roundTripString(name: string | null): string | null; roundTripInt(value: number | null): number | null; roundTripInt8(value: number | null): number | null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js index 5971c2fa8..c3c41f332 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -296,6 +311,19 @@ export async function createInstantiator(options, swift) { setException(error); } } + TestModule["bjs_WithOptionalJSClass_childOrNull_get"] = function bjs_WithOptionalJSClass_childOrNull_get(self) { + try { + let ret = swift.memory.getObject(self).childOrNull; + const isSome = ret != null; + if (isSome) { + const objId = swift.memory.retain(ret); + i32Stack.push(objId); + } + i32Stack.push(isSome ? 1 : 0); + } catch (error) { + setException(error); + } + } TestModule["bjs_WithOptionalJSClass_stringOrNull_set"] = function bjs_WithOptionalJSClass_stringOrNull_set(self, newValueIsSome, newValueBytes, newValueCount) { try { let optResult; @@ -366,6 +394,13 @@ export async function createInstantiator(options, swift) { setException(error); } } + TestModule["bjs_WithOptionalJSClass_childOrNull_set"] = function bjs_WithOptionalJSClass_childOrNull_set(self, newValueIsSome, newValueObjectId) { + try { + swift.memory.getObject(self).childOrNull = newValueIsSome ? swift.memory.getObject(newValueObjectId) : null; + } catch (error) { + setException(error); + } + } TestModule["bjs_WithOptionalJSClass_roundTripStringOrNull"] = function bjs_WithOptionalJSClass_roundTripStringOrNull(self, valueIsSome, valueBytes, valueCount) { try { let optResult; @@ -452,6 +487,19 @@ export async function createInstantiator(options, swift) { setException(error); } } + TestModule["bjs_WithOptionalJSClass_roundTripChildOrNull"] = function bjs_WithOptionalJSClass_roundTripChildOrNull(self, valueIsSome, valueObjectId) { + try { + let ret = swift.memory.getObject(self).roundTripChildOrNull(valueIsSome ? swift.memory.getObject(valueObjectId) : null); + const isSome = ret != null; + if (isSome) { + const objId = swift.memory.retain(ret); + i32Stack.push(objId); + } + i32Stack.push(isSome ? 1 : 0); + } catch (error) { + setException(error); + } + } }, setInstance: (i) => { instance = i; @@ -666,6 +714,48 @@ export async function createInstantiator(options, swift) { const optResult = pointer === null ? null : OptionalPropertyHolder.__construct(pointer); return optResult; }, + roundTripExportedOptionalJSObject: function bjs_roundTripExportedOptionalJSObject(value) { + const isSome = value != null; + let result; + if (isSome) { + result = swift.memory.retain(value); + } else { + result = 0; + } + instance.exports.bjs_roundTripExportedOptionalJSObject(+isSome, result); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + const objId = i32Stack.pop(); + const obj = swift.memory.getObject(objId); + swift.memory.release(objId); + optResult = obj; + } else { + optResult = null; + } + return optResult; + }, + roundTripExportedOptionalJSClass: function bjs_roundTripExportedOptionalJSClass(value) { + const isSome = value != null; + let result; + if (isSome) { + result = swift.memory.retain(value); + } else { + result = 0; + } + instance.exports.bjs_roundTripExportedOptionalJSClass(+isSome, result); + const isSome1 = i32Stack.pop(); + let optResult; + if (isSome1) { + const objId = i32Stack.pop(); + const obj = swift.memory.getObject(objId); + swift.memory.release(objId); + optResult = obj; + } else { + optResult = null; + } + return optResult; + }, roundTripString: function bjs_roundTripString(name) { const isSome = name != null; let result, result1; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js index 490f2b4e2..3957b5482 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js index bec07b959..e624ceb1a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js index 7f840708e..6e66102e2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 9fb9b172b..ac533b6d4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -49,6 +49,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -155,6 +156,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -722,14 +737,19 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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(); } - arrayResult.reverse(); return arrayResult; } set delegates(value) { @@ -783,14 +803,19 @@ export async function createInstantiator(options, swift) { 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); + let arrayResult; + if (arrayLen === -1) { + arrayResult = taStack.pop(); + } else { + 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(); } - arrayResult.reverse(); return arrayResult; }, processDelegatesByName: function bjs_processDelegatesByName(delegates) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js index aefdb5679..102ac6020 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -123,6 +124,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js index ef685b8a4..5257c9856 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -36,6 +36,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -142,6 +143,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js index 1fd066076..91316a8c4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -36,6 +36,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -142,6 +143,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js index 5800fcb56..f238551a9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -30,6 +30,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -103,6 +104,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js index b81255810..c7f9b4955 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -30,6 +30,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -103,6 +104,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js index 033f08cd2..994e1710a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js index 8187b9e92..839e194cf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 9ee57d692..5ee56f5bc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts index ccc95eb3b..d024be7dd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts @@ -41,6 +41,9 @@ export const APIResultValues: { 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 interface Animal { + type: string; +} export type DirectionObject = typeof DirectionValues; export type ThemeObject = typeof ThemeValues; @@ -67,6 +70,8 @@ export type Exports = { TestProcessor: { new(transform: (arg0: string) => string): TestProcessor; } + roundtripAnimal(animalClosure: (arg0: Animal) => Animal): (arg0: Animal) => Animal; + roundtripOptionalAnimal(animalClosure: (arg0: Animal | null) => Animal | null): (arg0: Animal | null) => Animal | null; roundtripString(stringClosure: (arg0: string) => string): (arg0: string) => string; roundtripInt(intClosure: (arg0: number) => number): (arg0: number) => number; roundtripBool(boolClosure: (arg0: boolean) => boolean): (arg0: boolean) => boolean; @@ -92,6 +97,9 @@ export type Exports = { Theme: ThemeObject HttpStatus: HttpStatusObject APIResult: APIResultObject + Animal: { + init(type: string): Animal; + } } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 03a5504e4..cdd80e90a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -55,6 +55,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -85,6 +86,18 @@ export async function createInstantiator(options, swift) { return swift.memory.retain(real); }; + const __bjs_createAnimalHelpers = () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.type); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + }, + lift: () => { + const string = strStack.pop(); + return { type: string }; + } + }); const __bjs_createAPIResultValuesHelpers = () => ({ lower: (value) => { const enumTag = value.tag; @@ -214,6 +227,27 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + bjs["swift_js_struct_lower_Animal"] = function(objectId) { + structHelpers.Animal.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_Animal"] = function() { + const value = structHelpers.Animal.lift(); + return swift.memory.retain(value); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -359,6 +393,31 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule5ThemeO_5ThemeO); } + bjs["invoke_js_callback_TestModule_10TestModule6AnimalV_6AnimalV"] = function(callbackId) { + try { + const callback = swift.memory.getObject(callbackId); + const structValue = structHelpers.Animal.lift(); + let ret = callback(structValue); + structHelpers.Animal.lower(ret); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule6AnimalV_6AnimalV = function(param0) { + structHelpers.Animal.lower(param0); + instance.exports.invoke_swift_closure_TestModule_10TestModule6AnimalV_6AnimalV(boxPtr); + const structValue = structHelpers.Animal.lift(); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + return structValue; + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule6AnimalV_6AnimalV); + } bjs["invoke_js_callback_TestModule_10TestModule6PersonC_6PersonC"] = function(callbackId, param0) { try { const callback = swift.memory.getObject(callbackId); @@ -620,6 +679,46 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO); } + bjs["invoke_js_callback_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + let optResult; + if (param0) { + const struct = structHelpers.Animal.lift(); + optResult = struct; + } else { + optResult = null; + } + let ret = callback(optResult); + const isSome = ret != null; + if (isSome) { + structHelpers.Animal.lower(ret); + } + i32Stack.push(isSome ? 1 : 0); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV = function(param0) { + const isSome = param0 != null; + if (isSome) { + structHelpers.Animal.lower(param0); + } + i32Stack.push(+isSome); + instance.exports.invoke_swift_closure_TestModule_10TestModuleSq6AnimalV_Sq6AnimalV(boxPtr); + const isSome1 = i32Stack.pop(); + const optResult = isSome1 ? structHelpers.Animal.lift() : null; + 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_10TestModuleSq6AnimalV_Sq6AnimalV); + } bjs["invoke_js_callback_TestModule_10TestModuleSq6PersonC_Sq6PersonC"] = function(callbackId, param0IsSome, param0Pointer) { try { const callback = swift.memory.getObject(callbackId); @@ -971,12 +1070,25 @@ export async function createInstantiator(options, swift) { return TestProcessor.__construct(ret); } } + const AnimalHelpers = __bjs_createAnimalHelpers(); + structHelpers.Animal = AnimalHelpers; + const APIResultHelpers = __bjs_createAPIResultValuesHelpers(); enumHelpers.APIResult = APIResultHelpers; const exports = { Person, TestProcessor, + roundtripAnimal: function bjs_roundtripAnimal(animalClosure) { + const callbackId = swift.memory.retain(animalClosure); + const ret = instance.exports.bjs_roundtripAnimal(callbackId); + return swift.memory.getObject(ret); + }, + roundtripOptionalAnimal: function bjs_roundtripOptionalAnimal(animalClosure) { + const callbackId = swift.memory.retain(animalClosure); + const ret = instance.exports.bjs_roundtripOptionalAnimal(callbackId); + return swift.memory.getObject(ret); + }, roundtripString: function bjs_roundtripString(stringClosure) { const callbackId = swift.memory.retain(stringClosure); const ret = instance.exports.bjs_roundtripString(callbackId); @@ -1086,6 +1198,15 @@ export async function createInstantiator(options, swift) { Theme: ThemeValues, HttpStatus: HttpStatusValues, APIResult: APIResultValues, + Animal: { + init: function(type) { + const typeBytes = textEncoder.encode(type); + const typeId = swift.memory.retain(typeBytes); + instance.exports.bjs_Animal_init(typeId, typeBytes.length); + const structValue = structHelpers.Animal.lift(); + return structValue; + }, + }, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index d9df868ec..6fd627dcb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -124,6 +125,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js index abfb24d48..aa523be20 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -30,6 +30,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -311,6 +312,13 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } bjs["swift_js_struct_lower_DataPoint"] = function(objectId) { structHelpers.DataPoint.lower(swift.memory.getObject(objectId)); } @@ -367,6 +375,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.Vector2D.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.d.ts index 3677f1e44..e97b50fda 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.d.ts @@ -12,6 +12,7 @@ export type Exports = { } export type Imports = { translate(point: Point, dx: number, dy: number): Point; + roundTripOptional(point: Point | null): Point | null; } export function createInstantiator(options: { imports: Imports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js index d4f1160f3..44b7c5527 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -110,6 +111,13 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } bjs["swift_js_struct_lower_Point"] = function(objectId) { structHelpers.Point.lower(swift.memory.getObject(objectId)); } @@ -117,6 +125,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.Point.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; @@ -218,6 +233,25 @@ export async function createInstantiator(options, swift) { setException(error); } } + TestModule["bjs_roundTripOptional"] = function bjs_roundTripOptional(point) { + try { + let optResult; + if (point) { + const struct = structHelpers.Point.lift(); + optResult = struct; + } else { + optResult = null; + } + let ret = imports.roundTripOptional(optResult); + const isSome = ret != null; + if (isSome) { + structHelpers.Point.lower(ret); + } + i32Stack.push(isSome ? 1 : 0); + } catch (error) { + setException(error); + } + } }, setInstance: (i) => { instance = i; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.d.ts new file mode 100644 index 000000000..99adf95b6 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.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`. + +export interface JSPublicEvent { +} +export interface JSPackageEvent { +} +export interface JSInternalEvent { +} +export interface JSPublicTarget { + addPublicListener(handler: (arg0: JSPublicEvent) => void): void; + addInternalListener(handler: (arg0: JSPublicEvent) => void): void; +} +export interface JSPackageTarget { + addPackageListener(handler: (arg0: JSPackageEvent) => void): void; +} +export interface JSInternalTarget { + addInternalListener(handler: (arg0: JSInternalEvent) => void): void; +} +export type Exports = { +} +export type Imports = { +} +export function createInstantiator(options: { + imports: Imports; +}, swift: any): Promise<{ + addImports: (importObject: WebAssembly.Imports) => void; + setInstance: (instance: WebAssembly.Instance) => void; + createExports: (instance: WebAssembly.Instance) => Exports; +}>; \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js new file mode 100644 index 000000000..f07b00968 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js @@ -0,0 +1,344 @@ +// 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; + let decodeString; + 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 i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + 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 = decodeString(state.file, 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; + bjs["swift_js_return_string"] = function(ptr, len) { + tmpRetString = decodeString(ptr, len); + } + 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) { + return swift.memory.retain(decodeString(ptr, len)); + } + 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 value = decodeString(ptr, len); + 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_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + 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 { + tmpRetString = decodeString(ptr, len); + } + } + 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_10TestModule13JSPublicEventC_y"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + callback(swift.memory.getObject(param0)); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModule13JSPublicEventC_y"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule13JSPublicEventC_y = function(param0) { + instance.exports.invoke_swift_closure_TestModule_10TestModule13JSPublicEventC_y(boxPtr, swift.memory.retain(param0)); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule13JSPublicEventC_y); + } + bjs["invoke_js_callback_TestModule_10TestModule14JSPackageEventC_y"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + callback(swift.memory.getObject(param0)); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModule14JSPackageEventC_y"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule14JSPackageEventC_y = function(param0) { + instance.exports.invoke_swift_closure_TestModule_10TestModule14JSPackageEventC_y(boxPtr, swift.memory.retain(param0)); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule14JSPackageEventC_y); + } + bjs["invoke_js_callback_TestModule_10TestModule15JSInternalEventC_y"] = function(callbackId, param0) { + try { + const callback = swift.memory.getObject(callbackId); + callback(swift.memory.getObject(param0)); + } catch (error) { + setException(error); + } + } + bjs["make_swift_closure_TestModule_10TestModule15JSInternalEventC_y"] = function(boxPtr, file, line) { + const lower_closure_TestModule_10TestModule15JSInternalEventC_y = function(param0) { + instance.exports.invoke_swift_closure_TestModule_10TestModule15JSInternalEventC_y(boxPtr, swift.memory.retain(param0)); + if (tmpRetException) { + const error = swift.memory.getObject(tmpRetException); + swift.memory.release(tmpRetException); + tmpRetException = undefined; + throw error; + } + }; + return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule15JSInternalEventC_y); + } + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_JSPublicTarget_addPublicListener"] = function bjs_JSPublicTarget_addPublicListener(self, handler) { + try { + swift.memory.getObject(self).addPublicListener(swift.memory.getObject(handler)); + } catch (error) { + setException(error); + } + } + TestModule["bjs_JSPublicTarget_addInternalListener"] = function bjs_JSPublicTarget_addInternalListener(self, handler) { + try { + swift.memory.getObject(self).addInternalListener(swift.memory.getObject(handler)); + } catch (error) { + setException(error); + } + } + TestModule["bjs_JSPackageTarget_addPackageListener"] = function bjs_JSPackageTarget_addPackageListener(self, handler) { + try { + swift.memory.getObject(self).addPackageListener(swift.memory.getObject(handler)); + } catch (error) { + setException(error); + } + } + TestModule["bjs_JSInternalTarget_addInternalListener"] = function bjs_JSInternalTarget_addInternalListener(self, handler) { + try { + swift.memory.getObject(self).addInternalListener(swift.memory.getObject(handler)); + } catch (error) { + setException(error); + } + } + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + 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/Throws.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js index b2c381a03..d1036cba4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -98,6 +99,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js index ef81ef69e..54276025b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -115,6 +116,13 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } bjs["swift_js_struct_lower_PointerFields"] = function(objectId) { structHelpers.PointerFields.lower(swift.memory.getObject(objectId)); } @@ -122,6 +130,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.PointerFields.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js index 97948b286..755165ee1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js @@ -25,6 +25,7 @@ export async function createInstantiator(options, swift) { let f32Stack = []; let f64Stack = []; let ptrStack = []; + let taStack = []; const enumHelpers = {}; const structHelpers = {}; @@ -99,6 +100,20 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_i64"] = function() { return i64Stack.pop(); } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/Plugins/PackageToJS/Sources/BridgeJSPluginUtilities b/Plugins/PackageToJS/Sources/BridgeJSPluginUtilities new file mode 120000 index 000000000..97aa4a1cc --- /dev/null +++ b/Plugins/PackageToJS/Sources/BridgeJSPluginUtilities @@ -0,0 +1 @@ +../../BridgeJS/Sources/BridgeJSPluginUtilities \ No newline at end of file diff --git a/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift b/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift index 7e335c68e..7686372f9 100644 --- a/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift +++ b/Plugins/PackageToJS/Sources/PackageToJSPlugin.swift @@ -748,15 +748,15 @@ class SkeletonCollector { } } if let target = target as? SwiftSourceModuleTarget { - let directories = [ - target.directoryURL.appending(path: "Generated/JavaScript"), - // context.pluginWorkDirectoryURL: ".build/plugins/PackageToJS/outputs/" - // .build/plugins/outputs/[package]/[target]/destination/BridgeJS/JavaScript/BridgeJS.json - context.pluginWorkDirectoryURL.deletingLastPathComponent().deletingLastPathComponent() - .appending(path: "outputs/\(package.id)/\(target.name)/destination/BridgeJS/JavaScript"), + let candidates = [ + target.directoryURL.appending(path: "Generated/JavaScript").appending(path: skeletonFile), + BridgeJSPluginPaths.skeletonURL( + targetName: target.name, + packageID: package.id, + commandPluginWorkDirectoryURL: context.pluginWorkDirectoryURL + ), ] - for directory in directories { - let skeletonURL = directory.appending(path: skeletonFile) + for skeletonURL in candidates { if FileManager.default.fileExists(atPath: skeletonURL.path) { skeletons.append(skeletonURL) } diff --git a/Plugins/PackageToJS/Templates/instantiate.js b/Plugins/PackageToJS/Templates/instantiate.js index 3dda6b28e..36d840099 100644 --- a/Plugins/PackageToJS/Templates/instantiate.js +++ b/Plugins/PackageToJS/Templates/instantiate.js @@ -68,6 +68,8 @@ async function createInstantiator(options, swift) { swift_js_push_i64: unexpectedBjsCall, swift_js_pop_i64: unexpectedBjsCall, swift_js_closure_unregister: unexpectedBjsCall, + swift_js_push_typed_array: unexpectedBjsCall, + swift_js_make_promise: unexpectedBjsCall, }; }, /** @param {WebAssembly.Instance} instance */ diff --git a/Plugins/PackageToJS/Templates/runtime.d.ts b/Plugins/PackageToJS/Templates/runtime.d.ts index 87cbeea72..e4795bedf 100644 --- a/Plugins/PackageToJS/Templates/runtime.d.ts +++ b/Plugins/PackageToJS/Templates/runtime.d.ts @@ -2,14 +2,16 @@ type ref = number; type pointer = number; declare class JSObjectSpace { - private _heapValueById; - private _heapEntryByValue; - private _heapNextKey; + private _slotByValue; + private _values; + private _stateBySlot; + private _freeSlotStack; constructor(); retain(value: any): number; - retainByRef(ref: ref): number; - release(ref: ref): void; - getObject(ref: ref): any; + retainByRef(reference: ref): number; + release(reference: ref): void; + getObject(reference: ref): any; + private _getValidatedSlotState; } /** diff --git a/Plugins/PackageToJS/Templates/runtime.mjs b/Plugins/PackageToJS/Templates/runtime.mjs index ab85e7893..daf4f3ab0 100644 --- a/Plugins/PackageToJS/Templates/runtime.mjs +++ b/Plugins/PackageToJS/Templates/runtime.mjs @@ -241,44 +241,91 @@ function deserializeError(error) { const globalVariable = globalThis; +const SLOT_BITS = 24; +const SLOT_MASK = (1 << SLOT_BITS) - 1; +const GEN_MASK = (1 << (32 - SLOT_BITS)) - 1; class JSObjectSpace { constructor() { - this._heapValueById = new Map(); - this._heapValueById.set(1, globalVariable); - this._heapEntryByValue = new Map(); - this._heapEntryByValue.set(globalVariable, { id: 1, rc: 1 }); + this._slotByValue = new Map(); + this._values = []; + this._stateBySlot = []; + this._freeSlotStack = []; // Note: 0 is preserved for invalid references, 1 is preserved for globalThis - this._heapNextKey = 2; + this._values[0] = undefined; + this._values[1] = globalVariable; + this._slotByValue.set(globalVariable, 1); + this._stateBySlot[1] = 1; // gen=0, rc=1 } retain(value) { - const entry = this._heapEntryByValue.get(value); - if (entry) { - entry.rc++; - return entry.id; - } - const id = this._heapNextKey++; - this._heapValueById.set(id, value); - this._heapEntryByValue.set(value, { id: id, rc: 1 }); - return id; - } - retainByRef(ref) { - return this.retain(this.getObject(ref)); - } - release(ref) { - const value = this._heapValueById.get(ref); - const entry = this._heapEntryByValue.get(value); - entry.rc--; - if (entry.rc != 0) + const slot = this._slotByValue.get(value); + if (slot !== undefined) { + const state = this._stateBySlot[slot]; + const nextState = (state + 1) >>> 0; + if ((nextState & SLOT_MASK) === 0) { + throw new RangeError(`Reference count overflow at slot ${slot}`); + } + this._stateBySlot[slot] = nextState; + return ((nextState & ~SLOT_MASK) | slot) >>> 0; + } + let newSlot; + let state; + if (this._freeSlotStack.length > 0) { + newSlot = this._freeSlotStack.pop(); + const gen = this._stateBySlot[newSlot] >>> SLOT_BITS; + state = ((gen << SLOT_BITS) | 1) >>> 0; + } + else { + newSlot = this._values.length; + if (newSlot > SLOT_MASK) { + throw new RangeError(`Reference slot overflow: ${newSlot} exceeds ${SLOT_MASK}`); + } + state = 1; + } + this._stateBySlot[newSlot] = state; + this._values[newSlot] = value; + this._slotByValue.set(value, newSlot); + return ((state & ~SLOT_MASK) | newSlot) >>> 0; + } + retainByRef(reference) { + const state = this._getValidatedSlotState(reference); + const slot = reference & SLOT_MASK; + const nextState = (state + 1) >>> 0; + if ((nextState & SLOT_MASK) === 0) { + throw new RangeError(`Reference count overflow at slot ${slot}`); + } + this._stateBySlot[slot] = nextState; + return reference; + } + release(reference) { + const state = this._getValidatedSlotState(reference); + const slot = reference & SLOT_MASK; + if ((state & SLOT_MASK) > 1) { + this._stateBySlot[slot] = (state - 1) >>> 0; return; - this._heapEntryByValue.delete(value); - this._heapValueById.delete(ref); - } - getObject(ref) { - const value = this._heapValueById.get(ref); - if (value === undefined) { - throw new ReferenceError("Attempted to read invalid reference " + ref); } - return value; + this._slotByValue.delete(this._values[slot]); + this._values[slot] = undefined; + const nextGen = ((state >>> SLOT_BITS) + 1) & GEN_MASK; + this._stateBySlot[slot] = (nextGen << SLOT_BITS) >>> 0; + this._freeSlotStack.push(slot); + } + getObject(reference) { + this._getValidatedSlotState(reference); + return this._values[reference & SLOT_MASK]; + } + // Returns the packed state for the slot, after validating the reference. + _getValidatedSlotState(reference) { + const slot = reference & SLOT_MASK; + if (slot === 0) + throw new ReferenceError(`Attempted to use invalid reference ${reference}`); + const state = this._stateBySlot[slot]; + if (state === undefined || (state & SLOT_MASK) === 0) { + throw new ReferenceError(`Attempted to use invalid reference ${reference}`); + } + if (state >>> SLOT_BITS !== reference >>> SLOT_BITS) { + throw new ReferenceError(`Attempted to use stale reference ${reference}`); + } + return state; } } diff --git a/Plugins/PackageToJS/Tests/ExampleTests.swift b/Plugins/PackageToJS/Tests/ExampleTests.swift index d26832771..d131b329a 100644 --- a/Plugins/PackageToJS/Tests/ExampleTests.swift +++ b/Plugins/PackageToJS/Tests/ExampleTests.swift @@ -246,11 +246,26 @@ extension Trait where Self == ConditionTrait { func basic() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) try withPackage(at: "Examples/Basic") { packageDir, _, runSwift in - try runSwift(["package", "--swift-sdk", swiftSDKID, "js"], [:]) - try runSwift(["package", "--swift-sdk", swiftSDKID, "js", "--debug-info-format", "dwarf"], [:]) - try runSwift(["package", "--swift-sdk", swiftSDKID, "js", "--debug-info-format", "name"], [:]) + try runSwift(["package", "--build-system", "native", "--swift-sdk", swiftSDKID, "js"], [:]) try runSwift( - ["package", "--swift-sdk", swiftSDKID, "-Xswiftc", "-DJAVASCRIPTKIT_WITHOUT_WEAKREFS", "js"], + [ + "package", "--build-system", "native", "--swift-sdk", swiftSDKID, "js", "--debug-info-format", + "dwarf", + ], + [:] + ) + try runSwift( + [ + "package", "--build-system", "native", "--swift-sdk", swiftSDKID, "js", "--debug-info-format", + "name", + ], + [:] + ) + try runSwift( + [ + "package", "--build-system", "native", "--swift-sdk", swiftSDKID, "-Xswiftc", + "-DJAVASCRIPTKIT_WITHOUT_WEAKREFS", "js", + ], [:] ) } @@ -266,7 +281,10 @@ extension Trait where Self == ConditionTrait { try runProcess(which("npm"), ["install"], [:]) try runProcess(which("npx"), ["playwright", "install", "chromium-headless-shell"], [:]) - try runSwift(["package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test"], [:]) + try runSwift( + ["package", "--build-system", "native", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test"], + [:] + ) try withTemporaryDirectory(body: { tempDir, _ in let scriptContent = """ const fs = require('fs'); @@ -278,7 +296,8 @@ extension Trait where Self == ConditionTrait { let scriptPath = tempDir.appending(path: "script.js") try runSwift( [ - "package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", + "package", "--build-system", "native", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", + "test", "-Xnode=--require=\(scriptPath.path)", ], [:] @@ -291,20 +310,25 @@ extension Trait where Self == ConditionTrait { ) }) try runSwift( - ["package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", "--environment", "browser"], + [ + "package", "--build-system", "native", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", + "--environment", "browser", + ], [:] ) } } - #if compiler(>=6.1) @Test(.requireSwiftSDK) func testingWithCoverage() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) let swiftPath = try #require(Self.getSwiftPath()) try withPackage(at: "Examples/Testing") { packageDir, runProcess, runSwift in try runSwift( - ["package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", "--enable-code-coverage"], + [ + "package", "--build-system", "native", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", + "--enable-code-coverage", + ], [ "LLVM_PROFDATA_PATH": URL(fileURLWithPath: swiftPath).appending(path: "llvm-profdata").path ] @@ -325,14 +349,13 @@ extension Trait where Self == ConditionTrait { } } } - #endif #endif // compiler(>=6.3) @Test(.requireSwiftSDK(triple: "wasm32-unknown-wasip1-threads")) func multithreading() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) try withPackage(at: "Examples/Multithreading") { packageDir, _, runSwift in - try runSwift(["package", "--swift-sdk", swiftSDKID, "js"], [:]) + try runSwift(["package", "--build-system", "native", "--swift-sdk", swiftSDKID, "js"], [:]) } } @@ -340,7 +363,7 @@ extension Trait where Self == ConditionTrait { func offscreenCanvas() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) try withPackage(at: "Examples/OffscrenCanvas") { packageDir, _, runSwift in - try runSwift(["package", "--swift-sdk", swiftSDKID, "js"], [:]) + try runSwift(["package", "--build-system", "native", "--swift-sdk", swiftSDKID, "js"], [:]) } } @@ -348,7 +371,7 @@ extension Trait where Self == ConditionTrait { func actorOnWebWorker() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) try withPackage(at: "Examples/ActorOnWebWorker") { packageDir, _, runSwift in - try runSwift(["package", "--swift-sdk", swiftSDKID, "js"], [:]) + try runSwift(["package", "--build-system", "native", "--swift-sdk", swiftSDKID, "js"], [:]) } } @@ -359,7 +382,7 @@ extension Trait where Self == ConditionTrait { let swiftSDKID = try #require(Self.getEmbeddedSwiftSDKID()) try withPackage(at: "Examples/Embedded") { packageDir, _, runSwift in try runSwift( - ["package", "--swift-sdk", swiftSDKID, "js", "-c", "release"], + ["package", "--build-system", "native", "--swift-sdk", swiftSDKID, "js", "-c", "release"], [ "JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM": "true" ] @@ -375,11 +398,13 @@ extension Trait where Self == ConditionTrait { at: "Plugins/PackageToJS/Fixtures/ContinuationLeakInTest/XCTest", assertTerminationStatus: { $0 != 0 } ) { packageDir, _, runSwift in - try runSwift(["package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test"], [:]) + try runSwift( + ["package", "--build-system", "native", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test"], + [:] + ) } } - #if compiler(>=6.1) // TODO: Remove triple restriction once swift-testing is shipped in p1-threads SDK @Test(.requireSwiftSDK(triple: "wasm32-unknown-wasi")) func continuationLeakInTest_SwiftTesting() throws { @@ -388,11 +413,12 @@ extension Trait where Self == ConditionTrait { at: "Plugins/PackageToJS/Fixtures/ContinuationLeakInTest/SwiftTesting", assertTerminationStatus: { $0 != 0 } ) { packageDir, _, runSwift in - try runSwift(["package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test"], [:]) + try runSwift( + ["package", "--build-system", "native", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test"], + [:] + ) } } - #endif - @Test(.requireSwiftSDK) func playwrightOnPageLoad_XCTest() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) @@ -405,7 +431,7 @@ extension Trait where Self == ConditionTrait { try runSwift( ["package", "--disable-sandbox"] + Self.stackSizeLinkerFlags + [ - "--swift-sdk", swiftSDKID, "js", "test", "--environment", "browser", + "--build-system", "native", "--swift-sdk", swiftSDKID, "js", "test", "--environment", "browser", "--playwright-expose", "../expose.js", ], [:] @@ -413,7 +439,6 @@ extension Trait where Self == ConditionTrait { } } - #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 { @@ -427,12 +452,12 @@ extension Trait where Self == ConditionTrait { try runSwift( [ - "package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", "--environment", "browser", + "package", "--build-system", "native", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", + "--environment", "browser", "--playwright-expose", "../expose.js", ], [:] ) } } - #endif } diff --git a/README.md b/README.md index 03129c3e2..88c1332a2 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,10 @@ Use the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/) Check out the [examples](https://github.com/swiftwasm/JavaScriptKit/tree/main/Examples) for more detailed usage patterns. +## Minimum Supported Swift Version (MSSV) + +The minimum supported Swift version is 6.3. + ## Contributing Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to the project. diff --git a/Runtime/src/object-heap.ts b/Runtime/src/object-heap.ts index ba9cf8021..6138953e9 100644 --- a/Runtime/src/object-heap.ts +++ b/Runtime/src/object-heap.ts @@ -1,59 +1,114 @@ import { globalVariable } from "./find-global.js"; import { ref } from "./types.js"; -type SwiftRuntimeHeapEntry = { - id: number; - rc: number; -}; +const SLOT_BITS = 24; +const SLOT_MASK = (1 << SLOT_BITS) - 1; +const GEN_MASK = (1 << (32 - SLOT_BITS)) - 1; + export class JSObjectSpace { - private _heapValueById: Map; - private _heapEntryByValue: Map; - private _heapNextKey: number; + private _slotByValue: Map; + private _values: (any | undefined)[]; + private _stateBySlot: number[]; + private _freeSlotStack: number[]; constructor() { - this._heapValueById = new Map(); - this._heapValueById.set(1, globalVariable); - - this._heapEntryByValue = new Map(); - this._heapEntryByValue.set(globalVariable, { id: 1, rc: 1 }); + this._slotByValue = new Map(); + this._values = []; + this._stateBySlot = []; + this._freeSlotStack = []; // Note: 0 is preserved for invalid references, 1 is preserved for globalThis - this._heapNextKey = 2; + this._values[0] = undefined; + this._values[1] = globalVariable; + this._slotByValue.set(globalVariable, 1); + this._stateBySlot[1] = 1; // gen=0, rc=1 } retain(value: any) { - const entry = this._heapEntryByValue.get(value); - if (entry) { - entry.rc++; - return entry.id; + const slot = this._slotByValue.get(value); + if (slot !== undefined) { + const state = this._stateBySlot[slot]!; + const nextState = (state + 1) >>> 0; + if ((nextState & SLOT_MASK) === 0) { + throw new RangeError( + `Reference count overflow at slot ${slot}`, + ); + } + this._stateBySlot[slot] = nextState; + return ((nextState & ~SLOT_MASK) | slot) >>> 0; + } + + let newSlot: number; + let state: number; + if (this._freeSlotStack.length > 0) { + newSlot = this._freeSlotStack.pop()!; + const gen = this._stateBySlot[newSlot]! >>> SLOT_BITS; + state = ((gen << SLOT_BITS) | 1) >>> 0; + } else { + newSlot = this._values.length; + if (newSlot > SLOT_MASK) { + throw new RangeError( + `Reference slot overflow: ${newSlot} exceeds ${SLOT_MASK}`, + ); + } + state = 1; } - const id = this._heapNextKey++; - this._heapValueById.set(id, value); - this._heapEntryByValue.set(value, { id: id, rc: 1 }); - return id; + + this._stateBySlot[newSlot] = state; + this._values[newSlot] = value; + this._slotByValue.set(value, newSlot); + return ((state & ~SLOT_MASK) | newSlot) >>> 0; } - retainByRef(ref: ref) { - return this.retain(this.getObject(ref)); + retainByRef(reference: ref) { + const state = this._getValidatedSlotState(reference); + const slot = reference & SLOT_MASK; + const nextState = (state + 1) >>> 0; + if ((nextState & SLOT_MASK) === 0) { + throw new RangeError(`Reference count overflow at slot ${slot}`); + } + this._stateBySlot[slot] = nextState; + return reference; } - release(ref: ref) { - const value = this._heapValueById.get(ref); - const entry = this._heapEntryByValue.get(value)!; - entry.rc--; - if (entry.rc != 0) return; + release(reference: ref) { + const state = this._getValidatedSlotState(reference); + const slot = reference & SLOT_MASK; + if ((state & SLOT_MASK) > 1) { + this._stateBySlot[slot] = (state - 1) >>> 0; + return; + } + + this._slotByValue.delete(this._values[slot]); + this._values[slot] = undefined; + const nextGen = ((state >>> SLOT_BITS) + 1) & GEN_MASK; + this._stateBySlot[slot] = (nextGen << SLOT_BITS) >>> 0; + this._freeSlotStack.push(slot); + } - this._heapEntryByValue.delete(value); - this._heapValueById.delete(ref); + getObject(reference: ref) { + this._getValidatedSlotState(reference); + return this._values[reference & SLOT_MASK]; } - getObject(ref: ref) { - const value = this._heapValueById.get(ref); - if (value === undefined) { + // Returns the packed state for the slot, after validating the reference. + private _getValidatedSlotState(reference: ref): number { + const slot = reference & SLOT_MASK; + if (slot === 0) + throw new ReferenceError( + `Attempted to use invalid reference ${reference}`, + ); + const state = this._stateBySlot[slot]; + if (state === undefined || (state & SLOT_MASK) === 0) { + throw new ReferenceError( + `Attempted to use invalid reference ${reference}`, + ); + } + if (state >>> SLOT_BITS !== reference >>> SLOT_BITS) { throw new ReferenceError( - "Attempted to read invalid reference " + ref, + `Attempted to use stale reference ${reference}`, ); } - return value; + return state; } } diff --git a/Sources/JavaScriptEventLoop/JSRemote.swift b/Sources/JavaScriptEventLoop/JSRemote.swift index 4f488d7b8..b85b4991c 100644 --- a/Sources/JavaScriptEventLoop/JSRemote.swift +++ b/Sources/JavaScriptEventLoop/JSRemote.swift @@ -62,7 +62,7 @@ extension JSRemote where T == JSObject { /// /// - Parameter object: The JavaScript object to reference remotely. public init(_ object: JSObject) { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) self.init(sourceObject: object, sourceTid: object.ownerTid) #else self.init(sourceObject: object, sourceTid: -1) @@ -92,7 +92,7 @@ extension JSRemote where T == JSObject { public func withJSObject( _ body: @Sendable @escaping (JSObject) throws(E) -> R ) async throws(E) -> sending R { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) if storage.sourceTid == swjs_get_worker_thread_id_cached() { return try body(storage.sourceObject) } @@ -137,13 +137,11 @@ private final class _JSRemoteContext: @unchecked Sendable { } } -#if compiler(>=6.1) @_expose(wasm, "swjs_invoke_remote_jsobject_body") @_cdecl("swjs_invoke_remote_jsobject_body") -#endif @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) func _swjs_invoke_remote_jsobject_body(_ contextPtr: UnsafeRawPointer?) -> Bool { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) guard let contextPtr else { return true } let context = Unmanaged<_JSRemoteContext>.fromOpaque(contextPtr).takeRetainedValue() diff --git a/Sources/JavaScriptEventLoop/JSSending.swift b/Sources/JavaScriptEventLoop/JSSending.swift index fb2fb1ddf..613abdd8a 100644 --- a/Sources/JavaScriptEventLoop/JSSending.swift +++ b/Sources/JavaScriptEventLoop/JSSending.swift @@ -105,7 +105,7 @@ extension JSSending where T == JSObject { construct: { $0 }, deconstruct: { $0 }, getSourceTid: { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) return $0.ownerTid #else _ = $0 @@ -258,7 +258,7 @@ extension JSSending { file: StaticString = #file, line: UInt = #line ) async throws -> T { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) let idInDestination = try await withCheckedThrowingContinuation { continuation in let context = _JSSendingContext(continuation: continuation) let idInSource = self.storage.idInSource @@ -278,8 +278,6 @@ extension JSSending { } #endif - // 6.0 and below can't compile the following without a compiler crash. - #if compiler(>=6.1) /// Receives multiple `JSSending` instances from a thread in a single operation. /// /// This method is more efficient than receiving multiple objects individually, as it @@ -317,7 +315,7 @@ extension JSSending { file: StaticString = #file, line: UInt = #line ) async throws -> (repeat each U) where T == (repeat each U) { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) var sendingObjects: [JavaScriptObjectRef] = [] var transferringObjects: [JavaScriptObjectRef] = [] var sourceTid: Int32? @@ -363,7 +361,6 @@ extension JSSending { return try await (repeat (each sendings).receive()) #endif } - #endif // compiler(>=6.1) } @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) @@ -404,13 +401,11 @@ public struct JSSendingError: Error, CustomStringConvertible { /// - object: The `JSObject` to be received. /// - contextPtr: A pointer to the `_JSSendingContext` instance. // swift-format-ignore -#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+ @_expose(wasm, "swjs_receive_response") @_cdecl("swjs_receive_response") -#endif @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) func _swjs_receive_response(_ object: JavaScriptObjectRef, _ contextPtr: UnsafeRawPointer?) { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) guard let contextPtr = contextPtr else { return } let context = Unmanaged<_JSSendingContext>.fromOpaque(contextPtr).takeRetainedValue() context.continuation.resume(returning: object) @@ -424,13 +419,11 @@ func _swjs_receive_response(_ object: JavaScriptObjectRef, _ contextPtr: UnsafeR /// - error: The error to be received. /// - contextPtr: A pointer to the `_JSSendingContext` instance. // swift-format-ignore -#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+ @_expose(wasm, "swjs_receive_error") @_cdecl("swjs_receive_error") -#endif @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) func _swjs_receive_error(_ error: JavaScriptObjectRef, _ contextPtr: UnsafeRawPointer?) { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) guard let contextPtr = contextPtr else { return } let context = Unmanaged<_JSSendingContext>.fromOpaque(contextPtr).takeRetainedValue() context.continuation.resume(throwing: JSException(JSObject(id: error).jsValue)) diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift index 0d2010016..17aedca3b 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop+ExecutorFactory.swift @@ -57,25 +57,12 @@ extension JavaScriptEventLoop: SchedulingExecutor { #endif // #if compiler(>=6.4) (Embedded) #else // #if hasFeature(Embedded) 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 { - #if compiler(>=6.4) - // Hand-off the scheduling work to Clock implementation for unknown clocks. - // Clock.enqueue is only available in the development branch (6.4+). - clock.enqueue( - job, - on: self, - at: clock.now.advanced(by: delay), - tolerance: tolerance - ) - return - #else fatalError("Unsupported clock type; only ContinuousClock and SuspendingClock are supported") - #endif // #if compiler(>=6.4) (non-Embedded) } let milliseconds = Self.delayInMilliseconds(from: duration) self.enqueue( diff --git a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift index 5fc267ddc..ead6157bf 100644 --- a/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift +++ b/Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift @@ -65,7 +65,7 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable { return _shared } - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) // In multi-threaded environment, we have an event loop executor per // thread (per Web Worker). A job enqueued in one thread should be // executed in the same thread under this global executor. @@ -129,7 +129,7 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable { _Concurrency._createExecutors(factory: JavaScriptEventLoop.self) } #else - // For Swift 6.1 and below, or Embedded Swift, we need to install + // For Embedded Swift, we need to install // the global executor by hook API. The ExecutorFactory mechanism // does not work in Embedded Swift because ExecutorImpl.swift is // excluded from the embedded Concurrency library. @@ -151,7 +151,7 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable { } internal func unsafeEnqueue(_ job: UnownedJob) { - #if canImport(wasi_pthread) && compiler(>=6.1) && _runtime(_multithreaded) + #if canImport(wasi_pthread) && _runtime(_multithreaded) guard swjs_get_worker_thread_id_cached() == SWJS_MAIN_THREAD_ID else { // Notify the main thread to execute the job when a job is // enqueued from a Web Worker thread but without an executor preference. diff --git a/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift b/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift index b827ad980..b6bfb9c5f 100644 --- a/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift +++ b/Sources/JavaScriptEventLoop/WebWorkerTaskExecutor.swift @@ -385,7 +385,7 @@ public final class WebWorkerTaskExecutor: TaskExecutor { } func start(timeout: Duration, checkInterval: Duration) async throws { - #if canImport(wasi_pthread) && compiler(>=6.1) && _runtime(_multithreaded) + #if canImport(wasi_pthread) && _runtime(_multithreaded) class Context: @unchecked Sendable { let executor: WebWorkerTaskExecutor.Executor let worker: Worker @@ -610,9 +610,7 @@ public final class WebWorkerTaskExecutor: TaskExecutor { /// Enqueue a job scheduled from a Web Worker thread to the main thread. /// This function is called when a job is enqueued from a Web Worker thread. @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+ @_expose(wasm, "swjs_enqueue_main_job_from_worker") -#endif func _swjs_enqueue_main_job_from_worker(_ job: UnownedJob) { WebWorkerTaskExecutor.traceStatsIncrement(\.receiveJobFromWorkerThread) JavaScriptEventLoop.shared.enqueue(ExecutorJob(job)) @@ -621,9 +619,7 @@ func _swjs_enqueue_main_job_from_worker(_ job: UnownedJob) { /// Wake up the worker thread. /// This function is called when a job is enqueued from the main thread to a worker thread. @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -#if compiler(>=6.1) // @_expose and @_extern are only available in Swift 6.1+ @_expose(wasm, "swjs_wake_worker_thread") -#endif func _swjs_wake_worker_thread() { WebWorkerTaskExecutor.Worker.currentThread!.wakeUpFromOtherThread() } diff --git a/Sources/JavaScriptFoundationCompat/Data+JSValue.swift b/Sources/JavaScriptFoundationCompat/Data+JSValue.swift index 6e74ba266..c4408d8cf 100644 --- a/Sources/JavaScriptFoundationCompat/Data+JSValue.swift +++ b/Sources/JavaScriptFoundationCompat/Data+JSValue.swift @@ -22,7 +22,7 @@ extension Data: ConvertibleToJSValue, ConstructibleFromJSValue { public var jsValue: JSValue { jsTypedArray.jsValue } /// Construct a Data from a JSTypedArray. - public static func construct(from uint8Array: JSTypedArray) -> Data? { + public static func construct(from uint8Array: JSTypedArray) -> Data { // First, allocate the data storage var data = Data(count: uint8Array.lengthInBytes) // Then, copy the byte contents into the Data buffer diff --git a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift index 0ad7b235a..4717b6705 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift @@ -204,3 +204,12 @@ public enum JSUInt8Clamped: TypedArrayElement { } public typealias JSUInt8ClampedArray = JSTypedArray + +public typealias JSInt8Array = JSTypedArray +public typealias JSUint8Array = JSTypedArray +public typealias JSInt16Array = JSTypedArray +public typealias JSUint16Array = JSTypedArray +public typealias JSInt32Array = JSTypedArray +public typealias JSUint32Array = JSTypedArray +public typealias JSFloat32Array = JSTypedArray +public typealias JSFloat64Array = JSTypedArray diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 867d0e835..bbf8c8f2e 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -154,6 +154,11 @@ public protocol _BridgedSwiftStackType { static func bridgeJSStackPopAsOptional() -> StackLiftResult? /// Specialization point for pushing an `Optional` static func bridgeJSStackPushAsOptional(_ value: consuming Self?) + + /// Specialization point for popping an `Array` from the bridge stack + static func bridgeJSStackPopAsArray() -> [StackLiftResult] + /// Specialization point for pushing an `Array` onto the bridge stack + static func bridgeJSStackPushAsArray(_ value: consuming [Self]) } extension _BridgedSwiftStackType { @@ -178,17 +183,36 @@ extension _BridgedSwiftStackType { _swift_js_push_i32(1) } } + + public static func bridgeJSStackPopAsArray() -> [StackLiftResult] { + let count = Int(_swift_js_pop_i32()) + var result: [StackLiftResult] = [] + result.reserveCapacity(count) + for _ in 0... -@_spi(BridgeJS) public protocol _BridgedAsOptional { +public protocol _BridgedAsOptional { associatedtype Wrapped var asOptional: Wrapped? { get } init(optional: Wrapped?) } -@_spi(BridgeJS) extension Optional: _BridgedAsOptional { +extension Optional: _BridgedAsOptional { public var asOptional: Wrapped? { self } public init(optional: Wrapped?) { self = optional } } @@ -847,6 +871,10 @@ extension _BridgedSwiftStruct { return Self(unsafelyCopying: jsObject) } + @_spi(BridgeJS) public static func bridgeJSLiftReturn() -> Self { + bridgeJSStackPop() + } + @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self { bridgeJSStackPop() } @@ -1004,6 +1032,107 @@ private func _swift_js_pop_f64_extern() -> Float64 { _swift_js_pop_f64_extern() } +// MARK: Typed array bulk push extern + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_typed_array") +private func _swift_js_push_typed_array_extern(_ kind: Int32, _ ptr: UnsafeRawPointer, _ count: Int32) +#else +private func _swift_js_push_typed_array_extern(_ kind: Int32, _ ptr: UnsafeRawPointer, _ count: Int32) { + _onlyAvailableOnWasm() +} +#endif + +/// Pushes a typed array onto the JS typed-array stack via bulk copy. +@_spi(BridgeJS) @inline(never) public func _swift_js_push_typed_array( + _ kind: Int32, + _ ptr: UnsafeRawPointer, + _ count: Int32 +) { + _swift_js_push_typed_array_extern(kind, ptr, count) +} + +/// Numeric TypedArray kind identifiers (must match the JS `taCtors` table in BridgeJSLink). +public enum _BridgedNumericArrayKind: Int32 { + case int8 = 0 + case uint8 = 1 + case int16 = 2 + case uint16 = 3 + case int32 = 4 + case uint32 = 5 + case float32 = 6 + case float64 = 7 +} + +// MARK: - Numeric typed-array bulk push + +/// Numeric types that opt into bulk typed-array push. +public protocol _BridgedNumericArray: _BridgedSwiftStackType where StackLiftResult == Self { + static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { get } +} + +extension _BridgedNumericArray { + @_spi(BridgeJS) + public static func bridgeJSStackPushAsArray(_ value: consuming [Self]) { + value.withUnsafeBufferPointer { buffer in + guard let base = buffer.baseAddress else { + _swift_js_push_i32(0) + return + } + _swift_js_push_typed_array( + Self._bridgedNumericArrayKind.rawValue, + UnsafeRawPointer(base), + Int32(buffer.count) + ) + // -1 discriminator tells JS arrayLift to pop from the typed-array stack + _swift_js_push_i32(-1) + } + } +} + +extension Int8: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { .int8 } +} +extension UInt8: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { .uint8 } +} +extension Int16: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { .int16 } +} +extension UInt16: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { .uint16 } +} +extension Int32: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { .int32 } +} +extension UInt32: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { .uint32 } +} +extension Float: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { .float32 } +} +extension Double: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { .float64 } +} +extension Int: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { + #if _pointerBitWidth(_32) + return .int32 + #else + return .int32 + #endif + } +} +extension UInt: _BridgedNumericArray { + public static var _bridgedNumericArrayKind: _BridgedNumericArrayKind { + #if _pointerBitWidth(_32) + return .uint32 + #else + return .uint32 + #endif + } +} + // MARK: Wasm externs used by type lowering/lifting #if arch(wasm32) @@ -1693,12 +1822,31 @@ extension _BridgedAsOptional where Wrapped == JSObject { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - asOptional._bridgeJSLowerReturn( - noneValue: 0, - lowerWrapped: { $0.bridgeJSLowerReturn() }, - write: _swift_js_return_optional_object + Wrapped.bridgeJSStackPushAsOptional(asOptional) + } +} + +extension _BridgedAsOptional where Wrapped: _JSBridgedClass { + // `@JSClass` wrappers (`_JSBridgedClass`) bridge an underlying `JSObject`, so an + // optional wrapper mirrors `Optional`: parameters use the direct + // (`isSome`, object id) ABI while returns travel through the bridge stack. + // + // Stack push/pop is provided by the generic `Wrapped: _BridgedSwiftStackType` + // extension; only the direct parameter lift and the export return lowering need + // dedicated implementations here. + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> Self { + Self( + optional: Optional._bridgeJSLiftParameter( + isSome, + objectId, + liftWrapped: Wrapped.bridgeJSLiftParameter + ) ) } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + Wrapped.bridgeJSStackPushAsOptional(asOptional) + } } extension _BridgedAsOptional where Wrapped: _BridgedSwiftProtocolWrapper { @@ -1973,22 +2121,11 @@ extension Array: _BridgedSwiftStackType where Element: _BridgedSwiftStackType, E 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] { @@ -2172,3 +2309,67 @@ extension _BridgedAsOptional { throw error } } + +// MARK: Async Promise Creation + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_make_promise") +private func _swift_js_make_promise_extern() -> Int32 +#else +private func _swift_js_make_promise_extern() -> Int32 { _onlyAvailableOnWasm() } +#endif + +// `@unchecked Sendable` is safe because the Wasm runtime is single-threaded. +private struct _BridgeJSMakePromiseContext: @unchecked Sendable { + let promise: JSObject + let resolve: (JSObject, T) throws(JSException) -> Void + let reject: (JSObject, JSValue) throws(JSException) -> Void + let body: () async throws(JSException) -> T +} + +/// Returns a `Promise` synchronously and settles it from a `Task` via the generated +/// `resolve` / `reject` thunks, which this library cannot name directly. +@_spi(BridgeJS) public func _bjs_makePromise( + resolve: @escaping (JSObject, T) throws(JSException) -> Void, + reject: @escaping (JSObject, JSValue) throws(JSException) -> Void, + _ body: @escaping () async throws(JSException) -> T +) -> Int32 { + let promise = JSObject(id: JavaScriptObjectRef(bitPattern: _swift_js_make_promise_extern())) + let context = _BridgeJSMakePromiseContext(promise: promise, resolve: resolve, reject: reject, body: body) + Task { + do throws(JSException) { + let value = try await context.body() + try context.resolve(context.promise, value) + } catch { + try? context.reject(context.promise, error.thrownValue) + } + } + return promise.bridgeJSLowerReturn() +} + +private struct _BridgeJSMakeVoidPromiseContext: @unchecked Sendable { + let promise: JSObject + let resolve: (JSObject) throws(JSException) -> Void + let reject: (JSObject, JSValue) throws(JSException) -> Void + let body: () async throws(JSException) -> Void +} + +/// `Void`-returning overload: a `Void` value can't cross the bridge as a parameter, so the +/// generated `resolve` thunk takes only the promise and settles it with `undefined`. +@_spi(BridgeJS) public func _bjs_makePromise( + resolve: @escaping (JSObject) throws(JSException) -> Void, + reject: @escaping (JSObject, JSValue) throws(JSException) -> Void, + _ body: @escaping () async throws(JSException) -> Void +) -> Int32 { + let promise = JSObject(id: JavaScriptObjectRef(bitPattern: _swift_js_make_promise_extern())) + let context = _BridgeJSMakeVoidPromiseContext(promise: promise, resolve: resolve, reject: reject, body: body) + Task { + do throws(JSException) { + try await context.body() + try context.resolve(context.promise) + } catch { + try? context.reject(context.promise, error.thrownValue) + } + } + return promise.bridgeJSLowerReturn() +} diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md index 0bd69aa5b..b8856ac30 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/BridgeJS-Configuration.md @@ -12,6 +12,8 @@ The configuration system supports two complementary files: - `bridge-js.config.json` - Base configuration (checked into version control) - `bridge-js.config.local.json` - Local overrides (intended to be ignored by git, for developer-specific settings) +> Note: The presence of a configuration file, even if empty, is required to expose `@JS` types to other modules in the package. See `Examples/MultiModule/` for an example. + ## Configuration Loading ### File Locations diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md index e97bceefa..1100358ba 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Array.md @@ -95,6 +95,42 @@ TypeScript definitions: - `[Int]?` becomes `number[] | null` - `[[Int]]` becomes `number[][]` +## Using TypedArrays + +When you need the JavaScript API to use native TypedArray types (e.g., `Uint8Array` for `fetch` body, `Float32Array` for WebGPU), use ``JSTypedArray`` instead of a plain Swift array: + +```swift +import JavaScriptKit + +@JS func processData(_ data: JSTypedArray) -> JSTypedArray { + return data +} + +// Convenience typealiases also work: +@JS func processFloats(_ data: JSFloat32Array) -> JSFloat32Array { + return data +} +``` + +Generated TypeScript: + +```typescript +export type Exports = { + processData(data: Uint8Array): Uint8Array; + processFloats(data: Float32Array): Float32Array; +} +``` + +Unlike plain arrays which use copy semantics, `JSTypedArray` uses **reference semantics** — it wraps a JavaScript TypedArray object and passes it by reference (no data copying). This is ideal for large binary data or when interacting with JavaScript APIs that expect TypedArrays. + +| Swift | TypeScript | +|:------|:-----------| +| `JSTypedArray` / `JSUint8Array` | `Uint8Array` | +| `JSTypedArray` / `JSInt8Array` | `Int8Array` | +| `JSTypedArray` / `JSInt32Array` | `Int32Array` | +| `JSTypedArray` / `JSFloat32Array` | `Float32Array` | +| `JSTypedArray` / `JSFloat64Array` | `Float64Array` | + ## How It Works Arrays use **copy semantics** when crossing the Swift/JavaScript boundary: diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md index 99a3d5b1c..5b9616105 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Setting-up-BridgeJS.md @@ -58,3 +58,7 @@ For package layout and how to consume the output from JavaScript, see . + +## Multiple targets in one package + +A single package can have multiple targets that use `@JS`. Apply the BridgeJS plugin to every target that contains `@JS` declarations. To make a target's `@JS` types visible to other targets in the same package, also add a `bridge-js.config.json` file (`{}` is enough) to that target’s source directory. See `Examples/MultiModule/` for an example. diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md index 81a135af3..5c609ab72 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md @@ -16,6 +16,20 @@ Swift types and their JavaScript/TypeScript equivalents at the BridgeJS boundary | ``JSUndefinedOr`` `` | `undefined` or `T` | `T \| undefined` | | ``JSObject`` | object | `object` | | ``JSValue`` | any | `any` | +| ``JSTypedArray`` `` | TypedArray | `Uint8Array`, `Float32Array`, etc. | + +### TypedArray mapping + +When using `JSTypedArray` (or convenience typealiases) in `@JS` signatures, the TypeScript type maps to the corresponding JavaScript TypedArray: + +| Swift | TypeScript | +|:--|:--| +| `JSTypedArray` / `JSUint8Array` | `Uint8Array` | +| `JSTypedArray` / `JSInt32Array` | `Int32Array` | +| `JSTypedArray` / `JSFloat32Array` | `Float32Array` | +| `JSTypedArray` / `JSFloat64Array` | `Float64Array` | + +See for usage details. ## See Also diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md index 7ba25f7ae..83213aca1 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Unsupported-Features.md @@ -8,13 +8,11 @@ BridgeJS generates glue code per Swift target (module). Some patterns that are v ## Type usage crossing module boundary -BridgeJS does **not** support using a type across module boundaries in the following situations. +### Exporting Swift: extending types from another Swift module -### Exporting Swift: types from another Swift module +If you have multiple Swift targets (e.g. a library and an app), you **cannot** extend a type defined in one target with a `@JS` exported API in another target. -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`: +**Unsupported example:** Module `App` extends a type defined in module `Lib`: ```swift // In module Lib @@ -24,5 +22,15 @@ If you have multiple Swift targets (e.g. a library and an app), you **cannot** u } // In module App (depends on Lib) - unsupported -@JS public func transform(_ p: LibPoint) -> LibPoint { ... } +extension LibPoint { + @JS public func transformed() -> LibPoint { ... } +} ``` + +### Exporting Swift: non-`@JS` types from another Swift module + +While using `@JS` types from another Swift module is supported, it is not possible to use non-`@JS` types defined in other modules: this will fail at type lookup. + +### Exporting Swift: types from another Swift package + +Types defined in a separate Swift package cannot yet be referenced from `@JS` declarations in your package. diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift index 1b6facada..7bc799c64 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift @@ -22,7 +22,7 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { @usableFromInline internal var _id: JavaScriptObjectRef - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) package let ownerTid: Int32 #endif @@ -35,7 +35,7 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { @_spi(BridgeJS) public init(id: JavaScriptObjectRef) { self._id = id - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) self.ownerTid = swjs_get_worker_thread_id_cached() #endif } @@ -61,7 +61,7 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { /// is a programmer error and will result in a runtime assertion failure because JavaScript /// object spaces are not shared across threads backed by Web Workers. private func assertOnOwnerThread(hint: @autoclosure () -> String) { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) precondition( ownerTid == swjs_get_worker_thread_id_cached(), "JSObject is being accessed from a thread other than the owner thread: \(hint())" @@ -71,7 +71,7 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { /// Asserts that the two objects being compared are owned by the same thread. private static func assertSameOwnerThread(lhs: JSObject, rhs: JSObject, hint: @autoclosure () -> String) { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) precondition( lhs.ownerTid == rhs.ownerTid, "JSObject is being accessed from a thread other than the owner thread: \(hint())" @@ -282,7 +282,7 @@ public class JSObject: Equatable, ExpressibleByDictionaryLiteral { }) deinit { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) if ownerTid != swjs_get_worker_thread_id_cached() { // If the object is not owned by the current thread swjs_release_remote(ownerTid, id) diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSString.swift b/Sources/JavaScriptKit/FundamentalObjects/JSString.swift index 4e6a0a085..0eabfa78d 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSString.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSString.swift @@ -16,25 +16,26 @@ import _CJavaScriptKit /// public struct JSString: LosslessStringConvertible, Equatable { /// The internal representation of JS compatible string - /// The initializers of this type must initialize `jsRef` or `buffer`. + /// The initializers of this type must initialize `jsObject` or `buffer`. /// And the uninitialized one will be lazily initialized class Guts { - var shouldDeallocateRef: Bool = false - lazy var jsRef: JavaScriptObjectRef = { - self.shouldDeallocateRef = true - return buffer.withUTF8 { bufferPtr in + // Owns the JS-side ref via JSObject, whose deinit routes the release to + // the correct thread via swjs_release_remote when destroyed off-owner-thread. + lazy var jsObject: JSObject = { + let ref = buffer.withUTF8 { bufferPtr in return swjs_decode_string(bufferPtr.baseAddress!, Int32(bufferPtr.count)) } + return JSObject(id: ref) // captures ownerTid = current thread here }() lazy var buffer: String = { var bytesRef: JavaScriptObjectRef = 0 - let bytesLength = Int(swjs_encode_string(jsRef, &bytesRef)) + let bytesLength = Int(swjs_encode_string(jsObject.id, &bytesRef)) // +1 for null terminator let buffer = UnsafeMutablePointer.allocate(capacity: bytesLength + 1) defer { buffer.deallocate() - swjs_release(bytesRef) + swjs_release(bytesRef) // bytesRef is a same-thread temporary } swjs_load_string(bytesRef, buffer) buffer[bytesLength] = 0 @@ -46,13 +47,7 @@ public struct JSString: LosslessStringConvertible, Equatable { } init(from jsRef: JavaScriptObjectRef) { - self.jsRef = jsRef - self.shouldDeallocateRef = true - } - - deinit { - guard shouldDeallocateRef else { return } - swjs_release(jsRef) + self.jsObject = JSObject(id: jsRef) } } @@ -79,7 +74,7 @@ public struct JSString: LosslessStringConvertible, Equatable { public static func == (lhs: JSString, rhs: JSString) -> Bool { withExtendedLifetime(lhs.guts) { lhsGuts in withExtendedLifetime(rhs.guts) { rhsGuts in - return swjs_value_equals(lhsGuts.jsRef, rhsGuts.jsRef) + return swjs_value_equals(lhsGuts.jsObject.id, rhsGuts.jsObject.id) } } } @@ -95,6 +90,6 @@ extension JSString: ExpressibleByStringLiteral { extension JSString { func asInternalJSRef() -> JavaScriptObjectRef { - guts.jsRef + guts.jsObject.id } } diff --git a/Sources/JavaScriptKit/JSUndefinedOr.swift b/Sources/JavaScriptKit/JSUndefinedOr.swift index c4d601738..de7be09b4 100644 --- a/Sources/JavaScriptKit/JSUndefinedOr.swift +++ b/Sources/JavaScriptKit/JSUndefinedOr.swift @@ -53,4 +53,4 @@ extension JSUndefinedOr: ConvertibleToJSValue where Wrapped: ConvertibleToJSValu // MARK: - BridgeJS (via _BridgedAsOptional in BridgeJSIntrinsics) -@_spi(BridgeJS) extension JSUndefinedOr: _BridgedAsOptional {} +extension JSUndefinedOr: _BridgedAsOptional {} diff --git a/Sources/JavaScriptKit/ThreadLocal.swift b/Sources/JavaScriptKit/ThreadLocal.swift index 12bf78773..4c8bac75f 100644 --- a/Sources/JavaScriptKit/ThreadLocal.swift +++ b/Sources/JavaScriptKit/ThreadLocal.swift @@ -17,7 +17,7 @@ import Glibc /// The value is stored in a thread-local variable, which is a separate copy for each thread. @propertyWrapper final class ThreadLocal: Sendable { - #if compiler(>=6.1) && _runtime(_multithreaded) + #if _runtime(_multithreaded) /// The wrapped value stored in the thread-local storage. /// The initial value is `nil` for each thread. var wrappedValue: Value? { diff --git a/Tests/BridgeJSGlobalTests/Generated/BridgeJS.swift b/Tests/BridgeJSGlobalTests/Generated/BridgeJS.swift index 862debbf0..4e35a1c9f 100644 --- a/Tests/BridgeJSGlobalTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSGlobalTests/Generated/BridgeJS.swift @@ -1,4 +1,5 @@ // bridge-js: skip +// swift-format-ignore-file // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // diff --git a/Tests/BridgeJSGlobalTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSGlobalTests/Generated/JavaScript/BridgeJS.json index f57f91936..5e9626840 100644 --- a/Tests/BridgeJSGlobalTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSGlobalTests/Generated/JavaScript/BridgeJS.json @@ -559,5 +559,8 @@ ] }, - "moduleName" : "BridgeJSGlobalTests" + "moduleName" : "BridgeJSGlobalTests", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Tests/BridgeJSIdentityTests/Generated/BridgeJS.swift b/Tests/BridgeJSIdentityTests/Generated/BridgeJS.swift index e25ebeb4c..72a8dfdd4 100644 --- a/Tests/BridgeJSIdentityTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSIdentityTests/Generated/BridgeJS.swift @@ -1,4 +1,5 @@ // bridge-js: skip +// swift-format-ignore-file // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // @@ -333,6 +334,25 @@ fileprivate func _bjs_ArrayIdentityElement_wrap_extern(_ pointer: UnsafeMutableR return _bjs_ArrayIdentityElement_wrap_extern(pointer) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSIdentityTests", name: "bjs_gc") +fileprivate func bjs_gc_extern() -> Void +#else +fileprivate func bjs_gc_extern() -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_gc() -> Void { + return bjs_gc_extern() +} + +func _$gc() throws(JSException) -> Void { + bjs_gc() + if let error = _swift_js_take_exception() { + throw error + } +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSIdentityTests", name: "bjs_IdentityModeTestImports_runJsIdentityModeTests_static") fileprivate func bjs_IdentityModeTestImports_runJsIdentityModeTests_static_extern() -> Void diff --git a/Tests/BridgeJSIdentityTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSIdentityTests/Generated/JavaScript/BridgeJS.json index d30ca00f8..56db0a3ed 100644 --- a/Tests/BridgeJSIdentityTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSIdentityTests/Generated/JavaScript/BridgeJS.json @@ -406,10 +406,28 @@ "children" : [ { "functions" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "from" : "global", + "name" : "gc", + "parameters" : [ + + ], + "returnType" : { + "void" : { + } + } + } ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -422,6 +440,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -443,5 +462,8 @@ } ] }, - "moduleName" : "BridgeJSIdentityTests" + "moduleName" : "BridgeJSIdentityTests", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Tests/BridgeJSIdentityTests/IdentityModeTests.swift b/Tests/BridgeJSIdentityTests/IdentityModeTests.swift index 795b0679b..dacf85800 100644 --- a/Tests/BridgeJSIdentityTests/IdentityModeTests.swift +++ b/Tests/BridgeJSIdentityTests/IdentityModeTests.swift @@ -1,6 +1,8 @@ import XCTest import JavaScriptKit +@JSFunction(from: .global) func gc() throws(JSException) -> Void + @JSClass struct IdentityModeTestImports { @JSFunction static func runJsIdentityModeTests() throws(JSException) } @@ -9,6 +11,46 @@ final class IdentityModeTests: XCTestCase { func testRunJsIdentityModeTests() throws { try IdentityModeTestImports.runJsIdentityModeTests() } + + /// Verifies that identity-cached wrappers are properly reclaimed by GC. + /// + /// Creates an identity-mode object, crosses it multiple times (filling the + /// identity cache), drops all references, triggers GC + event loop ticks, + /// and verifies the Swift object is deallocated. This proves that the + /// WeakRef-based identity cache does not prevent garbage collection. + func testIdentityCachedWrapperIsReclaimedByGC() async throws { + RetainLeakSubject.deinits = 0 + + // Create object and cross it multiple times to fill identity cache + _retainLeakSubject = RetainLeakSubject(tag: 99) + weak var weakSubject = _retainLeakSubject + + // Cross to JS 5 times (populates identity cache with WeakRef) + for _ in 0..<5 { + _ = getRetainLeakSubject() + } + + // Drop Swift-side strong reference + _retainLeakSubject = nil + + // JS wrapper should still be alive via the identity cache's WeakRef, + // but WeakRef doesn't prevent GC. Trigger GC + event loop ticks to + // let FinalizationRegistry fire and call deinit. + for _ in 0..<100 { + try gc() + // Give the JS runtime an actual turn so FinalizationRegistry callbacks + // can run before we check the Swift weak reference. + try await Task.sleep(for: .milliseconds(1)) + if weakSubject == nil { + break + } + } + + // The identity-cached wrapper should have been collected, + // FinalizationRegistry should have fired, deinit should have run. + XCTAssertNil(weakSubject, "Identity-cached object should be deallocated after GC") + XCTAssertEqual(RetainLeakSubject.deinits, 1, "Deinit should fire exactly once") + } } @JS class IdentityTestSubject { diff --git a/Tests/BridgeJSRuntimeTests/AsyncImportTests.swift b/Tests/BridgeJSRuntimeTests/AsyncImportTests.swift index 041f251f4..a092d111c 100644 --- a/Tests/BridgeJSRuntimeTests/AsyncImportTests.swift +++ b/Tests/BridgeJSRuntimeTests/AsyncImportTests.swift @@ -1,6 +1,12 @@ import Testing import JavaScriptKit +@JS enum AsyncImportedPayloadResult: Equatable { + case success(String) + case failure(Int) + case idle +} + @JSClass struct AsyncImportImports { @JSFunction static func jsAsyncRoundTripVoid() async throws(JSException) @JSFunction static func jsAsyncRoundTripNumber(_ v: Double) async throws(JSException) -> Double @@ -12,6 +18,12 @@ import JavaScriptKit @JSFunction static func jsAsyncRoundTripIntArray(_ values: [Double]) async throws(JSException) -> [Double] @JSFunction static func jsAsyncRoundTripStringArray(_ values: [String]) async throws(JSException) -> [String] @JSFunction static func jsAsyncRoundTripFeatureFlag(_ v: FeatureFlag) async throws(JSException) -> FeatureFlag + @JSFunction static func jsAsyncRoundTripAssociatedValueEnum( + _ v: AsyncImportedPayloadResult + ) async throws(JSException) -> AsyncImportedPayloadResult + @JSFunction static func jsAsyncRoundTripOptionalAssociatedValueEnum( + _ v: AsyncImportedPayloadResult? + ) async throws(JSException) -> AsyncImportedPayloadResult? } @Suite struct AsyncImportTests { @@ -69,6 +81,29 @@ import JavaScriptKit try #expect(await AsyncImportImports.jsAsyncRoundTripFeatureFlag(v) == v) } + @Test func asyncRoundTripAssociatedValueEnum() async throws { + let values: [AsyncImportedPayloadResult] = [ + .success("ok"), + .failure(7), + .idle, + ] + for value in values { + try #expect(await AsyncImportImports.jsAsyncRoundTripAssociatedValueEnum(value) == value) + } + } + + @Test func asyncRoundTripOptionalAssociatedValueEnum() async throws { + let values: [AsyncImportedPayloadResult?] = [ + .some(.success("ok")), + .some(.failure(7)), + .some(.idle), + nil, + ] + for value in values { + try #expect(await AsyncImportImports.jsAsyncRoundTripOptionalAssociatedValueEnum(value) == value) + } + } + // MARK: - Structured return type @Test func fetchWeatherData() async throws { diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 2562fe18e..282b7cc60 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -75,6 +75,10 @@ func runJsWorks() -> Void return try Foo(value) } +@JS func roundTripOptionalImportedClass(v: Foo?) -> Foo? { + return v +} + struct TestError: Error { let message: String } @@ -92,6 +96,10 @@ struct TestError: Error { @JS func throwsWithSwiftHeapObjectResult() throws(JSException) -> Greeter { return Greeter(name: "Test") } @JS func throwsWithJSObjectResult() throws(JSException) -> JSObject { return JSObject() } +@JS func zeroArgAsyncThrows() async throws(JSException) -> String { + throw JSException(JSError(message: "ZeroArgAsyncThrowsError").jsValue) +} + @JS func asyncRoundTripVoid() async -> Void { return } @JS func asyncRoundTripInt(v: Int) async -> Int { return v } @JS func asyncRoundTripFloat(v: Float) async -> Float { return v } @@ -174,6 +182,10 @@ extension Greeter { return a + b } + @JS func asyncMakePoint(x: Int, y: Int) async -> PublicPoint { + return PublicPoint(x: x, y: y) + } + deinit { Self.onDeinit() } @@ -302,6 +314,36 @@ extension StaticCalculator { return .light } +@JS func asyncRoundTripTheme(_ v: Theme) async -> Theme { v } + +@JS func asyncRoundTripDirection(_ v: Direction) async -> Direction { v } + +@JS func asyncRoundTripOptionalTheme(_ v: Theme?) async -> Theme? { v } + +@JS func asyncRoundTripOptionalDirection(_ v: Direction?) async -> Direction? { v } + +@JS func asyncRoundTripDirectionArray(_ v: [Direction]) async -> [Direction] { v } + +@JS func asyncRoundTripDirectionDict(_ v: [String: Direction]) async -> [String: Direction] { v } + +@JS func asyncRoundTripThemeArray(_ v: [Theme]) async -> [Theme] { v } + +@JS func asyncRoundTripThemeDict(_ v: [String: Theme]) async -> [String: Theme] { v } + +@JS func asyncRoundTripFileSize(_ v: FileSize) async -> FileSize { v } + +@JS func asyncRoundTripOptionalFileSize(_ v: FileSize?) async -> FileSize? { v } + +@JS enum AsyncPayloadResult: Equatable { + case success(String) + case failure(Int) + case idle +} + +@JS func asyncRoundTripAssociatedValueEnum(_ v: AsyncPayloadResult) async -> AsyncPayloadResult { v } + +@JS func asyncRoundTripOptionalAssociatedValueEnum(_ v: AsyncPayloadResult?) async -> AsyncPayloadResult? { v } + @JS func setHttpStatus(_ status: HttpStatus) -> HttpStatus { return status } @@ -1285,6 +1327,36 @@ enum GraphOperations { processor.increment(by: 7) return callback(processor) + " | " + callback(nil) } + + @JS func processVector(_ callback: (Double) -> Vector2D) -> Double { + return callback(3.0).magnitude() + } + + @JS func processOptionalVector(_ callback: (Double) -> Vector2D?) -> String { + let some = callback(2.0) + let none = callback(-1.0) + let someStr = some.map { "(\($0.dx),\($0.dy))" } ?? "nil" + let noneStr = none.map { "(\($0.dx),\($0.dy))" } ?? "nil" + return "\(someStr) | \(noneStr)" + } +} + +@JS enum NestedStructGroupA { + @JS struct Metadata { + var label: String + var count: Int + } + + @JS static func roundtripMetadata(_ m: Metadata) -> Metadata { m } +} + +@JS enum NestedStructGroupB { + @JS struct Metadata { + var tag: String + var value: Double + } + + @JS static func roundtripMetadata(_ m: Metadata) -> Metadata { m } } class ExportAPITests: XCTestCase { diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift index e3a6eec61..08d0db2a7 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift @@ -1,3 +1,4 @@ +// swift-format-ignore-file // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index a37a7e4c5..c02cb72f7 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -1,4 +1,5 @@ // bridge-js: skip +// swift-format-ignore-file // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. // @@ -369,7 +370,7 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests7GreeterC_SS { } extension JSTypedClosure where Signature == (Greeter) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Greeter) -> String) { + public init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Greeter) -> String) { self.init( makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests7GreeterC_SS, body: body, @@ -687,7 +688,7 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_7GreeterC { } extension JSTypedClosure where Signature == (String) -> Greeter { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> Greeter) { + public init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> Greeter) { self.init( makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC, body: body, @@ -753,7 +754,7 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_SS { } extension JSTypedClosure where Signature == (String) -> String { - init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> String) { + public init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (String) -> String) { self.init( makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS, body: body, @@ -775,6 +776,69 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_ #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV_extern(_ callback: Int32, _ param0: Float64) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV_extern(_ callback: Int32, _ param0: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV(_ callback: Int32, _ param0: Float64) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV_extern(callback, param0) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSd_8Vector2DV { + static func bridgeJSLift(_ callbackId: Int32) -> (Double) -> Vector2D { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV(callbackValue, param0Value) + return Vector2D.bridgeJSLiftReturn() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Double) -> Vector2D { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Double) -> Vector2D) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_8Vector2DV(_ boxPtr: UnsafeMutableRawPointer, _ param0: Float64) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Double) -> Vector2D>>.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_20BridgeJSRuntimeTestsSd_Sd") fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sd_extern(_ callback: Int32, _ param0: Float64) -> Float64 @@ -838,6 +902,69 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_ #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV_extern(_ callback: Int32, _ param0: Float64) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV_extern(_ callback: Int32, _ param0: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV(_ callback: Int32, _ param0: Float64) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV_extern(callback, param0) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_20BridgeJSRuntimeTestsSd_Sq8Vector2DV { + static func bridgeJSLift(_ callbackId: Int32) -> (Double) -> Optional { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0Value = param0.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV(callbackValue, param0Value) + return Optional.bridgeJSLiftReturn() + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (Double) -> Optional { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (Double) -> Optional) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_Sq8Vector2DV(_ boxPtr: UnsafeMutableRawPointer, _ param0: Float64) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(Double) -> Optional>>.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_extern(_ callback: Int32, _ param0: Int32, _ param1Bytes: Int32, _ param1Length: Int32, _ param2: Float64) -> Int32 @@ -1797,6 +1924,67 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11 #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(_ callback: Int32, _ param0: Int32) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(_ callback: Int32, _ param0: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y(_ callback: Int32, _ param0: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(callback, param0) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y { + static func bridgeJSLift(_ callbackId: Int32) -> (sending AsyncImportedPayloadResult) -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0CaseId = param0.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y(callbackValue, param0CaseId) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (sending AsyncImportedPayloadResult) -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (sending AsyncImportedPayloadResult) -> Void) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(sending AsyncImportedPayloadResult) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(AsyncImportedPayloadResult.bridgeJSLiftParameter(param0)) + #else + fatalError("Only available on WebAssembly") + #endif +} + #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss7JSValueV_y") fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss7JSValueV_y_extern(_ callback: Int32, _ param0Kind: Int32, _ param0Payload1: Int32, _ param0Payload2: Float64) -> Void @@ -2225,6 +2413,67 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSd #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(callback, param0IsSome, param0CaseId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y { + static func bridgeJSLift(_ callbackId: Int32) -> (sending Optional) -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0CaseId) = param0.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y(callbackValue, param0IsSome, param0CaseId) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (sending Optional) -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (sending Optional) -> Void) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(sending Optional) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) + #else + fatalError("Only available on WebAssembly") + #endif +} + #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y") fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void @@ -3689,6 +3938,34 @@ public func _bjs_ArraySupportExports_static_multiOptionalArraySecond() -> Void { #endif } +extension AsyncImportedPayloadResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AsyncImportedPayloadResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown AsyncImportedPayloadResult 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 .idle: + return Int32(2) + } + } +} + @_expose(wasm, "bjs_DefaultArgumentExports_static_testStringDefault") @_cdecl("bjs_DefaultArgumentExports_static_testStringDefault") public func _bjs_DefaultArgumentExports_static_testStringDefault(_ messageBytes: Int32, _ messageLength: Int32) -> Void { @@ -4000,6 +4277,34 @@ extension TSDirection: _BridgedSwiftCaseEnum { extension TSTheme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { } +extension AsyncPayloadResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AsyncPayloadResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown AsyncPayloadResult 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 .idle: + return Int32(2) + } + } +} + @_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 { @@ -4682,49 +4987,138 @@ public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_se #endif } -@_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripInt") -@_cdecl("bjs_IntegerTypesSupportExports_static_roundTripInt") -public func _bjs_IntegerTypesSupportExports_static_roundTripInt(_ v: Int32) -> Int32 { +@_expose(wasm, "bjs_NestedStructGroupA_static_roundtripMetadata") +@_cdecl("bjs_NestedStructGroupA_static_roundtripMetadata") +public func _bjs_NestedStructGroupA_static_roundtripMetadata() -> Void { #if arch(wasm32) - let ret = IntegerTypesSupportExports.roundTripInt(_: Int.bridgeJSLiftParameter(v)) + let ret = NestedStructGroupA.roundtripMetadata(_: NestedStructGroupA.Metadata.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripUInt") -@_cdecl("bjs_IntegerTypesSupportExports_static_roundTripUInt") -public func _bjs_IntegerTypesSupportExports_static_roundTripUInt(_ v: Int32) -> Int32 { +@_expose(wasm, "bjs_NestedStructGroupB_static_roundtripMetadata") +@_cdecl("bjs_NestedStructGroupB_static_roundtripMetadata") +public func _bjs_NestedStructGroupB_static_roundtripMetadata() -> Void { #if arch(wasm32) - let ret = IntegerTypesSupportExports.roundTripUInt(_: UInt.bridgeJSLiftParameter(v)) + let ret = NestedStructGroupB.roundtripMetadata(_: NestedStructGroupB.Metadata.bridgeJSLiftParameter()) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripInt8") -@_cdecl("bjs_IntegerTypesSupportExports_static_roundTripInt8") -public func _bjs_IntegerTypesSupportExports_static_roundTripInt8(_ v: Int32) -> Int32 { - #if arch(wasm32) - let ret = IntegerTypesSupportExports.roundTripInt8(_: Int8.bridgeJSLiftParameter(v)) - return ret.bridgeJSLowerReturn() - #else - fatalError("Only available on WebAssembly") - #endif -} +extension LightColor: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> LightColor { + return bridgeJSLiftParameter(value) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> LightColor { + return LightColor(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSLowerParameter() + } -@_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripUInt8") -@_cdecl("bjs_IntegerTypesSupportExports_static_roundTripUInt8") -public func _bjs_IntegerTypesSupportExports_static_roundTripUInt8(_ v: Int32) -> Int32 { - #if arch(wasm32) - let ret = IntegerTypesSupportExports.roundTripUInt8(_: UInt8.bridgeJSLiftParameter(v)) - return ret.bridgeJSLowerReturn() - #else - fatalError("Only available on WebAssembly") - #endif -} + @_spi(BridgeJS) @usableFromInline init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .red + case 1: + self = .yellow + case 2: + self = .green + default: + return nil + } + } + + @_spi(BridgeJS) @usableFromInline var bridgeJSRawValue: Int32 { + switch self { + case .red: + return 0 + case .yellow: + return 1 + case .green: + return 2 + } + } +} + +extension ImportedPayloadSignal: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> ImportedPayloadSignal { + switch caseId { + case 0: + return .start(String.bridgeJSStackPop()) + case 1: + return .stop(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown ImportedPayloadSignal case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .start(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .stop(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .idle: + return Int32(2) + } + } +} + +@_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripInt") +@_cdecl("bjs_IntegerTypesSupportExports_static_roundTripInt") +public func _bjs_IntegerTypesSupportExports_static_roundTripInt(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = IntegerTypesSupportExports.roundTripInt(_: Int.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripUInt") +@_cdecl("bjs_IntegerTypesSupportExports_static_roundTripUInt") +public func _bjs_IntegerTypesSupportExports_static_roundTripUInt(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = IntegerTypesSupportExports.roundTripUInt(_: UInt.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripInt8") +@_cdecl("bjs_IntegerTypesSupportExports_static_roundTripInt8") +public func _bjs_IntegerTypesSupportExports_static_roundTripInt8(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = IntegerTypesSupportExports.roundTripInt8(_: Int8.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripUInt8") +@_cdecl("bjs_IntegerTypesSupportExports_static_roundTripUInt8") +public func _bjs_IntegerTypesSupportExports_static_roundTripUInt8(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = IntegerTypesSupportExports.roundTripUInt8(_: UInt8.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} @_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripInt16") @_cdecl("bjs_IntegerTypesSupportExports_static_roundTripInt16") @@ -4792,6 +5186,50 @@ public func _bjs_IntegerTypesSupportExports_static_roundTripUInt64(_ v: Int64) - #endif } +@_expose(wasm, "bjs_JSTypedArrayExports_static_roundTripUint8Array") +@_cdecl("bjs_JSTypedArrayExports_static_roundTripUint8Array") +public func _bjs_JSTypedArrayExports_static_roundTripUint8Array(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSTypedArrayExports.roundTripUint8Array(_: JSUint8Array.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSTypedArrayExports_static_roundTripFloat32Array") +@_cdecl("bjs_JSTypedArrayExports_static_roundTripFloat32Array") +public func _bjs_JSTypedArrayExports_static_roundTripFloat32Array(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSTypedArrayExports.roundTripFloat32Array(_: JSFloat32Array.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSTypedArrayExports_static_roundTripFloat64Array") +@_cdecl("bjs_JSTypedArrayExports_static_roundTripFloat64Array") +public func _bjs_JSTypedArrayExports_static_roundTripFloat64Array(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSTypedArrayExports.roundTripFloat64Array(_: JSFloat64Array.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_JSTypedArrayExports_static_roundTripInt32Array") +@_cdecl("bjs_JSTypedArrayExports_static_roundTripInt32Array") +public func _bjs_JSTypedArrayExports_static_roundTripInt32Array(_ v: Int32) -> Int32 { + #if arch(wasm32) + let ret = JSTypedArrayExports.roundTripInt32Array(_: JSInt32Array.bridgeJSLiftParameter(v)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_OptionalSupportExports_static_roundTripOptionalString") @_cdecl("bjs_OptionalSupportExports_static_roundTripOptionalString") public func _bjs_OptionalSupportExports_static_roundTripOptionalString(_ vIsSome: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { @@ -5192,6 +5630,102 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { } } +extension NestedStructGroupA.Metadata: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> NestedStructGroupA.Metadata { + let count = Int.bridgeJSStackPop() + let label = String.bridgeJSStackPop() + return NestedStructGroupA.Metadata(label: label, count: count) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.label.bridgeJSStackPush() + self.count.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_NestedStructGroupA_Metadata(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_NestedStructGroupA_Metadata())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_NestedStructGroupA_Metadata") +fileprivate func _bjs_struct_lower_NestedStructGroupA_Metadata_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_NestedStructGroupA_Metadata_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_NestedStructGroupA_Metadata(_ objectId: Int32) -> Void { + return _bjs_struct_lower_NestedStructGroupA_Metadata_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_NestedStructGroupA_Metadata") +fileprivate func _bjs_struct_lift_NestedStructGroupA_Metadata_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_NestedStructGroupA_Metadata_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_NestedStructGroupA_Metadata() -> Int32 { + return _bjs_struct_lift_NestedStructGroupA_Metadata_extern() +} + +extension NestedStructGroupB.Metadata: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> NestedStructGroupB.Metadata { + let value = Double.bridgeJSStackPop() + let tag = String.bridgeJSStackPop() + return NestedStructGroupB.Metadata(tag: tag, value: value) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.tag.bridgeJSStackPush() + self.value.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_NestedStructGroupB_Metadata(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_NestedStructGroupB_Metadata())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_NestedStructGroupB_Metadata") +fileprivate func _bjs_struct_lower_NestedStructGroupB_Metadata_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_NestedStructGroupB_Metadata_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_NestedStructGroupB_Metadata(_ objectId: Int32) -> Void { + return _bjs_struct_lower_NestedStructGroupB_Metadata_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_NestedStructGroupB_Metadata") +fileprivate func _bjs_struct_lift_NestedStructGroupB_Metadata_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_NestedStructGroupB_Metadata_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_NestedStructGroupB_Metadata() -> Int32 { + return _bjs_struct_lift_NestedStructGroupB_Metadata_extern() +} + extension Point: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Point { let y = Int.bridgeJSStackPop() @@ -6639,7 +7173,7 @@ public func _bjs_makeImportedFoo(_ valueBytes: Int32, _ valueLength: Int32) -> I _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6651,6 +7185,17 @@ public func _bjs_makeImportedFoo(_ valueBytes: Int32, _ valueLength: Int32) -> I #endif } +@_expose(wasm, "bjs_roundTripOptionalImportedClass") +@_cdecl("bjs_roundTripOptionalImportedClass") +public func _bjs_roundTripOptionalImportedClass(_ vIsSome: Int32, _ vValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalImportedClass(v: Optional.bridgeJSLiftParameter(vIsSome, vValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_throwsSwiftError") @_cdecl("bjs_throwsSwiftError") public func _bjs_throwsSwiftError(_ shouldThrow: Int32) -> Void { @@ -6663,7 +7208,7 @@ public func _bjs_throwsSwiftError(_ shouldThrow: Int32) -> Void { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6688,7 +7233,7 @@ public func _bjs_throwsWithIntResult() -> Int32 { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6713,7 +7258,7 @@ public func _bjs_throwsWithStringResult() -> Void { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6738,7 +7283,7 @@ public func _bjs_throwsWithBoolResult() -> Int32 { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6763,7 +7308,7 @@ public func _bjs_throwsWithFloatResult() -> Float32 { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6788,7 +7333,7 @@ public func _bjs_throwsWithDoubleResult() -> Float64 { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6813,7 +7358,7 @@ public func _bjs_throwsWithSwiftHeapObjectResult() -> UnsafeMutableRawPointer { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6838,7 +7383,7 @@ public func _bjs_throwsWithJSObjectResult() -> Int32 { _swift_js_throw(Int32(bitPattern: $0.id)) } } else { - let jsError = JSError(message: String(describing: error)) + let jsError = JSError(message: error.description) withExtendedLifetime(jsError.jsObject) { _swift_js_throw(Int32(bitPattern: $0.id)) } @@ -6850,14 +7395,27 @@ public func _bjs_throwsWithJSObjectResult() -> Int32 { #endif } +@_expose(wasm, "bjs_zeroArgAsyncThrows") +@_cdecl("bjs_zeroArgAsyncThrows") +public func _bjs_zeroArgAsyncThrows() -> Int32 { + #if arch(wasm32) + let __bjs_capture = 0 + return _bjs_makePromise(resolve: Promise_resolve_SS, reject: Promise_reject) { [__bjs_capture] () async throws(JSException) -> String in + _ = __bjs_capture + return try await zeroArgAsyncThrows() + } + #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 { + return _bjs_makePromise(resolve: Promise_resolve_y, reject: Promise_reject) { await asyncRoundTripVoid() - }.jsObject - return ret.bridgeJSLowerReturn() + } #else fatalError("Only available on WebAssembly") #endif @@ -6867,10 +7425,9 @@ public func _bjs_asyncRoundTripVoid() -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_Si, reject: Promise_reject) { + return await asyncRoundTripInt(v: Int.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -6880,10 +7437,9 @@ public func _bjs_asyncRoundTripInt(_ v: Int32) -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_Sf, reject: Promise_reject) { + return await asyncRoundTripFloat(v: Float.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -6893,10 +7449,9 @@ public func _bjs_asyncRoundTripFloat(_ v: Float32) -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_Sd, reject: Promise_reject) { + return await asyncRoundTripDouble(v: Double.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -6906,10 +7461,9 @@ public func _bjs_asyncRoundTripDouble(_ v: Float64) -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_Sb, reject: Promise_reject) { + return await asyncRoundTripBool(v: Bool.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -6919,10 +7473,9 @@ public func _bjs_asyncRoundTripBool(_ v: Int32) -> Int32 { @_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() + return _bjs_makePromise(resolve: Promise_resolve_SS, reject: Promise_reject) { + return await asyncRoundTripString(v: String.bridgeJSLiftParameter(vBytes, vLength)) + } #else fatalError("Only available on WebAssembly") #endif @@ -6932,10 +7485,9 @@ public func _bjs_asyncRoundTripString(_ vBytes: Int32, _ vLength: Int32) -> Int3 @_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() + return _bjs_makePromise(resolve: Promise_resolve_7GreeterC, reject: Promise_reject) { + return await asyncRoundTripSwiftHeapObject(v: Greeter.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -6945,10 +7497,9 @@ public func _bjs_asyncRoundTripSwiftHeapObject(_ v: UnsafeMutableRawPointer) -> @_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() + return _bjs_makePromise(resolve: Promise_resolve_8JSObjectC, reject: Promise_reject) { + return await asyncRoundTripJSObject(v: JSObject.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif @@ -7074,122 +7625,272 @@ public func _bjs_getTheme() -> Void { #endif } -@_expose(wasm, "bjs_setHttpStatus") -@_cdecl("bjs_setHttpStatus") -public func _bjs_setHttpStatus(_ status: Int32) -> Int32 { +@_expose(wasm, "bjs_asyncRoundTripTheme") +@_cdecl("bjs_asyncRoundTripTheme") +public func _bjs_asyncRoundTripTheme(_ vBytes: Int32, _ vLength: Int32) -> Int32 { #if arch(wasm32) - let ret = setHttpStatus(_: HttpStatus.bridgeJSLiftParameter(status)) - return ret.bridgeJSLowerReturn() + return _bjs_makePromise(resolve: Promise_resolve_5ThemeO, reject: Promise_reject) { + return await asyncRoundTripTheme(_: Theme.bridgeJSLiftParameter(vBytes, vLength)) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_getHttpStatus") -@_cdecl("bjs_getHttpStatus") -public func _bjs_getHttpStatus() -> Int32 { +@_expose(wasm, "bjs_asyncRoundTripDirection") +@_cdecl("bjs_asyncRoundTripDirection") +public func _bjs_asyncRoundTripDirection(_ v: Int32) -> Int32 { #if arch(wasm32) - let ret = getHttpStatus() - return ret.bridgeJSLowerReturn() + return _bjs_makePromise(resolve: Promise_resolve_9DirectionO, reject: Promise_reject) { + return await asyncRoundTripDirection(_: Direction.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_setFileSize") -@_cdecl("bjs_setFileSize") -public func _bjs_setFileSize(_ size: Int64) -> Int64 { +@_expose(wasm, "bjs_asyncRoundTripOptionalTheme") +@_cdecl("bjs_asyncRoundTripOptionalTheme") +public func _bjs_asyncRoundTripOptionalTheme(_ vIsSome: Int32, _ vBytes: Int32, _ vLength: Int32) -> Int32 { #if arch(wasm32) - let ret = setFileSize(_: FileSize.bridgeJSLiftParameter(size)) - return ret.bridgeJSLowerReturn() + return _bjs_makePromise(resolve: Promise_resolve_Sq5ThemeO, reject: Promise_reject) { + return await asyncRoundTripOptionalTheme(_: Optional.bridgeJSLiftParameter(vIsSome, vBytes, vLength)) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_getFileSize") -@_cdecl("bjs_getFileSize") -public func _bjs_getFileSize() -> Int64 { +@_expose(wasm, "bjs_asyncRoundTripOptionalDirection") +@_cdecl("bjs_asyncRoundTripOptionalDirection") +public func _bjs_asyncRoundTripOptionalDirection(_ vIsSome: Int32, _ vValue: Int32) -> Int32 { #if arch(wasm32) - let ret = getFileSize() - return ret.bridgeJSLowerReturn() + return _bjs_makePromise(resolve: Promise_resolve_Sq9DirectionO, reject: Promise_reject) { + return await asyncRoundTripOptionalDirection(_: Optional.bridgeJSLiftParameter(vIsSome, vValue)) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_setSessionId") -@_cdecl("bjs_setSessionId") -public func _bjs_setSessionId(_ session: Int64) -> Int64 { +@_expose(wasm, "bjs_asyncRoundTripDirectionArray") +@_cdecl("bjs_asyncRoundTripDirectionArray") +public func _bjs_asyncRoundTripDirectionArray() -> Int32 { #if arch(wasm32) - let ret = setSessionId(_: SessionId.bridgeJSLiftParameter(session)) - return ret.bridgeJSLowerReturn() + let _tmp_v = [Direction].bridgeJSStackPop() + return _bjs_makePromise(resolve: Promise_resolve_Sa9DirectionO, reject: Promise_reject) { + return await asyncRoundTripDirectionArray(_: _tmp_v) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_getSessionId") -@_cdecl("bjs_getSessionId") -public func _bjs_getSessionId() -> Int64 { +@_expose(wasm, "bjs_asyncRoundTripDirectionDict") +@_cdecl("bjs_asyncRoundTripDirectionDict") +public func _bjs_asyncRoundTripDirectionDict() -> Int32 { #if arch(wasm32) - let ret = getSessionId() - return ret.bridgeJSLowerReturn() + let _tmp_v = [String: Direction].bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_SD9DirectionO, reject: Promise_reject) { + return await asyncRoundTripDirectionDict(_: _tmp_v) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_processTheme") -@_cdecl("bjs_processTheme") -public func _bjs_processTheme(_ themeBytes: Int32, _ themeLength: Int32) -> Int32 { +@_expose(wasm, "bjs_asyncRoundTripThemeArray") +@_cdecl("bjs_asyncRoundTripThemeArray") +public func _bjs_asyncRoundTripThemeArray() -> Int32 { #if arch(wasm32) - let ret = processTheme(_: Theme.bridgeJSLiftParameter(themeBytes, themeLength)) - return ret.bridgeJSLowerReturn() + let _tmp_v = [Theme].bridgeJSStackPop() + return _bjs_makePromise(resolve: Promise_resolve_Sa5ThemeO, reject: Promise_reject) { + return await asyncRoundTripThemeArray(_: _tmp_v) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_setTSDirection") -@_cdecl("bjs_setTSDirection") -public func _bjs_setTSDirection(_ direction: Int32) -> Int32 { +@_expose(wasm, "bjs_asyncRoundTripThemeDict") +@_cdecl("bjs_asyncRoundTripThemeDict") +public func _bjs_asyncRoundTripThemeDict() -> Int32 { #if arch(wasm32) - let ret = setTSDirection(_: TSDirection.bridgeJSLiftParameter(direction)) - return ret.bridgeJSLowerReturn() + let _tmp_v = [String: Theme].bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_SD5ThemeO, reject: Promise_reject) { + return await asyncRoundTripThemeDict(_: _tmp_v) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_getTSDirection") -@_cdecl("bjs_getTSDirection") -public func _bjs_getTSDirection() -> Int32 { +@_expose(wasm, "bjs_asyncRoundTripFileSize") +@_cdecl("bjs_asyncRoundTripFileSize") +public func _bjs_asyncRoundTripFileSize(_ v: Int64) -> Int32 { #if arch(wasm32) - let ret = getTSDirection() - return ret.bridgeJSLowerReturn() + return _bjs_makePromise(resolve: Promise_resolve_8FileSizeO, reject: Promise_reject) { + return await asyncRoundTripFileSize(_: FileSize.bridgeJSLiftParameter(v)) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_setTSTheme") -@_cdecl("bjs_setTSTheme") -public func _bjs_setTSTheme(_ themeBytes: Int32, _ themeLength: Int32) -> Void { +@_expose(wasm, "bjs_asyncRoundTripOptionalFileSize") +@_cdecl("bjs_asyncRoundTripOptionalFileSize") +public func _bjs_asyncRoundTripOptionalFileSize(_ vIsSome: Int32, _ vValue: Int64) -> Int32 { #if arch(wasm32) - let ret = setTSTheme(_: TSTheme.bridgeJSLiftParameter(themeBytes, themeLength)) - return ret.bridgeJSLowerReturn() + return _bjs_makePromise(resolve: Promise_resolve_Sq8FileSizeO, reject: Promise_reject) { + return await asyncRoundTripOptionalFileSize(_: Optional.bridgeJSLiftParameter(vIsSome, vValue)) + } #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_getTSTheme") -@_cdecl("bjs_getTSTheme") -public func _bjs_getTSTheme() -> Void { +@_expose(wasm, "bjs_asyncRoundTripAssociatedValueEnum") +@_cdecl("bjs_asyncRoundTripAssociatedValueEnum") +public func _bjs_asyncRoundTripAssociatedValueEnum(_ v: Int32) -> Int32 { #if arch(wasm32) - let ret = getTSTheme() - return ret.bridgeJSLowerReturn() + let _tmp_v = AsyncPayloadResult.bridgeJSLiftParameter(v) + return _bjs_makePromise(resolve: Promise_resolve_18AsyncPayloadResultO, reject: Promise_reject) { + return await asyncRoundTripAssociatedValueEnum(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripOptionalAssociatedValueEnum") +@_cdecl("bjs_asyncRoundTripOptionalAssociatedValueEnum") +public func _bjs_asyncRoundTripOptionalAssociatedValueEnum(_ vIsSome: Int32, _ vCaseId: Int32) -> Int32 { + #if arch(wasm32) + let _tmp_v = Optional.bridgeJSLiftParameter(vIsSome, vCaseId) + return _bjs_makePromise(resolve: Promise_resolve_Sq18AsyncPayloadResultO, reject: Promise_reject) { + return await asyncRoundTripOptionalAssociatedValueEnum(_: _tmp_v) + } + #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_setFileSize") +@_cdecl("bjs_setFileSize") +public func _bjs_setFileSize(_ size: Int64) -> Int64 { + #if arch(wasm32) + let ret = setFileSize(_: FileSize.bridgeJSLiftParameter(size)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getFileSize") +@_cdecl("bjs_getFileSize") +public func _bjs_getFileSize() -> Int64 { + #if arch(wasm32) + let ret = getFileSize() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_setSessionId") +@_cdecl("bjs_setSessionId") +public func _bjs_setSessionId(_ session: Int64) -> Int64 { + #if arch(wasm32) + let ret = setSessionId(_: SessionId.bridgeJSLiftParameter(session)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getSessionId") +@_cdecl("bjs_getSessionId") +public func _bjs_getSessionId() -> Int64 { + #if arch(wasm32) + let ret = getSessionId() + 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 @@ -7722,6 +8423,110 @@ public func _bjs_roundTripPublicPoint() -> Void { #endif } +@_expose(wasm, "bjs_asyncRoundTripPublicPoint") +@_cdecl("bjs_asyncRoundTripPublicPoint") +public func _bjs_asyncRoundTripPublicPoint() -> Int32 { + #if arch(wasm32) + let _tmp_point = PublicPoint.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_11PublicPointV, reject: Promise_reject) { + return await asyncRoundTripPublicPoint(_: _tmp_point) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripPublicPointThrows") +@_cdecl("bjs_asyncRoundTripPublicPointThrows") +public func _bjs_asyncRoundTripPublicPointThrows() -> Int32 { + #if arch(wasm32) + let _tmp_point = PublicPoint.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_11PublicPointV, reject: Promise_reject) { () async throws(JSException) -> PublicPoint in + return try await asyncRoundTripPublicPointThrows(_: _tmp_point) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncStructOrThrow") +@_cdecl("bjs_asyncStructOrThrow") +public func _bjs_asyncStructOrThrow(_ shouldThrow: Int32) -> Int32 { + #if arch(wasm32) + return _bjs_makePromise(resolve: Promise_resolve_11PublicPointV, reject: Promise_reject) { () async throws(JSException) -> PublicPoint in + return try await asyncStructOrThrow(_: Bool.bridgeJSLiftParameter(shouldThrow)) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncCombinePublicPoints") +@_cdecl("bjs_asyncCombinePublicPoints") +public func _bjs_asyncCombinePublicPoints() -> Int32 { + #if arch(wasm32) + let _tmp_b = PublicPoint.bridgeJSLiftParameter() + let _tmp_a = PublicPoint.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_11PublicPointV, reject: Promise_reject) { + return await asyncCombinePublicPoints(_: _tmp_a, _: _tmp_b) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripContact") +@_cdecl("bjs_asyncRoundTripContact") +public func _bjs_asyncRoundTripContact() -> Int32 { + #if arch(wasm32) + let _tmp_contact = Contact.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_7ContactV, reject: Promise_reject) { + return await asyncRoundTripContact(_: _tmp_contact) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripPublicPointArray") +@_cdecl("bjs_asyncRoundTripPublicPointArray") +public func _bjs_asyncRoundTripPublicPointArray() -> Int32 { + #if arch(wasm32) + let _tmp_points = [PublicPoint].bridgeJSStackPop() + return _bjs_makePromise(resolve: Promise_resolve_Sa11PublicPointV, reject: Promise_reject) { + return await asyncRoundTripPublicPointArray(_: _tmp_points) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripOptionalPublicPoint") +@_cdecl("bjs_asyncRoundTripOptionalPublicPoint") +public func _bjs_asyncRoundTripOptionalPublicPoint() -> Int32 { + #if arch(wasm32) + let _tmp_point = Optional.bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_Sq11PublicPointV, reject: Promise_reject) { + return await asyncRoundTripOptionalPublicPoint(_: _tmp_point) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripPublicPointDict") +@_cdecl("bjs_asyncRoundTripPublicPointDict") +public func _bjs_asyncRoundTripPublicPointDict() -> Int32 { + #if arch(wasm32) + let _tmp_points = [String: PublicPoint].bridgeJSLiftParameter() + return _bjs_makePromise(resolve: Promise_resolve_SD11PublicPointV, reject: Promise_reject) { + return await asyncRoundTripPublicPointDict(_: _tmp_points) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_roundTripContact") @_cdecl("bjs_roundTripContact") public func _bjs_roundTripContact() -> Void { @@ -8331,6 +9136,18 @@ public func _bjs_Calculator_add(_ _self: UnsafeMutableRawPointer, _ a: Int32, _ #endif } +@_expose(wasm, "bjs_Calculator_asyncMakePoint") +@_cdecl("bjs_Calculator_asyncMakePoint") +public func _bjs_Calculator_asyncMakePoint(_ _self: UnsafeMutableRawPointer, _ x: Int32, _ y: Int32) -> Int32 { + #if arch(wasm32) + return _bjs_makePromise(resolve: Promise_resolve_11PublicPointV, reject: Promise_reject) { + return await Calculator.bridgeJSLiftParameter(_self).asyncMakePoint(x: Int.bridgeJSLiftParameter(x), y: Int.bridgeJSLiftParameter(y)) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_Calculator_deinit") @_cdecl("bjs_Calculator_deinit") public func _bjs_Calculator_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { @@ -10441,6 +11258,28 @@ public func _bjs_TextProcessor_processOptionalDataProcessor(_ _self: UnsafeMutab #endif } +@_expose(wasm, "bjs_TextProcessor_processVector") +@_cdecl("bjs_TextProcessor_processVector") +public func _bjs_TextProcessor_processVector(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Float64 { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processVector(_: _BJS_Closure_20BridgeJSRuntimeTestsSd_8Vector2DV.bridgeJSLift(callback)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TextProcessor_processOptionalVector") +@_cdecl("bjs_TextProcessor_processOptionalVector") +public func _bjs_TextProcessor_processOptionalVector(_ _self: UnsafeMutableRawPointer, _ callback: Int32) -> Void { + #if arch(wasm32) + let ret = TextProcessor.bridgeJSLiftParameter(_self).processOptionalVector(_: _BJS_Closure_20BridgeJSRuntimeTestsSd_Sq8Vector2DV.bridgeJSLift(callback)) + return 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 { @@ -10692,101 +11531,649 @@ public func _bjs_Container_location_set(_ _self: UnsafeMutableRawPointer) -> Voi Container.bridgeJSLiftParameter(_self).location = DataPoint.bridgeJSLiftParameter() #else fatalError("Only available on WebAssembly") - #endif + #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, _BridgedSwiftProtocolExportable { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque())))) + } + consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { + _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque()) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Container_wrap") +fileprivate func _bjs_Container_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Container_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_Container_wrap_extern(pointer) +} + +@_expose(wasm, "bjs_LeakCheck_init") +@_cdecl("bjs_LeakCheck_init") +public func _bjs_LeakCheck_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = LeakCheck() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_LeakCheck_deinit") +@_cdecl("bjs_LeakCheck_deinit") +public func _bjs_LeakCheck_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension LeakCheck: ConvertibleToJSValue, _BridgedSwiftHeapObject, _BridgedSwiftProtocolExportable { + public var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_LeakCheck_wrap(Unmanaged.passRetained(self).toOpaque())))) + } + public consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { + _bjs_LeakCheck_wrap(Unmanaged.passRetained(self).toOpaque()) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_LeakCheck_wrap") +fileprivate func _bjs_LeakCheck_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_LeakCheck_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_LeakCheck_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_LeakCheck_wrap_extern(pointer) +} + +@JSFunction func Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_reject_BridgeJSRuntimeTests") +fileprivate func promise_reject_BridgeJSRuntimeTests_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void +#else +fileprivate func promise_reject_BridgeJSRuntimeTests_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_reject_BridgeJSRuntimeTests(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + return promise_reject_BridgeJSRuntimeTests_extern(promise, valueKind, valuePayload1, valuePayload2) +} + +func _$Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueKind, valuePayload1, valuePayload2) = value.bridgeJSLowerParameter() + promise_reject_BridgeJSRuntimeTests(promiseValue, valueKind, valuePayload1, valuePayload2) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_SS(_ promise: JSObject, _ value: String) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_SS") +fileprivate func promise_resolve_BridgeJSRuntimeTests_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_SS(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_SS_extern(promise, valueBytes, valueLength) +} + +func _$Promise_resolve_SS(_ promise: JSObject, _ value: String) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + promise_resolve_BridgeJSRuntimeTests_SS(promiseValue, valueBytes, valueLength) + } + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_y(_ promise: JSObject) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_y") +fileprivate func promise_resolve_BridgeJSRuntimeTests_y_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_y_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_y(_ promise: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_y_extern(promise) +} + +func _$Promise_resolve_y(_ promise: JSObject) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_y(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Si(_ promise: JSObject, _ value: Int) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Si") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Si_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Si_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Si(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Si_extern(promise, value) +} + +func _$Promise_resolve_Si(_ promise: JSObject, _ value: Int) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Si(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sf(_ promise: JSObject, _ value: Float) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sf") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sf_extern(_ promise: Int32, _ value: Float32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sf_extern(_ promise: Int32, _ value: Float32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sf(_ promise: Int32, _ value: Float32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sf_extern(promise, value) +} + +func _$Promise_resolve_Sf(_ promise: JSObject, _ value: Float) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sf(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sd(_ promise: JSObject, _ value: Double) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sd") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sd_extern(_ promise: Int32, _ value: Float64) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sd_extern(_ promise: Int32, _ value: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sd(_ promise: Int32, _ value: Float64) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sd_extern(promise, value) +} + +func _$Promise_resolve_Sd(_ promise: JSObject, _ value: Double) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sd(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sb(_ promise: JSObject, _ value: Bool) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sb") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sb_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sb_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sb(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sb_extern(promise, value) +} + +func _$Promise_resolve_Sb(_ promise: JSObject, _ value: Bool) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sb(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_7GreeterC(_ promise: JSObject, _ value: Greeter) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_7GreeterC") +fileprivate func promise_resolve_BridgeJSRuntimeTests_7GreeterC_extern(_ promise: Int32, _ value: UnsafeMutableRawPointer) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_7GreeterC_extern(_ promise: Int32, _ value: UnsafeMutableRawPointer) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_7GreeterC(_ promise: Int32, _ value: UnsafeMutableRawPointer) -> Void { + return promise_resolve_BridgeJSRuntimeTests_7GreeterC_extern(promise, value) +} + +func _$Promise_resolve_7GreeterC(_ promise: JSObject, _ value: Greeter) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valuePointer = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_7GreeterC(promiseValue, valuePointer) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_8JSObjectC(_ promise: JSObject, _ value: JSObject) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_8JSObjectC") +fileprivate func promise_resolve_BridgeJSRuntimeTests_8JSObjectC_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_8JSObjectC_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_8JSObjectC(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_8JSObjectC_extern(promise, value) +} + +func _$Promise_resolve_8JSObjectC(_ promise: JSObject, _ value: JSObject) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_8JSObjectC(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_5ThemeO(_ promise: JSObject, _ value: Theme) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_5ThemeO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(promise, valueBytes, valueLength) +} + +func _$Promise_resolve_5ThemeO(_ promise: JSObject, _ value: Theme) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + promise_resolve_BridgeJSRuntimeTests_5ThemeO(promiseValue, valueBytes, valueLength) + } + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_9DirectionO(_ promise: JSObject, _ value: Direction) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_9DirectionO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_9DirectionO_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_9DirectionO_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_9DirectionO(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_9DirectionO_extern(promise, value) +} + +func _$Promise_resolve_9DirectionO(_ promise: JSObject, _ value: Direction) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_9DirectionO(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq5ThemeO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(promise, valueIsSome, valueBytes, valueLength) +} + +func _$Promise_resolve_Sq5ThemeO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in + promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO(promiseValue, valueIsSome, valueBytes, valueLength) + } + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq9DirectionO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sq9DirectionO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq9DirectionO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq9DirectionO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq9DirectionO(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sq9DirectionO_extern(promise, valueIsSome, valueValue) +} + +func _$Promise_resolve_Sq9DirectionO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sq9DirectionO(promiseValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sa9DirectionO(_ promise: JSObject, _ value: [Direction]) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sa9DirectionO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa9DirectionO_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa9DirectionO_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa9DirectionO(_ promise: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sa9DirectionO_extern(promise) +} + +func _$Promise_resolve_Sa9DirectionO(_ promise: JSObject, _ value: [Direction]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sa9DirectionO(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_SD9DirectionO(_ promise: JSObject, _ value: [String: Direction]) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_SD9DirectionO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_SD9DirectionO_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_SD9DirectionO_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_SD9DirectionO(_ promise: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_SD9DirectionO_extern(promise) +} + +func _$Promise_resolve_SD9DirectionO(_ promise: JSObject, _ value: [String: Direction]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_SD9DirectionO(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sa5ThemeO(_ promise: JSObject, _ value: [Theme]) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sa5ThemeO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa5ThemeO_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa5ThemeO_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa5ThemeO(_ promise: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sa5ThemeO_extern(promise) +} + +func _$Promise_resolve_Sa5ThemeO(_ promise: JSObject, _ value: [Theme]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sa5ThemeO(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_SD5ThemeO(_ promise: JSObject, _ value: [String: Theme]) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_SD5ThemeO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_SD5ThemeO_extern(_ promise: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_SD5ThemeO_extern(_ promise: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_SD5ThemeO(_ promise: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_SD5ThemeO_extern(promise) +} + +func _$Promise_resolve_SD5ThemeO(_ promise: JSObject, _ value: [String: Theme]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_SD5ThemeO(promiseValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_8FileSizeO(_ promise: JSObject, _ value: FileSize) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_8FileSizeO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_8FileSizeO_extern(_ promise: Int32, _ value: Int64) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_8FileSizeO_extern(_ promise: Int32, _ value: Int64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_8FileSizeO(_ promise: Int32, _ value: Int64) -> Void { + return promise_resolve_BridgeJSRuntimeTests_8FileSizeO_extern(promise, value) +} + +func _$Promise_resolve_8FileSizeO(_ promise: JSObject, _ value: FileSize) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueValue = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_8FileSizeO(promiseValue, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq8FileSizeO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sq8FileSizeO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq8FileSizeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int64) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq8FileSizeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq8FileSizeO(_ promise: Int32, _ valueIsSome: Int32, _ valueValue: Int64) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sq8FileSizeO_extern(promise, valueIsSome, valueValue) +} + +func _$Promise_resolve_Sq8FileSizeO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sq8FileSizeO(promiseValue, valueIsSome, valueValue) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO_extern(promise, value) +} + +func _$Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueCaseId = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO(promiseValue, valueCaseId) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO_extern(promise, valueIsSome, valueCaseId) } -@_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 +func _$Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueIsSome, valueCaseId) = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO(promiseValue, valueIsSome, valueCaseId) + if let error = _swift_js_take_exception() { throw error } } -@_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 +@JSFunction func Promise_resolve_11PublicPointV(_ promise: JSObject, _ value: PublicPoint) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_11PublicPointV") +fileprivate func promise_resolve_BridgeJSRuntimeTests_11PublicPointV_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_11PublicPointV_extern(_ promise: Int32, _ value: Int32) -> Void { fatalError("Only available on WebAssembly") - #endif +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_11PublicPointV(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_11PublicPointV_extern(promise, value) } -@_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 +func _$Promise_resolve_11PublicPointV(_ promise: JSObject, _ value: PublicPoint) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueObjectId = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_11PublicPointV(promiseValue, valueObjectId) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_7ContactV(_ promise: JSObject, _ value: Contact) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_7ContactV") +fileprivate func promise_resolve_BridgeJSRuntimeTests_7ContactV_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_7ContactV_extern(_ promise: Int32, _ value: Int32) -> Void { fatalError("Only available on WebAssembly") - #endif +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_7ContactV(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_7ContactV_extern(promise, value) } -extension Container: ConvertibleToJSValue, _BridgedSwiftHeapObject, _BridgedSwiftProtocolExportable { - var jsValue: JSValue { - return .object(JSObject(id: UInt32(bitPattern: _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque())))) - } - consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { - _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque()) - } +func _$Promise_resolve_7ContactV(_ promise: JSObject, _ value: Contact) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueObjectId = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_7ContactV(promiseValue, valueObjectId) + if let error = _swift_js_take_exception() { throw error } } +@JSFunction func Promise_resolve_Sa11PublicPointV(_ promise: JSObject, _ value: [PublicPoint]) throws(JSException) + #if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Container_wrap") -fileprivate func _bjs_Container_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sa11PublicPointV") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa11PublicPointV_extern(_ promise: Int32) -> Void #else -fileprivate func _bjs_Container_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa11PublicPointV_extern(_ promise: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { - return _bjs_Container_wrap_extern(pointer) +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sa11PublicPointV(_ promise: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sa11PublicPointV_extern(promise) } -@_expose(wasm, "bjs_LeakCheck_init") -@_cdecl("bjs_LeakCheck_init") -public func _bjs_LeakCheck_init() -> UnsafeMutableRawPointer { - #if arch(wasm32) - let ret = LeakCheck() - return ret.bridgeJSLowerReturn() - #else - fatalError("Only available on WebAssembly") - #endif +func _$Promise_resolve_Sa11PublicPointV(_ promise: JSObject, _ value: [PublicPoint]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sa11PublicPointV(promiseValue) + if let error = _swift_js_take_exception() { throw error } } -@_expose(wasm, "bjs_LeakCheck_deinit") -@_cdecl("bjs_LeakCheck_deinit") -public func _bjs_LeakCheck_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { - #if arch(wasm32) - Unmanaged.fromOpaque(pointer).release() - #else +@JSFunction func Promise_resolve_Sq11PublicPointV(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sq11PublicPointV") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq11PublicPointV_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq11PublicPointV_extern(_ promise: Int32, _ value: Int32) -> Void { fatalError("Only available on WebAssembly") - #endif +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq11PublicPointV(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sq11PublicPointV_extern(promise, value) } -extension LeakCheck: ConvertibleToJSValue, _BridgedSwiftHeapObject, _BridgedSwiftProtocolExportable { - public var jsValue: JSValue { - return .object(JSObject(id: UInt32(bitPattern: _bjs_LeakCheck_wrap(Unmanaged.passRetained(self).toOpaque())))) - } - public consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { - _bjs_LeakCheck_wrap(Unmanaged.passRetained(self).toOpaque()) - } +func _$Promise_resolve_Sq11PublicPointV(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueIsSome = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sq11PublicPointV(promiseValue, valueIsSome) + if let error = _swift_js_take_exception() { throw error } } +@JSFunction func Promise_resolve_SD11PublicPointV(_ promise: JSObject, _ value: [String: PublicPoint]) throws(JSException) + #if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_LeakCheck_wrap") -fileprivate func _bjs_LeakCheck_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_SD11PublicPointV") +fileprivate func promise_resolve_BridgeJSRuntimeTests_SD11PublicPointV_extern(_ promise: Int32) -> Void #else -fileprivate func _bjs_LeakCheck_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { +fileprivate func promise_resolve_BridgeJSRuntimeTests_SD11PublicPointV_extern(_ promise: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func _bjs_LeakCheck_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { - return _bjs_LeakCheck_wrap_extern(pointer) +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_SD11PublicPointV(_ promise: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_SD11PublicPointV_extern(promise) +} + +func _$Promise_resolve_SD11PublicPointV(_ promise: JSObject, _ value: [String: PublicPoint]) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let _ = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_SD11PublicPointV(promiseValue) + if let error = _swift_js_take_exception() { throw error } } #if arch(wasm32) @@ -11308,6 +12695,30 @@ fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_exter return bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_extern(resolveRef, rejectRef, vBytes, vLength) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static") +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ v: Int32) -> Void +#else +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ v: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static(_ resolveRef: Int32, _ rejectRef: Int32, _ v: Int32) -> Void { + return bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static_extern(resolveRef, rejectRef, v) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static") +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vCaseId: Int32) -> Void +#else +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vCaseId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vCaseId: Int32) -> Void { + return bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static_extern(resolveRef, rejectRef, vIsSome, vCaseId) +} + func _$AsyncImportImports_jsAsyncRoundTripVoid() async throws(JSException) -> Void { try await _bjs_awaitPromise(makeResolveClosure: { JSTypedClosure<() -> Void>($0) @@ -11429,6 +12840,30 @@ func _$AsyncImportImports_jsAsyncRoundTripFeatureFlag(_ v: FeatureFlag) async th return resolved } +func _$AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum(_ v: AsyncImportedPayloadResult) async throws(JSException) -> AsyncImportedPayloadResult { + let resolved = try await _bjs_awaitPromise(makeResolveClosure: { + JSTypedClosure<(sending AsyncImportedPayloadResult) -> Void>($0) + }, makeRejectClosure: { + JSTypedClosure<(sending JSValue) -> Void>($0) + }) { resolveRef, rejectRef in + let vCaseId = v.bridgeJSLowerParameter() + bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static(resolveRef, rejectRef, vCaseId) + } + return resolved +} + +func _$AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum(_ v: Optional) async throws(JSException) -> Optional { + let resolved = try await _bjs_awaitPromise(makeResolveClosure: { + JSTypedClosure<(sending Optional) -> Void>($0) + }, makeRejectClosure: { + JSTypedClosure<(sending JSValue) -> Void>($0) + }) { resolveRef, rejectRef in + let (vIsSome, vCaseId) = v.bridgeJSLowerParameter() + bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static(resolveRef, rejectRef, vIsSome, vCaseId) + } + return resolved +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyVoid_static") fileprivate func bjs_ClosureSupportImports_jsApplyVoid_static_extern(_ callback: Int32) -> Void @@ -12945,6 +14380,69 @@ func _$Animal_getIsCat(_ self: JSObject) throws(JSException) -> Bool { return Bool.bridgeJSLiftReturn(ret) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripLightColor") +fileprivate func bjs_jsRoundTripLightColor_extern(_ value: Int32) -> Int32 +#else +fileprivate func bjs_jsRoundTripLightColor_extern(_ value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_jsRoundTripLightColor(_ value: Int32) -> Int32 { + return bjs_jsRoundTripLightColor_extern(value) +} + +func _$jsRoundTripLightColor(_ value: LightColor) throws(JSException) -> LightColor { + let valueValue = value.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripLightColor(valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return LightColor.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripImportedPayloadSignal") +fileprivate func bjs_jsRoundTripImportedPayloadSignal_extern(_ value: Int32) -> Int32 +#else +fileprivate func bjs_jsRoundTripImportedPayloadSignal_extern(_ value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_jsRoundTripImportedPayloadSignal(_ value: Int32) -> Int32 { + return bjs_jsRoundTripImportedPayloadSignal_extern(value) +} + +func _$jsRoundTripImportedPayloadSignal(_ value: ImportedPayloadSignal) throws(JSException) -> ImportedPayloadSignal { + let valueCaseId = value.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripImportedPayloadSignal(valueCaseId) + if let error = _swift_js_take_exception() { + throw error + } + return ImportedPayloadSignal.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripOptionalImportedPayloadSignal") +fileprivate func bjs_jsRoundTripOptionalImportedPayloadSignal_extern(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 +#else +fileprivate func bjs_jsRoundTripOptionalImportedPayloadSignal_extern(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_jsRoundTripOptionalImportedPayloadSignal(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 { + return bjs_jsRoundTripOptionalImportedPayloadSignal_extern(valueIsSome, valueCaseId) +} + +func _$jsRoundTripOptionalImportedPayloadSignal(_ value: Optional) throws(JSException) -> Optional { + let (valueIsSome, valueCaseId) = value.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripOptionalImportedPayloadSignal(valueIsSome, valueCaseId) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsTranslatePoint") fileprivate func bjs_jsTranslatePoint_extern(_ point: Int32, _ dx: Int32, _ dy: Int32) -> Int32 @@ -12968,6 +14466,27 @@ func _$jsTranslatePoint(_ point: Point, _ dx: Int, _ dy: Int) throws(JSException return Point.bridgeJSLiftReturn(ret) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripOptionalPoint") +fileprivate func bjs_jsRoundTripOptionalPoint_extern(_ point: Int32) -> Void +#else +fileprivate func bjs_jsRoundTripOptionalPoint_extern(_ point: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_jsRoundTripOptionalPoint(_ point: Int32) -> Void { + return bjs_jsRoundTripOptionalPoint_extern(point) +} + +func _$jsRoundTripOptionalPoint(_ point: Optional) throws(JSException) -> Optional { + let pointIsSome = point.bridgeJSLowerParameter() + bjs_jsRoundTripOptionalPoint(pointIsSome) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn() +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_IntegerTypesSupportImports_jsRoundTripInt_static") fileprivate func bjs_IntegerTypesSupportImports_jsRoundTripInt_static_extern(_ v: Int32) -> Int32 @@ -13391,6 +14910,129 @@ func _$JSClassSupportImports_makeJSClassWithArrayMembers(_ numbers: [Int], _ lab return JSClassWithArrayMembers.bridgeJSLiftReturn(ret) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JSTypedArrayImports_jsCreateUint8Array_static") +fileprivate func bjs_JSTypedArrayImports_jsCreateUint8Array_static_extern() -> Int32 +#else +fileprivate func bjs_JSTypedArrayImports_jsCreateUint8Array_static_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSTypedArrayImports_jsCreateUint8Array_static() -> Int32 { + return bjs_JSTypedArrayImports_jsCreateUint8Array_static_extern() +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JSTypedArrayImports_jsRoundTripUint8Array_static") +fileprivate func bjs_JSTypedArrayImports_jsRoundTripUint8Array_static_extern(_ v: Int32) -> Int32 +#else +fileprivate func bjs_JSTypedArrayImports_jsRoundTripUint8Array_static_extern(_ v: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSTypedArrayImports_jsRoundTripUint8Array_static(_ v: Int32) -> Int32 { + return bjs_JSTypedArrayImports_jsRoundTripUint8Array_static_extern(v) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JSTypedArrayImports_jsRoundTripFloat32Array_static") +fileprivate func bjs_JSTypedArrayImports_jsRoundTripFloat32Array_static_extern(_ v: Int32) -> Int32 +#else +fileprivate func bjs_JSTypedArrayImports_jsRoundTripFloat32Array_static_extern(_ v: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSTypedArrayImports_jsRoundTripFloat32Array_static(_ v: Int32) -> Int32 { + return bjs_JSTypedArrayImports_jsRoundTripFloat32Array_static_extern(v) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JSTypedArrayImports_jsRoundTripFloat64Array_static") +fileprivate func bjs_JSTypedArrayImports_jsRoundTripFloat64Array_static_extern(_ v: Int32) -> Int32 +#else +fileprivate func bjs_JSTypedArrayImports_jsRoundTripFloat64Array_static_extern(_ v: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSTypedArrayImports_jsRoundTripFloat64Array_static(_ v: Int32) -> Int32 { + return bjs_JSTypedArrayImports_jsRoundTripFloat64Array_static_extern(v) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JSTypedArrayImports_jsRoundTripInt32Array_static") +fileprivate func bjs_JSTypedArrayImports_jsRoundTripInt32Array_static_extern(_ v: Int32) -> Int32 +#else +fileprivate func bjs_JSTypedArrayImports_jsRoundTripInt32Array_static_extern(_ v: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSTypedArrayImports_jsRoundTripInt32Array_static(_ v: Int32) -> Int32 { + return bjs_JSTypedArrayImports_jsRoundTripInt32Array_static_extern(v) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JSTypedArrayImports_runJsTypedArrayTests_static") +fileprivate func bjs_JSTypedArrayImports_runJsTypedArrayTests_static_extern() -> Void +#else +fileprivate func bjs_JSTypedArrayImports_runJsTypedArrayTests_static_extern() -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_JSTypedArrayImports_runJsTypedArrayTests_static() -> Void { + return bjs_JSTypedArrayImports_runJsTypedArrayTests_static_extern() +} + +func _$JSTypedArrayImports_jsCreateUint8Array() throws(JSException) -> JSUint8Array { + let ret = bjs_JSTypedArrayImports_jsCreateUint8Array_static() + if let error = _swift_js_take_exception() { + throw error + } + return JSUint8Array.bridgeJSLiftReturn(ret) +} + +func _$JSTypedArrayImports_jsRoundTripUint8Array(_ v: JSUint8Array) throws(JSException) -> JSUint8Array { + let vValue = v.bridgeJSLowerParameter() + let ret = bjs_JSTypedArrayImports_jsRoundTripUint8Array_static(vValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSUint8Array.bridgeJSLiftReturn(ret) +} + +func _$JSTypedArrayImports_jsRoundTripFloat32Array(_ v: JSFloat32Array) throws(JSException) -> JSFloat32Array { + let vValue = v.bridgeJSLowerParameter() + let ret = bjs_JSTypedArrayImports_jsRoundTripFloat32Array_static(vValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSFloat32Array.bridgeJSLiftReturn(ret) +} + +func _$JSTypedArrayImports_jsRoundTripFloat64Array(_ v: JSFloat64Array) throws(JSException) -> JSFloat64Array { + let vValue = v.bridgeJSLowerParameter() + let ret = bjs_JSTypedArrayImports_jsRoundTripFloat64Array_static(vValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSFloat64Array.bridgeJSLiftReturn(ret) +} + +func _$JSTypedArrayImports_jsRoundTripInt32Array(_ v: JSInt32Array) throws(JSException) -> JSInt32Array { + let vValue = v.bridgeJSLowerParameter() + let ret = bjs_JSTypedArrayImports_jsRoundTripInt32Array_static(vValue) + if let error = _swift_js_take_exception() { + throw error + } + return JSInt32Array.bridgeJSLiftReturn(ret) +} + +func _$JSTypedArrayImports_runJsTypedArrayTests() throws(JSException) -> Void { + bjs_JSTypedArrayImports_runJsTypedArrayTests_static() + if let error = _swift_js_take_exception() { + throw error + } +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_MyJSClassInternal_init") fileprivate func bjs_MyJSClassInternal_init_extern() -> Int32 @@ -13642,6 +15284,18 @@ fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDic return bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined_static_extern(v) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static") +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static_extern(_ valueIsSome: Int32, _ valueValue: Int32) -> Void +#else +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static_extern(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static(_ valueIsSome: Int32, _ valueValue: Int32) -> Void { + return bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static_extern(valueIsSome, valueValue) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_runJsOptionalSupportTests_static") fileprivate func bjs_OptionalSupportImports_runJsOptionalSupportTests_static_extern() -> Void @@ -13728,6 +15382,15 @@ func _$OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefin return JSUndefinedOr<[String: String]>.bridgeJSLiftReturn() } +func _$OptionalSupportImports_jsRoundTripOptionalJSObjectNull(_ value: Optional) throws(JSException) -> Optional { + let (valueIsSome, valueValue) = value.bridgeJSLowerParameter() + bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static(valueIsSome, valueValue) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn() +} + func _$OptionalSupportImports_runJsOptionalSupportTests() throws(JSException) -> Void { bjs_OptionalSupportImports_runJsOptionalSupportTests_static() if let error = _swift_js_take_exception() { diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index dd4362fc1..a51e6bafd 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -908,6 +908,46 @@ } } } + }, + { + "abiName" : "bjs_Calculator_asyncMakePoint", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncMakePoint", + "parameters" : [ + { + "label" : "x", + "name" : "x", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } } ], "name" : "Calculator", @@ -4057,6 +4097,99 @@ "returnType" : { "string" : { + } + } + }, + { + "abiName" : "bjs_TextProcessor_processVector", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processVector", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_8Vector2DV", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Vector2D" + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_TextProcessor_processOptionalVector", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processOptionalVector", + "parameters" : [ + { + "label" : "_", + "name" : "callback", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSd_Sq8Vector2DV", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "double" : { + + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Vector2D" + } + }, + "_1" : "null" + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false + } + } + } + ], + "returnType" : { + "string" : { + } } } @@ -6417,6 +6550,53 @@ "swiftCallName" : "ArraySupportExports", "tsFullPath" : "ArraySupportExports" }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "AsyncImportedPayloadResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AsyncImportedPayloadResult", + "tsFullPath" : "AsyncImportedPayloadResult" + }, { "cases" : [ @@ -7582,6 +7762,53 @@ "swiftCallName" : "TSTheme", "tsFullPath" : "TSTheme" }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "AsyncPayloadResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AsyncPayloadResult", + "tsFullPath" : "AsyncPayloadResult" + }, { "cases" : [ @@ -9072,90 +9299,263 @@ ], "emitStyle" : "const", - "name" : "IntegerTypesSupportExports", + "name" : "NestedStructGroupA", "staticMethods" : [ { - "abiName" : "bjs_IntegerTypesSupportExports_static_roundTripInt", + "abiName" : "bjs_NestedStructGroupA_static_roundtripMetadata", "effects" : { "isAsync" : false, "isStatic" : true, "isThrows" : false }, - "name" : "roundTripInt", + "name" : "roundtripMetadata", "namespace" : [ - "IntegerTypesSupportExports" + "NestedStructGroupA" ], "parameters" : [ { "label" : "_", - "name" : "v", + "name" : "m", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "swiftStruct" : { + "_0" : "NestedStructGroupA.Metadata" } } } ], "returnType" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "swiftStruct" : { + "_0" : "NestedStructGroupA.Metadata" } }, "staticContext" : { "namespaceEnum" : { - "_0" : "IntegerTypesSupportExports" + "_0" : "NestedStructGroupA" } } - }, + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "NestedStructGroupA", + "tsFullPath" : "NestedStructGroupA" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "NestedStructGroupB", + "staticMethods" : [ { - "abiName" : "bjs_IntegerTypesSupportExports_static_roundTripUInt", + "abiName" : "bjs_NestedStructGroupB_static_roundtripMetadata", "effects" : { "isAsync" : false, "isStatic" : true, "isThrows" : false }, - "name" : "roundTripUInt", + "name" : "roundtripMetadata", "namespace" : [ - "IntegerTypesSupportExports" + "NestedStructGroupB" ], "parameters" : [ { "label" : "_", - "name" : "v", + "name" : "m", "type" : { - "integer" : { - "_0" : { - "isSigned" : false, - "width" : "word" - } + "swiftStruct" : { + "_0" : "NestedStructGroupB.Metadata" } } } ], "returnType" : { - "integer" : { - "_0" : { - "isSigned" : false, - "width" : "word" - } + "swiftStruct" : { + "_0" : "NestedStructGroupB.Metadata" } }, "staticContext" : { "namespaceEnum" : { - "_0" : "IntegerTypesSupportExports" + "_0" : "NestedStructGroupB" } } - }, - { - "abiName" : "bjs_IntegerTypesSupportExports_static_roundTripInt8", - "effects" : { - "isAsync" : false, + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "NestedStructGroupB", + "tsFullPath" : "NestedStructGroupB" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "red" + }, + { + "associatedValues" : [ + + ], + "name" : "yellow" + }, + { + "associatedValues" : [ + + ], + "name" : "green" + } + ], + "emitStyle" : "const", + "name" : "LightColor", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "LightColor", + "tsFullPath" : "LightColor" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "start" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "stop" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "ImportedPayloadSignal", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "ImportedPayloadSignal", + "tsFullPath" : "ImportedPayloadSignal" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "IntegerTypesSupportExports", + "staticMethods" : [ + { + "abiName" : "bjs_IntegerTypesSupportExports_static_roundTripInt", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundTripInt", + "namespace" : [ + "IntegerTypesSupportExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "returnType" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "IntegerTypesSupportExports" + } + } + }, + { + "abiName" : "bjs_IntegerTypesSupportExports_static_roundTripUInt", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundTripUInt", + "namespace" : [ + "IntegerTypesSupportExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "integer" : { + "_0" : { + "isSigned" : false, + "width" : "word" + } + } + } + } + ], + "returnType" : { + "integer" : { + "_0" : { + "isSigned" : false, + "width" : "word" + } + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "IntegerTypesSupportExports" + } + } + }, + { + "abiName" : "bjs_IntegerTypesSupportExports_static_roundTripInt8", + "effects" : { + "isAsync" : false, "isStatic" : true, "isThrows" : false }, @@ -9476,192 +9876,338 @@ ], "emitStyle" : "const", - "name" : "OptionalSupportExports", + "name" : "JSTypedArrayExports", "staticMethods" : [ { - "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalString", + "abiName" : "bjs_JSTypedArrayExports_static_roundTripUint8Array", "effects" : { "isAsync" : false, "isStatic" : true, "isThrows" : false }, - "name" : "roundTripOptionalString", + "name" : "roundTripUint8Array", "namespace" : [ - "OptionalSupportExports" + "JSTypedArrayExports" ], "parameters" : [ { "label" : "_", "name" : "v", "type" : { - "nullable" : { - "_0" : { - "string" : { - - } - }, - "_1" : "null" + "jsObject" : { + "_0" : "JSUint8Array" } } } ], "returnType" : { - "nullable" : { - "_0" : { - "string" : { - - } - }, - "_1" : "null" + "jsObject" : { + "_0" : "JSUint8Array" } }, "staticContext" : { "namespaceEnum" : { - "_0" : "OptionalSupportExports" + "_0" : "JSTypedArrayExports" } } }, { - "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalInt", + "abiName" : "bjs_JSTypedArrayExports_static_roundTripFloat32Array", "effects" : { "isAsync" : false, "isStatic" : true, "isThrows" : false }, - "name" : "roundTripOptionalInt", + "name" : "roundTripFloat32Array", "namespace" : [ - "OptionalSupportExports" + "JSTypedArrayExports" ], "parameters" : [ { "label" : "_", "name" : "v", "type" : { - "nullable" : { - "_0" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - }, - "_1" : "null" + "jsObject" : { + "_0" : "JSFloat32Array" } } } ], "returnType" : { - "nullable" : { - "_0" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - }, - "_1" : "null" + "jsObject" : { + "_0" : "JSFloat32Array" } }, "staticContext" : { "namespaceEnum" : { - "_0" : "OptionalSupportExports" + "_0" : "JSTypedArrayExports" } } }, { - "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalBool", + "abiName" : "bjs_JSTypedArrayExports_static_roundTripFloat64Array", "effects" : { "isAsync" : false, "isStatic" : true, "isThrows" : false }, - "name" : "roundTripOptionalBool", + "name" : "roundTripFloat64Array", "namespace" : [ - "OptionalSupportExports" + "JSTypedArrayExports" ], "parameters" : [ { "label" : "_", "name" : "v", "type" : { - "nullable" : { - "_0" : { - "bool" : { - - } - }, - "_1" : "null" + "jsObject" : { + "_0" : "JSFloat64Array" } } } ], "returnType" : { - "nullable" : { - "_0" : { - "bool" : { - - } - }, - "_1" : "null" + "jsObject" : { + "_0" : "JSFloat64Array" } }, "staticContext" : { "namespaceEnum" : { - "_0" : "OptionalSupportExports" + "_0" : "JSTypedArrayExports" } } }, { - "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalFloat", + "abiName" : "bjs_JSTypedArrayExports_static_roundTripInt32Array", "effects" : { "isAsync" : false, "isStatic" : true, "isThrows" : false }, - "name" : "roundTripOptionalFloat", + "name" : "roundTripInt32Array", "namespace" : [ - "OptionalSupportExports" + "JSTypedArrayExports" ], "parameters" : [ { "label" : "_", "name" : "v", "type" : { - "nullable" : { - "_0" : { - "float" : { - - } - }, - "_1" : "null" + "jsObject" : { + "_0" : "JSInt32Array" } } } ], "returnType" : { - "nullable" : { - "_0" : { - "float" : { - - } - }, - "_1" : "null" + "jsObject" : { + "_0" : "JSInt32Array" } }, "staticContext" : { "namespaceEnum" : { - "_0" : "OptionalSupportExports" + "_0" : "JSTypedArrayExports" } } - }, - { - "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalDouble", - "effects" : { - "isAsync" : false, - "isStatic" : true, - "isThrows" : false + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "JSTypedArrayExports", + "tsFullPath" : "JSTypedArrayExports" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "OptionalSupportExports", + "staticMethods" : [ + { + "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalString", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundTripOptionalString", + "namespace" : [ + "OptionalSupportExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "OptionalSupportExports" + } + } + }, + { + "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalInt", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundTripOptionalInt", + "namespace" : [ + "OptionalSupportExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + }, + "_1" : "null" + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "OptionalSupportExports" + } + } + }, + { + "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalBool", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundTripOptionalBool", + "namespace" : [ + "OptionalSupportExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "bool" : { + + } + }, + "_1" : "null" + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "OptionalSupportExports" + } + } + }, + { + "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalFloat", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundTripOptionalFloat", + "namespace" : [ + "OptionalSupportExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "float" : { + + } + }, + "_1" : "null" + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "OptionalSupportExports" + } + } + }, + { + "abiName" : "bjs_OptionalSupportExports_static_roundTripOptionalDouble", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false }, "name" : "roundTripOptionalDouble", "namespace" : [ @@ -11584,6 +12130,41 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalImportedClass", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalImportedClass", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "jsObject" : { + "_0" : "Foo" + } + }, + "_1" : "null" + } + } + }, { "abiName" : "bjs_throwsSwiftError", "effects" : { @@ -11731,6 +12312,23 @@ } } }, + { + "abiName" : "bjs_zeroArgAsyncThrows", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "zeroArgAsyncThrows", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, { "abiName" : "bjs_asyncRoundTripVoid", "effects" : { @@ -12134,72 +12732,456 @@ } }, { - "abiName" : "bjs_processDirection", + "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_asyncRoundTripTheme", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripTheme", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripDirection", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripDirection", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Direction" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalTheme", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripOptionalTheme", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalDirection", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripOptionalDirection", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripDirectionArray", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripDirectionArray", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + }, + { + "abiName" : "bjs_asyncRoundTripDirectionDict", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripDirectionDict", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "dictionary" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + }, + { + "abiName" : "bjs_asyncRoundTripThemeArray", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripThemeArray", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "array" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + }, + { + "abiName" : "bjs_asyncRoundTripThemeDict", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripThemeDict", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "dictionary" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + }, + { + "abiName" : "bjs_asyncRoundTripFileSize", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripFileSize", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + } + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalFileSize", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "processDirection", + "name" : "asyncRoundTripOptionalFileSize", "parameters" : [ { "label" : "_", - "name" : "input", + "name" : "v", "type" : { - "caseEnum" : { - "_0" : "Direction" + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + }, + "_1" : "null" } } } ], "returnType" : { - "caseEnum" : { - "_0" : "Status" + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + }, + "_1" : "null" } } }, { - "abiName" : "bjs_setTheme", + "abiName" : "bjs_asyncRoundTripAssociatedValueEnum", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "setTheme", + "name" : "asyncRoundTripAssociatedValueEnum", "parameters" : [ { "label" : "_", - "name" : "theme", + "name" : "v", "type" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" } } }, { - "abiName" : "bjs_getTheme", + "abiName" : "bjs_asyncRoundTripOptionalAssociatedValueEnum", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "getTheme", + "name" : "asyncRoundTripOptionalAssociatedValueEnum", "parameters" : [ - + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + }, + "_1" : "null" + } + } + } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + }, + "_1" : "null" } } }, @@ -13879,119 +14861,354 @@ } ] } - }, - "label" : "point", - "name" : "point", + }, + "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_asyncRoundTripPublicPoint", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripPublicPoint", + "parameters" : [ + { + "label" : "_", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripPublicPointThrows", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "asyncRoundTripPublicPointThrows", + "parameters" : [ + { + "label" : "_", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + }, + { + "abiName" : "bjs_asyncStructOrThrow", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "asyncStructOrThrow", + "parameters" : [ + { + "label" : "_", + "name" : "shouldThrow", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + }, + { + "abiName" : "bjs_asyncCombinePublicPoints", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncCombinePublicPoints", + "parameters" : [ + { + "label" : "_", + "name" : "a", + "type" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + }, + { + "label" : "_", + "name" : "b", "type" : { "swiftStruct" : { - "_0" : "DataPoint" + "_0" : "PublicPoint" } } } ], "returnType" : { - "string" : { - + "swiftStruct" : { + "_0" : "PublicPoint" } } }, { - "abiName" : "bjs_cartToJSObject", + "abiName" : "bjs_asyncRoundTripContact", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "cartToJSObject", + "name" : "asyncRoundTripContact", "parameters" : [ { "label" : "_", - "name" : "cart", + "name" : "contact", "type" : { "swiftStruct" : { - "_0" : "CopyableCart" + "_0" : "Contact" } } } ], "returnType" : { - "jsObject" : { - + "swiftStruct" : { + "_0" : "Contact" } } }, { - "abiName" : "bjs_nestedCartToJSObject", + "abiName" : "bjs_asyncRoundTripPublicPointArray", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "nestedCartToJSObject", + "name" : "asyncRoundTripPublicPointArray", "parameters" : [ { "label" : "_", - "name" : "cart", + "name" : "points", "type" : { - "swiftStruct" : { - "_0" : "CopyableNestedCart" + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } } } } ], "returnType" : { - "jsObject" : { - + "array" : { + "_0" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } } } }, { - "abiName" : "bjs_roundTripDataPoint", + "abiName" : "bjs_asyncRoundTripOptionalPublicPoint", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripDataPoint", + "name" : "asyncRoundTripOptionalPublicPoint", "parameters" : [ { "label" : "_", - "name" : "data", + "name" : "point", "type" : { - "swiftStruct" : { - "_0" : "DataPoint" + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + }, + "_1" : "null" } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "DataPoint" + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + }, + "_1" : "null" } } }, { - "abiName" : "bjs_roundTripPublicPoint", + "abiName" : "bjs_asyncRoundTripPublicPointDict", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripPublicPoint", + "name" : "asyncRoundTripPublicPointDict", "parameters" : [ { "label" : "_", - "name" : "point", + "name" : "points", "type" : { - "swiftStruct" : { - "_0" : "PublicPoint" + "dictionary" : { + "_0" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "PublicPoint" + "dictionary" : { + "_0" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } } } }, @@ -14797,6 +16014,85 @@ } ], "structs" : [ + { + "methods" : [ + + ], + "name" : "Metadata", + "namespace" : [ + "NestedStructGroupA" + ], + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "label", + "namespace" : [ + "NestedStructGroupA" + ], + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "count", + "namespace" : [ + "NestedStructGroupA" + ], + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "swiftCallName" : "NestedStructGroupA.Metadata" + }, + { + "methods" : [ + + ], + "name" : "Metadata", + "namespace" : [ + "NestedStructGroupB" + ], + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "tag", + "namespace" : [ + "NestedStructGroupB" + ], + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "value", + "namespace" : [ + "NestedStructGroupB" + ], + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "NestedStructGroupB.Metadata" + }, { "methods" : [ @@ -16410,7 +17706,9 @@ ], "types" : [ { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "id", @@ -16424,6 +17722,7 @@ }, "getters" : [ { + "accessLevel" : "internal", "name" : "id", "type" : { "string" : { @@ -16444,6 +17743,7 @@ ] }, { + "accessLevel" : "internal", "getters" : [ ], @@ -16456,6 +17756,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16489,6 +17790,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16526,6 +17828,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16557,6 +17860,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16588,6 +17892,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16619,6 +17924,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16650,6 +17956,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16681,6 +17988,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16712,6 +18020,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16759,6 +18068,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16800,6 +18110,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16841,6 +18152,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16882,6 +18194,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16923,6 +18236,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16964,6 +18278,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -16991,6 +18306,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17011,6 +18327,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17036,6 +18353,7 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -17048,6 +18366,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17064,6 +18383,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17087,6 +18407,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17110,6 +18431,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17133,6 +18455,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17166,6 +18489,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17199,6 +18523,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17230,6 +18555,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17261,6 +18587,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17292,6 +18619,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -17315,6 +18643,64 @@ "_1" : "String" } } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsAsyncRoundTripAssociatedValueEnum", + "parameters" : [ + { + "name" : "v", + "type" : { + "associatedValueEnum" : { + "_0" : "AsyncImportedPayloadResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "AsyncImportedPayloadResult" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsAsyncRoundTripOptionalAssociatedValueEnum", + "parameters" : [ + { + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncImportedPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncImportedPayloadResult" + } + }, + "_1" : "null" + } + } } ] } @@ -17326,6 +18712,7 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -17338,6 +18725,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17376,6 +18764,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17414,6 +18803,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17476,6 +18866,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17526,6 +18917,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17576,6 +18968,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17626,6 +19019,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17677,6 +19071,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17719,6 +19114,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17761,6 +19157,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17820,6 +19217,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17879,6 +19277,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17946,6 +19345,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -17984,6 +19384,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18027,6 +19428,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18065,6 +19467,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18081,6 +19484,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18100,6 +19504,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18125,6 +19530,7 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -18137,6 +19543,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18162,6 +19569,7 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -18174,6 +19582,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18211,6 +19620,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18242,6 +19652,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18273,6 +19684,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18304,6 +19716,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18335,6 +19748,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18383,7 +19797,9 @@ ], "types" : [ { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "value", @@ -18397,6 +19813,7 @@ }, "getters" : [ { + "accessLevel" : "internal", "name" : "value", "type" : { "string" : { @@ -18421,6 +19838,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18437,6 +19855,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18460,6 +19879,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18483,6 +19903,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18506,6 +19927,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18529,6 +19951,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18552,6 +19975,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18575,6 +19999,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18598,6 +20023,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18621,6 +20047,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18646,6 +20073,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -18662,6 +20090,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : true, "isStatic" : false, @@ -18685,6 +20114,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18702,6 +20132,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18728,6 +20159,7 @@ ], "globalGetters" : [ { + "accessLevel" : "internal", "from" : "global", "name" : "globalObject1", "type" : { @@ -18739,7 +20171,9 @@ ], "types" : [ { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "name", @@ -18761,6 +20195,7 @@ }, "getters" : [ { + "accessLevel" : "internal", "name" : "name", "type" : { "string" : { @@ -18769,6 +20204,7 @@ } }, { + "accessLevel" : "internal", "name" : "prefix", "type" : { "string" : { @@ -18779,6 +20215,7 @@ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18795,6 +20232,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18821,6 +20259,7 @@ "name" : "JsGreeter", "setters" : [ { + "accessLevel" : "internal", "functionName" : "name_set", "name" : "name", "type" : { @@ -18835,8 +20274,10 @@ ] }, { + "accessLevel" : "internal", "getters" : [ { + "accessLevel" : "internal", "name" : "temperature", "type" : { "double" : { @@ -18845,6 +20286,7 @@ } }, { + "accessLevel" : "internal", "name" : "description", "type" : { "string" : { @@ -18853,6 +20295,7 @@ } }, { + "accessLevel" : "internal", "name" : "humidity", "type" : { "double" : { @@ -18867,6 +20310,7 @@ "name" : "WeatherData", "setters" : [ { + "accessLevel" : "internal", "functionName" : "temperature_set", "name" : "temperature", "type" : { @@ -18876,6 +20320,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "description_set", "name" : "description", "type" : { @@ -18885,6 +20330,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "humidity_set", "name" : "humidity", "type" : { @@ -18899,7 +20345,9 @@ ] }, { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ ] @@ -18910,6 +20358,7 @@ "jsName" : "$WeirdClass", "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18936,7 +20385,9 @@ ] }, { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "value", @@ -18953,6 +20404,7 @@ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18975,6 +20427,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -18998,6 +20451,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19014,6 +20468,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19030,6 +20485,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19049,7 +20505,9 @@ ] }, { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "name", @@ -19080,6 +20538,7 @@ "from" : "global", "getters" : [ { + "accessLevel" : "internal", "name" : "name", "type" : { "string" : { @@ -19088,6 +20547,7 @@ } }, { + "accessLevel" : "internal", "name" : "age", "type" : { "double" : { @@ -19096,6 +20556,7 @@ } }, { + "accessLevel" : "internal", "name" : "isCat", "type" : { "bool" : { @@ -19106,6 +20567,7 @@ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19122,6 +20584,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19141,6 +20604,7 @@ "name" : "Animal", "setters" : [ { + "accessLevel" : "internal", "functionName" : "name_set", "name" : "name", "type" : { @@ -19148,35 +20612,127 @@ } } - }, + }, + { + "accessLevel" : "internal", + "functionName" : "age_set", + "name" : "age", + "type" : { + "double" : { + + } + } + }, + { + "accessLevel" : "internal", + "functionName" : "isCat_set", + "name" : "isCat", + "type" : { + "bool" : { + + } + } + } + ], + "staticMethods" : [ + + ] + } + ] + }, + { + "functions" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripLightColor", + "parameters" : [ + { + "name" : "value", + "type" : { + "caseEnum" : { + "_0" : "LightColor" + } + } + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "LightColor" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripImportedPayloadSignal", + "parameters" : [ { - "functionName" : "age_set", - "name" : "age", + "name" : "value", "type" : { - "double" : { - + "associatedValueEnum" : { + "_0" : "ImportedPayloadSignal" } } - }, + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ImportedPayloadSignal" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripOptionalImportedPayloadSignal", + "parameters" : [ { - "functionName" : "isCat_set", - "name" : "isCat", + "name" : "value", "type" : { - "bool" : { - + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ImportedPayloadSignal" + } + }, + "_1" : "null" } } } ], - "staticMethods" : [ - - ] + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ImportedPayloadSignal" + } + }, + "_1" : "null" + } + } } + ], + "types" : [ + ] }, { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19220,6 +20776,40 @@ "_0" : "Point" } } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripOptionalPoint", + "parameters" : [ + { + "name" : "point", + "type" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftStruct" : { + "_0" : "Point" + } + }, + "_1" : "null" + } + } } ], "types" : [ @@ -19232,6 +20822,7 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -19244,6 +20835,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19273,6 +20865,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19302,6 +20895,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19331,6 +20925,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19360,6 +20955,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19389,6 +20985,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19418,6 +21015,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19447,6 +21045,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19476,6 +21075,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19505,6 +21105,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19534,6 +21135,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19559,7 +21161,9 @@ ], "types" : [ { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ { "name" : "numbers", @@ -19592,6 +21196,7 @@ }, "getters" : [ { + "accessLevel" : "internal", "name" : "numbers", "type" : { "array" : { @@ -19607,6 +21212,7 @@ } }, { + "accessLevel" : "internal", "name" : "labels", "type" : { "array" : { @@ -19621,6 +21227,7 @@ ], "methods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19658,6 +21265,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19689,6 +21297,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19719,6 +21328,7 @@ "name" : "JSClassWithArrayMembers", "setters" : [ { + "accessLevel" : "internal", "functionName" : "numbers_set", "name" : "numbers", "type" : { @@ -19735,6 +21345,7 @@ } }, { + "accessLevel" : "internal", "functionName" : "labels_set", "name" : "labels", "type" : { @@ -19753,6 +21364,7 @@ ] }, { + "accessLevel" : "internal", "getters" : [ ], @@ -19765,6 +21377,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19816,7 +21429,161 @@ ], "types" : [ { + "accessLevel" : "internal", + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "JSTypedArrayImports", + "setters" : [ + + ], + "staticMethods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsCreateUint8Array", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + "_0" : "JSUint8Array" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripUint8Array", + "parameters" : [ + { + "name" : "v", + "type" : { + "jsObject" : { + "_0" : "JSUint8Array" + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "JSUint8Array" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripFloat32Array", + "parameters" : [ + { + "name" : "v", + "type" : { + "jsObject" : { + "_0" : "JSFloat32Array" + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "JSFloat32Array" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripFloat64Array", + "parameters" : [ + { + "name" : "v", + "type" : { + "jsObject" : { + "_0" : "JSFloat64Array" + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "JSFloat64Array" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripInt32Array", + "parameters" : [ + { + "name" : "v", + "type" : { + "jsObject" : { + "_0" : "JSInt32Array" + } + } + } + ], + "returnType" : { + "jsObject" : { + "_0" : "JSInt32Array" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "runJsTypedArrayTests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ] + } + ] + }, + { + "functions" : [ + + ], + "types" : [ + { + "accessLevel" : "internal", "constructor" : { + "accessLevel" : "internal", "parameters" : [ ] @@ -19837,7 +21604,9 @@ ] }, { + "accessLevel" : "public", "constructor" : { + "accessLevel" : "public", "parameters" : [ ] @@ -19858,7 +21627,9 @@ ] }, { + "accessLevel" : "package", "constructor" : { + "accessLevel" : "package", "parameters" : [ ] @@ -19883,6 +21654,7 @@ { "functions" : [ { + "accessLevel" : "package", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19899,6 +21671,7 @@ } }, { + "accessLevel" : "public", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19915,6 +21688,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19931,6 +21705,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19947,6 +21722,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -19973,6 +21749,7 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -19985,6 +21762,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20024,6 +21802,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20063,6 +21842,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20096,6 +21876,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20129,6 +21910,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20170,6 +21952,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20211,6 +21994,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20252,6 +22036,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20293,6 +22078,41 @@ } }, { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripOptionalJSObjectNull", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "jsObject" : { + + } + }, + "_1" : "null" + } + } + }, + { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20315,6 +22135,7 @@ { "functions" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20334,6 +22155,7 @@ ], "types" : [ { + "accessLevel" : "internal", "getters" : [ ], @@ -20346,6 +22168,7 @@ ], "staticMethods" : [ { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20369,6 +22192,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20392,6 +22216,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20425,6 +22250,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20448,6 +22274,7 @@ } }, { + "accessLevel" : "internal", "effects" : { "isAsync" : false, "isStatic" : false, @@ -20481,5 +22308,8 @@ } ] }, - "moduleName" : "BridgeJSRuntimeTests" + "moduleName" : "BridgeJSRuntimeTests", + "usedExternalModules" : [ + + ] } \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift index 8f02af2ef..9cf77ed9d 100644 --- a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift @@ -1,6 +1,26 @@ import XCTest import JavaScriptKit +@JS enum LightColor { + case red + case yellow + case green +} + +@JS enum ImportedPayloadSignal: Equatable { + case start(String) + case stop(Int) + case idle +} + +@JSFunction func jsRoundTripLightColor(_ value: LightColor) throws(JSException) -> LightColor +@JSFunction func jsRoundTripImportedPayloadSignal( + _ value: ImportedPayloadSignal +) throws(JSException) -> ImportedPayloadSignal +@JSFunction func jsRoundTripOptionalImportedPayloadSignal( + _ value: ImportedPayloadSignal? +) throws(JSException) -> ImportedPayloadSignal? + class ImportAPITests: XCTestCase { func testRoundTripVoid() throws { try jsRoundTripVoid() @@ -59,6 +79,42 @@ class ImportAPITests: XCTestCase { } } + func testRoundTripOptionalStruct() throws { + let p = try jsRoundTripOptionalPoint(Point(x: 3, y: 4)) + XCTAssertEqual(p?.x, 3) + XCTAssertEqual(p?.y, 4) + XCTAssertNil(try jsRoundTripOptionalPoint(nil)) + } + + func testRoundTripCaseEnum() throws { + for v in [LightColor.red, .yellow, .green] { + try XCTAssertEqual(jsRoundTripLightColor(v), v) + } + } + + func testRoundTripAssociatedValueEnum() throws { + let values: [ImportedPayloadSignal] = [ + .start("go"), + .stop(42), + .idle, + ] + for value in values { + try XCTAssertEqual(jsRoundTripImportedPayloadSignal(value), value) + } + } + + func testRoundTripOptionalAssociatedValueEnum() throws { + let values: [ImportedPayloadSignal?] = [ + .some(.start("go")), + .some(.stop(42)), + .some(.idle), + nil, + ] + for value in values { + try XCTAssertEqual(jsRoundTripOptionalImportedPayloadSignal(value), value) + } + } + func ensureThrows(_ f: (Bool) throws(JSException) -> T) throws { do { _ = try f(true) diff --git a/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift b/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift index 41929772e..f981a5e01 100644 --- a/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift +++ b/Tests/BridgeJSRuntimeTests/ImportStructAPIs.swift @@ -7,3 +7,5 @@ struct Point { } @JSFunction func jsTranslatePoint(_ point: Point, dx: Int, dy: Int) throws(JSException) -> Point + +@JSFunction func jsRoundTripOptionalPoint(_ point: Point?) throws(JSException) -> Point? diff --git a/Tests/BridgeJSRuntimeTests/JSTypedArrayTests.swift b/Tests/BridgeJSRuntimeTests/JSTypedArrayTests.swift new file mode 100644 index 000000000..25045ecc8 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JSTypedArrayTests.swift @@ -0,0 +1,53 @@ +import XCTest +import JavaScriptKit + +@JS enum JSTypedArrayExports { + @JS static func roundTripUint8Array(_ v: JSUint8Array) -> JSUint8Array { v } + @JS static func roundTripFloat32Array(_ v: JSFloat32Array) -> JSFloat32Array { v } + @JS static func roundTripFloat64Array(_ v: JSFloat64Array) -> JSFloat64Array { v } + @JS static func roundTripInt32Array(_ v: JSInt32Array) -> JSInt32Array { v } +} + +@JSClass struct JSTypedArrayImports { + @JSFunction static func jsCreateUint8Array() throws(JSException) -> JSUint8Array + @JSFunction static func jsRoundTripUint8Array(_ v: JSUint8Array) throws(JSException) -> JSUint8Array + @JSFunction static func jsRoundTripFloat32Array(_ v: JSFloat32Array) throws(JSException) -> JSFloat32Array + @JSFunction static func jsRoundTripFloat64Array(_ v: JSFloat64Array) throws(JSException) -> JSFloat64Array + @JSFunction static func jsRoundTripInt32Array(_ v: JSInt32Array) throws(JSException) -> JSInt32Array + @JSFunction static func runJsTypedArrayTests() throws(JSException) +} + +final class JSTypedArrayTests: XCTestCase { + func testRunJsTypedArrayTests() throws { + try JSTypedArrayImports.runJsTypedArrayTests() + } + + func testRoundTripUint8Array() throws { + let arr = JSUint8Array([1, 2, 3, 255]) + let result = try JSTypedArrayImports.jsRoundTripUint8Array(arr) + XCTAssertEqual(result.length, 4) + } + + func testCreateUint8Array() throws { + let result = try JSTypedArrayImports.jsCreateUint8Array() + XCTAssertEqual(result.length, 3) + } + + func testRoundTripFloat32Array() throws { + let arr = JSFloat32Array([1.0, 2.5, 3.0]) + let result = try JSTypedArrayImports.jsRoundTripFloat32Array(arr) + XCTAssertEqual(result.length, 3) + } + + func testRoundTripFloat64Array() throws { + let arr = JSFloat64Array([1.0, 2.5, 3.14159]) + let result = try JSTypedArrayImports.jsRoundTripFloat64Array(arr) + XCTAssertEqual(result.length, 3) + } + + func testRoundTripInt32Array() throws { + let arr = JSInt32Array([1, -2, 2_147_483_647]) + let result = try JSTypedArrayImports.jsRoundTripInt32Array(arr) + XCTAssertEqual(result.length, 3) + } +} diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/AsyncImportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/AsyncImportTests.mjs index f64531d4a..9be7af1be 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/AsyncImportTests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/AsyncImportTests.mjs @@ -1,6 +1,7 @@ // @ts-check import assert from 'node:assert'; +import { ThemeValues, DirectionValues, FileSizeValues, AsyncPayloadResultValues } from '../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; /** * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["AsyncImportImports"]} @@ -37,10 +38,107 @@ export function getImports(importsContext) { jsAsyncRoundTripFeatureFlag: (v) => { return Promise.resolve(v); }, + jsAsyncRoundTripAssociatedValueEnum: (v) => { + return Promise.resolve(v); + }, + jsAsyncRoundTripOptionalAssociatedValueEnum: (v) => { + return Promise.resolve(v); + }, }; } /** @param {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ export async function runAsyncWorksTests(exports) { await exports.asyncRoundTripVoid(); + + const asyncPoint = { x: 7, y: 11 }; + assert.deepEqual(await exports.asyncRoundTripPublicPoint(asyncPoint), asyncPoint); + assert.deepEqual(await exports.asyncRoundTripPublicPointThrows(asyncPoint), asyncPoint); + + const [c1, c2] = await Promise.all([ + exports.asyncRoundTripPublicPoint({ x: 1, y: 2 }), + exports.asyncRoundTripPublicPoint({ x: 3, y: 4 }), + ]); + assert.deepEqual(c1, { x: 1, y: 2 }); + assert.deepEqual(c2, { x: 3, y: 4 }); + + assert.deepEqual(await exports.asyncCombinePublicPoints({ x: 1, y: 2 }, { x: 10, y: 20 }), { x: 11, y: 22 }); + + assert.deepEqual(await exports.asyncStructOrThrow(false), { x: 1, y: 2 }); + await assert.rejects( + () => exports.asyncStructOrThrow(true), + (error) => error instanceof Error && error.message === "async struct failure" + ); + + await assert.rejects( + () => exports.zeroArgAsyncThrows(), + (error) => error instanceof Error && error.message === "ZeroArgAsyncThrowsError" + ); + + const richContact = { + 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(await exports.asyncRoundTripContact(richContact), richContact); + + const calc = exports.createCalculator(); + assert.deepEqual(await calc.asyncMakePoint(3, 4), { x: 3, y: 4 }); + calc.release(); + + assert.equal(await exports.asyncRoundTripTheme(ThemeValues.Dark), ThemeValues.Dark); + assert.equal(await exports.asyncRoundTripDirection(DirectionValues.East), DirectionValues.East); + + assert.deepEqual( + await exports.asyncRoundTripPublicPointArray([{ x: 1, y: 2 }, { x: 3, y: 4 }]), + [{ x: 1, y: 2 }, { x: 3, y: 4 }] + ); + + assert.equal(await exports.asyncRoundTripOptionalTheme(ThemeValues.Light), ThemeValues.Light); + assert.equal(await exports.asyncRoundTripOptionalTheme(null), null); + assert.equal(await exports.asyncRoundTripOptionalDirection(DirectionValues.South), DirectionValues.South); + assert.equal(await exports.asyncRoundTripOptionalDirection(null), null); + + assert.deepEqual(await exports.asyncRoundTripOptionalPublicPoint({ x: 5, y: 6 }), { x: 5, y: 6 }); + assert.equal(await exports.asyncRoundTripOptionalPublicPoint(null), null); + + assert.deepEqual( + await exports.asyncRoundTripPublicPointDict({ a: { x: 1, y: 2 }, b: { x: 3, y: 4 } }), + { a: { x: 1, y: 2 }, b: { x: 3, y: 4 } } + ); + + assert.deepEqual( + await exports.asyncRoundTripDirectionArray([DirectionValues.North, DirectionValues.East]), + [DirectionValues.North, DirectionValues.East] + ); + assert.deepEqual( + await exports.asyncRoundTripDirectionDict({ a: DirectionValues.North, b: DirectionValues.South }), + { a: DirectionValues.North, b: DirectionValues.South } + ); + + assert.deepEqual( + await exports.asyncRoundTripThemeArray([ThemeValues.Light, ThemeValues.Dark]), + [ThemeValues.Light, ThemeValues.Dark] + ); + assert.deepEqual( + await exports.asyncRoundTripThemeDict({ a: ThemeValues.Light, b: ThemeValues.Auto }), + { a: ThemeValues.Light, b: ThemeValues.Auto } + ); + + assert.equal(await exports.asyncRoundTripFileSize(FileSizeValues.Large), FileSizeValues.Large); + assert.equal(await exports.asyncRoundTripOptionalFileSize(FileSizeValues.Tiny), FileSizeValues.Tiny); + assert.equal(await exports.asyncRoundTripOptionalFileSize(null), null); + + const asyncPayloadSuccess = { tag: AsyncPayloadResultValues.Tag.Success, param0: "ok" }; + const asyncPayloadFailure = { tag: AsyncPayloadResultValues.Tag.Failure, param0: 7 }; + const asyncPayloadIdle = { tag: AsyncPayloadResultValues.Tag.Idle }; + assert.deepEqual(await exports.asyncRoundTripAssociatedValueEnum(asyncPayloadSuccess), asyncPayloadSuccess); + assert.deepEqual(await exports.asyncRoundTripAssociatedValueEnum(asyncPayloadFailure), asyncPayloadFailure); + assert.deepEqual(await exports.asyncRoundTripAssociatedValueEnum(asyncPayloadIdle), asyncPayloadIdle); + assert.deepEqual(await exports.asyncRoundTripOptionalAssociatedValueEnum(asyncPayloadSuccess), asyncPayloadSuccess); + assert.deepEqual(await exports.asyncRoundTripOptionalAssociatedValueEnum(asyncPayloadFailure), asyncPayloadFailure); + assert.deepEqual(await exports.asyncRoundTripOptionalAssociatedValueEnum(asyncPayloadIdle), asyncPayloadIdle); + assert.equal(await exports.asyncRoundTripOptionalAssociatedValueEnum(null), null); } diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs index ebe00548b..bab496d09 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs @@ -355,6 +355,17 @@ export function runJsClosureSupportTests(exports) { }); assert.equal(optDpResult, "DP: 7 | DP: null"); + const vectorMagnitude = processor.processVector((value) => ({ + dx: value, + dy: 4.0, + })); + assert.equal(vectorMagnitude, 5.0); + + const optVectorResult = processor.processOptionalVector((value) => + value > 0 ? { dx: value, dy: value * 2 } : null, + ); + assert.equal(optVectorResult, "(2.0,4.0) | nil"); + processor.release(); const intToInt = exports.ClosureSupportExports.makeIntToInt(10); diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/JSTypedArrayTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/JSTypedArrayTests.mjs new file mode 100644 index 000000000..f29c248f9 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/JSTypedArrayTests.mjs @@ -0,0 +1,77 @@ +// @ts-check + +import assert from 'node:assert'; + +/** + * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["JSTypedArrayImports"]} + */ +export function getImports(importsContext) { + return { + jsCreateUint8Array: function () { + return new Uint8Array([10, 20, 30]); + }, + jsRoundTripUint8Array: function (arr) { + assert.ok(arr instanceof Uint8Array, 'Expected Uint8Array'); + return arr; + }, + jsRoundTripFloat32Array: function (arr) { + assert.ok(arr instanceof Float32Array, 'Expected Float32Array'); + return arr; + }, + jsRoundTripFloat64Array: function (arr) { + assert.ok(arr instanceof Float64Array, 'Expected Float64Array'); + return arr; + }, + jsRoundTripInt32Array: function (arr) { + assert.ok(arr instanceof Int32Array, 'Expected Int32Array'); + return arr; + }, + runJsTypedArrayTests: () => { + const exports = importsContext.getExports(); + if (!exports) { throw new Error("No exports!?"); } + runJsTypedArrayTests(exports); + }, + }; +} + +/** + * JSTypedArray bridging coverage for BridgeJS runtime tests. + * @param {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} rootExports + */ +export function runJsTypedArrayTests(rootExports) { + const exports = rootExports.JSTypedArrayExports; + + // Uint8Array round-trip + const u8 = new Uint8Array([1, 2, 3, 255]); + const u8Result = exports.roundTripUint8Array(u8); + assert.ok(u8Result instanceof Uint8Array, 'Expected Uint8Array back from Swift'); + assert.equal(u8Result.length, 4); + assert.deepEqual(Array.from(u8Result), [1, 2, 3, 255]); + + // Float32Array round-trip + const f32 = new Float32Array([1.0, 2.5, 3.0]); + const f32Result = exports.roundTripFloat32Array(f32); + assert.ok(f32Result instanceof Float32Array, 'Expected Float32Array back from Swift'); + assert.equal(f32Result.length, 3); + assert.deepEqual(Array.from(f32Result), [1.0, 2.5, 3.0]); + + // Float64Array round-trip + const f64 = new Float64Array([1.0, 2.5, 3.14159]); + const f64Result = exports.roundTripFloat64Array(f64); + assert.ok(f64Result instanceof Float64Array, 'Expected Float64Array back from Swift'); + assert.equal(f64Result.length, 3); + assert.deepEqual(Array.from(f64Result), [1.0, 2.5, 3.14159]); + + // Int32Array round-trip + const i32 = new Int32Array([1, -2, 2147483647]); + const i32Result = exports.roundTripInt32Array(i32); + assert.ok(i32Result instanceof Int32Array, 'Expected Int32Array back from Swift'); + assert.equal(i32Result.length, 3); + assert.deepEqual(Array.from(i32Result), [1, -2, 2147483647]); + + // Empty typed array + const emptyU8 = new Uint8Array([]); + const emptyResult = exports.roundTripUint8Array(emptyU8); + assert.ok(emptyResult instanceof Uint8Array, 'Expected Uint8Array for empty array'); + assert.equal(emptyResult.length, 0); +} diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs index 6576876da..05969a56d 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs @@ -46,6 +46,9 @@ export function getImports(importsContext) { jsRoundTripOptionalStringToStringDictionaryUndefined: (v) => { return v === undefined ? undefined : v; }, + jsRoundTripOptionalJSObjectNull: (v) => { + return v ?? null; + }, runJsOptionalSupportTests: () => { const exports = importsContext.getExports(); if (!exports) { throw new Error("No exports!?"); } @@ -80,6 +83,10 @@ export function runJsOptionalSupportTests(rootExports) { assert.equal(exports.roundTripOptionalIntRawValueEnum(HttpStatus.Ok), HttpStatusValues.Ok); assert.equal(exports.roundTripOptionalInt64RawValueEnum(FileSize.Tiny), FileSizeValues.Tiny); assert.equal(exports.roundTripOptionalUInt64RawValueEnum(SessionId.Active), SessionIdValues.Active); + // The `none` case lowers the i64/u64 placeholder as a BigInt (`0n`); a plain `0` + // would throw "Cannot convert 0 to a BigInt" when calling the Wasm export. + assert.equal(exports.roundTripOptionalInt64RawValueEnum(null), null); + assert.equal(exports.roundTripOptionalUInt64RawValueEnum(null), null); assert.equal(exports.roundTripOptionalTSEnum(TSDirection.North), TSDirection.North); assert.equal(exports.roundTripOptionalTSStringEnum(TSTheme.Light), TSTheme.Light); assert.equal(exports.roundTripOptionalNamespacedEnum(Networking.API.Method.Get), Networking.API.Method.Get); diff --git a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift index 3b06901db..85eaa04c7 100644 --- a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift +++ b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift @@ -24,6 +24,8 @@ import JavaScriptEventLoop _ v: JSUndefinedOr<[String: String]> ) throws(JSException) -> JSUndefinedOr<[String: String]> + @JSFunction static func jsRoundTripOptionalJSObjectNull(_ value: JSObject?) throws(JSException) -> JSObject? + @JSFunction static func runJsOptionalSupportTests() throws(JSException) } @@ -84,6 +86,15 @@ final class OptionalSupportTests: XCTestCase { func testRoundTripOptionalStringToStringDictionaryUndefined() throws { try roundTripTest(OptionalSupportImports.jsRoundTripOptionalStringToStringDictionaryUndefined, ["key": "value"]) } + + func testRoundTripOptionalJSObjectNull() throws { + try XCTAssertNil(OptionalSupportImports.jsRoundTripOptionalJSObjectNull(nil)) + + let object = JSObject.global.Object.function!.new() + object.testProp = "hello" + let result = try OptionalSupportImports.jsRoundTripOptionalJSObjectNull(object) + XCTAssertEqual(result?.testProp.string, "hello") + } } @JS enum OptionalSupportExports { diff --git a/Tests/BridgeJSRuntimeTests/StructAPIs.swift b/Tests/BridgeJSRuntimeTests/StructAPIs.swift index daa7ad1e2..c2216c808 100644 --- a/Tests/BridgeJSRuntimeTests/StructAPIs.swift +++ b/Tests/BridgeJSRuntimeTests/StructAPIs.swift @@ -210,6 +210,41 @@ extension Vector2D { point } +@JS public func asyncRoundTripPublicPoint(_ point: PublicPoint) async -> PublicPoint { + point +} + +@JS public func asyncRoundTripPublicPointThrows(_ point: PublicPoint) async throws(JSException) -> PublicPoint { + point +} + +@JS public func asyncStructOrThrow(_ shouldThrow: Bool) async throws(JSException) -> PublicPoint { + if shouldThrow { + throw JSException(JSError(message: "async struct failure").jsValue) + } + return PublicPoint(x: 1, y: 2) +} + +@JS public func asyncCombinePublicPoints(_ a: PublicPoint, _ b: PublicPoint) async -> PublicPoint { + PublicPoint(x: a.x + b.x, y: a.y + b.y) +} + +@JS func asyncRoundTripContact(_ contact: Contact) async -> Contact { + contact +} + +@JS public func asyncRoundTripPublicPointArray(_ points: [PublicPoint]) async -> [PublicPoint] { + points +} + +@JS public func asyncRoundTripOptionalPublicPoint(_ point: PublicPoint?) async -> PublicPoint? { + point +} + +@JS public func asyncRoundTripPublicPointDict(_ points: [String: PublicPoint]) async -> [String: PublicPoint] { + points +} + @JS func roundTripContact(_ contact: Contact) -> Contact { return contact } diff --git a/Tests/JavaScriptEventLoopTests/JSClosure+AsyncTests.swift b/Tests/JavaScriptEventLoopTests/JSClosure+AsyncTests.swift index db093e549..e3c19a8e4 100644 --- a/Tests/JavaScriptEventLoopTests/JSClosure+AsyncTests.swift +++ b/Tests/JavaScriptEventLoopTests/JSClosure+AsyncTests.swift @@ -72,7 +72,7 @@ class JSClosureAsyncTests: XCTestCase { )!.value() XCTAssertEqual(result, 42.0) } - + func testAsyncOneshotClosureWithPriority() async throws { let priority = UnsafeSendableBox(nil) let closure = JSOneshotClosure.async(priority: .high) { _ in @@ -83,7 +83,7 @@ class JSClosureAsyncTests: XCTestCase { XCTAssertEqual(result, 42.0) XCTAssertEqual(priority.value, .high) } - + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) func testAsyncOneshotClosureWithTaskExecutor() async throws { let executor = AnyTaskExecutor() @@ -93,7 +93,7 @@ class JSClosureAsyncTests: XCTestCase { let result = try await JSPromise(from: closure.function!())!.value() XCTAssertEqual(result, 42.0) } - + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) func testAsyncOneshotClosureWithTaskExecutorPreference() async throws { let executor = AnyTaskExecutor() diff --git a/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift b/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift index aae8c2cea..b1dee1f3b 100644 --- a/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift +++ b/Tests/JavaScriptEventLoopTests/WebWorkerDedicatedExecutorTests.swift @@ -1,4 +1,4 @@ -#if compiler(>=6.1) && _runtime(_multithreaded) +#if _runtime(_multithreaded) import XCTest @testable import JavaScriptEventLoop diff --git a/Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift b/Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift index 54559f3d8..a40a039bd 100644 --- a/Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift +++ b/Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift @@ -1,4 +1,4 @@ -#if compiler(>=6.1) && _runtime(_multithreaded) +#if _runtime(_multithreaded) import Synchronization import XCTest import _CJavaScriptKit // For swjs_get_worker_thread_id @@ -789,5 +789,30 @@ final class WebWorkerTaskExecutorTests: XCTestCase { // await task.value // executor.terminate() // } + + func testDeinitJSStringOnDifferentThread() async throws { + final class Box: @unchecked Sendable { + var string: JSString? + init(_ string: JSString) { self.string = string } + } + + let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1) + defer { executor.terminate() } + + // Force JS ref allocation on the main thread so ownerTid = main thread. + var string: JSString? = JSString("main-thread-owned-key") + _ = string!.asInternalJSRef() + + let box = Box(string!) + string = nil + + // Drop the last reference on a worker — deinit fires on the worker. + // Before the fix this crashed: TypeError: Cannot read properties of undefined (reading 'rc') + let task = Task(executorPreference: executor) { + XCTAssertFalse(isMainThread()) + box.string = nil + } + await task.value + } } #endif diff --git a/Tests/JavaScriptKitTests/JSClosureTests.swift b/Tests/JavaScriptKitTests/JSClosureTests.swift index 3d609a9b9..e278656d8 100644 --- a/Tests/JavaScriptKitTests/JSClosureTests.swift +++ b/Tests/JavaScriptKitTests/JSClosureTests.swift @@ -92,52 +92,38 @@ class JSClosureTests: XCTestCase { throw XCTSkip("Missing --expose-gc flag") } - // Step 1: Create many JSClosure instances + // Step 1: Create many source closures and keep only JS references alive. + // These closures must remain callable even after heavy finalizer churn. let obj = JSObject() - var closurePointers: Set = [] let numberOfSourceClosures = 10_000 do { var closures: [JSClosure] = [] for i in 0.. maxClosurePointer { - break + let numberOfProbeClosures = 50_000 + for i in 0.. { return flag; }, + "jsRoundTripLightColor": (value) => { + return value; + }, + "jsRoundTripImportedPayloadSignal": (value) => { + return value; + }, + "jsRoundTripOptionalImportedPayloadSignal": (value) => { + return value; + }, "jsEchoJSValue": (v) => { return v; }, @@ -140,6 +150,7 @@ export async function setupOptions(options, context) { jsTranslatePoint: (point, dx, dy) => { return { x: (point.x | 0) + (dx | 0), y: (point.y | 0) + (dy | 0) }; }, + jsRoundTripOptionalPoint: (point) => point, roundTripArrayMembers: (value) => { return value; }, @@ -156,6 +167,7 @@ export async function setupOptions(options, context) { DefaultArgumentImports: getDefaultArgumentImports(importsContext), JSClassSupportImports: getJSClassSupportImports(importsContext), IntegerTypesSupportImports: getIntegerTypesSupportImports(importsContext), + JSTypedArrayImports: getJSTypedArrayImports(importsContext), IdentityModeTestImports: getIdentityModeTestImports(importsContext), }; }, @@ -299,6 +311,13 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.ok(foo instanceof ImportedFoo); assert.equal(foo.value, "hello"); + // Optional @JSClass directly as an exported function parameter/return value (issue #751) + const optFoo = new ImportedFoo("optional-foo"); + const optFooResult = exports.roundTripOptionalImportedClass(optFoo); + assert.ok(optFooResult instanceof ImportedFoo); + assert.equal(optFooResult.value, "optional-foo"); + assert.equal(exports.roundTripOptionalImportedClass(null), null); + // Test PropertyHolder with various types const testObj = { testProp: "test" }; const sibling = new exports.SimplePropertyHolder(999); @@ -1023,6 +1042,17 @@ function testStructSupport(exports) { const fooContainerResult2 = exports.roundTripFooContainer(fooContainer2); assert.equal(fooContainerResult2.foo.value, "first"); assert.equal(fooContainerResult2.optionalFoo, null); + + // Test nested structs with same short name under different parents + const metaA = { label: "hello", count: 42 }; + const metaAResult = exports.NestedStructGroupA.roundtripMetadata(metaA); + assert.equal(metaAResult.label, "hello"); + assert.equal(metaAResult.count, 42); + + const metaB = { tag: "world", value: 3.14 }; + const metaBResult = exports.NestedStructGroupB.roundtripMetadata(metaB); + assert.equal(metaBResult.tag, "world"); + assert.equal(metaBResult.value, 3.14); } /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ diff --git a/Utilities/build-examples.sh b/Utilities/build-examples.sh index bc84e6943..77e923322 100755 --- a/Utilities/build-examples.sh +++ b/Utilities/build-examples.sh @@ -6,12 +6,14 @@ 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 ((${#EXCLUDED_EXAMPLES[@]})); then + for excluded in "${EXCLUDED_EXAMPLES[@]}"; do + if [[ "$example" == *"$excluded"* ]]; then + skip_example=true + break + fi + done + fi if [ "$skip_example" = true ]; then echo "Skipping $example" continue diff --git a/Utilities/setup-dev.sh b/Utilities/setup-dev.sh new file mode 100755 index 000000000..261e5ebf6 --- /dev/null +++ b/Utilities/setup-dev.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# +# Set up a local development environment for JavaScriptKit. +# +# Steps: +# 1. Verify required tools are available (swiftly, swift, jq, npm, make, curl). +# 2. If .swift-version is present, ensure that toolchain is installed via swiftly. +# 3. Resolve a matching Wasm SDK from https://github.com/swiftwasm/swift-sdk-index +# and install it (idempotent — skipped if already installed). +# 4. Run `make bootstrap` to install JS dependencies. +# 5. Print the SWIFT_SDK_ID so it can be exported for `make unittest`. +# +# The script runs under bash via the shebang. The final `export` instructions +# it prints work unchanged in both bash and zsh. + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO_ROOT" + +INDEX_BASE="https://raw.githubusercontent.com/swiftwasm/swift-sdk-index/refs/heads/main/v1" + +if [[ -t 1 ]]; then + C_BLUE=$'\033[1;34m'; C_YELLOW=$'\033[1;33m'; C_RED=$'\033[1;31m'; C_RESET=$'\033[0m' +else + C_BLUE=''; C_YELLOW=''; C_RED=''; C_RESET='' +fi + +log() { printf '%s==>%s %s\n' "$C_BLUE" "$C_RESET" "$*"; } +warn() { printf '%swarn:%s %s\n' "$C_YELLOW" "$C_RESET" "$*" >&2; } +fail() { printf '%serror:%s %s\n' "$C_RED" "$C_RESET" "$*" >&2; exit 1; } + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || fail "missing required command: $1${2:+ ($2)}" +} + +log "Checking required tools..." +require_cmd curl +require_cmd jq "install via 'brew install jq' or your package manager" +require_cmd npm "install Node.js from https://nodejs.org" +require_cmd make +require_cmd swiftly "install from https://www.swift.org/install/macos/swiftly" +require_cmd swift "install a Swift toolchain via swiftly" +require_cmd swiftc + +# 1. Honor a .swift-version pin if the repo has one. +if [[ -f .swift-version ]]; then + pinned="$(tr -d '[:space:]' < .swift-version)" + if [[ -n "$pinned" ]]; then + log "Repo pins Swift $pinned via .swift-version" + if ! swiftly list 2>/dev/null | grep -qF "$pinned"; then + log "Installing Swift $pinned via swiftly..." + swiftly install "$pinned" + fi + fi +fi + +SWIFT_VERSION_KEY="$(swiftc --version | head -n1)" +log "Active Swift: $SWIFT_VERSION_KEY" + +# 2. Resolve a matching Wasm SDK. +log "Resolving Wasm SDK from swift-sdk-index..." +TAG_BY_VERSION="$(curl -fsSL "$INDEX_BASE/tag-by-version.json")" +TAG="$(jq -r --arg v "$SWIFT_VERSION_KEY" '.[$v] // [] | .[-1] // empty' <<<"$TAG_BY_VERSION")" + +if [[ -z "$TAG" ]]; then + cat >&2 <'. + + - Use an OSS development snapshot from https://www.swift.org/install/ + +See https://github.com/swiftwasm/swift-sdk-index for details. +EOF + exit 1 +fi + +log "Resolved tag: $TAG" +BUILD_JSON="$(curl -fsSL "$INDEX_BASE/builds/$TAG.json")" +SDK_URL="$(jq -r '."swift-sdks"."wasm32-unknown-wasip1".url' <<<"$BUILD_JSON")" +SDK_CHECKSUM="$(jq -r '."swift-sdks"."wasm32-unknown-wasip1".checksum' <<<"$BUILD_JSON")" +SDK_ID="$(jq -r '."swift-sdks"."wasm32-unknown-wasip1".id' <<<"$BUILD_JSON")" + +if swift sdk list 2>/dev/null | grep -qx "$SDK_ID"; then + log "Wasm SDK already installed: $SDK_ID" +else + log "Installing Wasm SDK: $SDK_ID" + swift sdk install "$SDK_URL" --checksum "$SDK_CHECKSUM" +fi + +# 3. JS dependencies. +log "Installing JS dependencies (make bootstrap)..." +make bootstrap + +cat <