[pull] main from swiftwasm:main#7
Open
pull[bot] wants to merge 1200 commits intomajacQ:mainfrom
Open
Conversation
BridgeJS: Support static @JSFunction imports
BridgeJS: T | null and T | undefined support
…ode (#575) When generating JavaScript code, avoid adding trailing spaces to empty lines.
…node allocation (#577) `trimmedDescription` allocates two new Syntax nodes just to get the trimmed description of a node. ```swift extension SyntaxProtocol { public var trimmedDescription: String { // TODO: We shouldn't need to create to copies just to get the trimmed // description. return self.trimmed.description } public var trimmed: Self { // TODO: Should only need one new node here return self.with(\.leadingTrivia, []).with(\.trailingTrivia, []) } } ``` ``` $ cat check.d.ts export function getCanvas(x: string): HTMLCanvasElement; $ node Plugins/BridgeJS/Sources/TS2Swift/JavaScript/bin/ts2swift.js check.d.ts -p tsconfig.json -o out.swift $ hyperfine "./Plugins/BridgeJS/.build/debug/BridgeJSToolInternal.before emit-skeleton out.swift" "./Plugins/BridgeJS/.build/debug/BridgeJSToolInternal.after emit-skeleton out.swift" Benchmark 1: ./Plugins/BridgeJS/.build/debug/BridgeJSToolInternal.before emit-skeleton out.swift Time (mean ± σ): 16.531 s ± 0.317 s [User: 16.355 s, System: 0.107 s] Range (min … max): 16.026 s … 17.252 s 10 runs Benchmark 2: ./Plugins/BridgeJS/.build/debug/BridgeJSToolInternal.after emit-skeleton out.swift Time (mean ± σ): 4.068 s ± 0.134 s [User: 3.976 s, System: 0.039 s] Range (min … max): 4.000 s … 4.445 s 10 runs Summary ./Plugins/BridgeJS/.build/debug/BridgeJSToolInternal.after emit-skeleton out.swift ran 4.06 ± 0.15 times faster than ./Plugins/BridgeJS/.build/debug/BridgeJSToolInternal.before emit-skeleton out.swift ```
* BridgeJS: Add support for `JSValue` * BridgeJS: Fix unused result warnings * BridgeJS: Keep translating object-like types to JSObject * UPDATE_SNAPSHOTS=1 swift test --package-path ./Plugins/BridgeJS * BridgeJS: Update object-like check not to rely on definition location * BridgeJS: Add __bjs_jsValueLower/Lift helper functions * UPDATE_SNAPSHOTS=1 swift test --package-path ./Plugins/BridgeJS
…nment BridgeJS: Support all missing types as associated values in exported enums
BridgeJS: Array import
The compiler crash should be fixed in `swift-DEVELOPMENT-SNAPSHOT-2026-01-07-a`. Resolves #449.
BridgeJS: Import-side Array Support
…SValue payloads using the shared helpers, enabling `[JSValue]` round-trips in both directions (`Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift`). - Extended JSValue test inputs with array and optional-array cases plus a JS-imported array echo to exercise the new path (`Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/JSValue.swift`). - Updated codegen/link snapshots to reflect the new JSValue array glue (`Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.swift`, `Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSValue.json`, `Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js`, `Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.d.ts`). Tests: `UPDATE_SNAPSHOTS=1 swift test --package-path ./Plugins/BridgeJS`. Next step: run `make unittest SWIFT_SDK_ID=DEVELOPMENT-SNAPSHOT-2025-11-03-a-wasm32-unknown-wasip1` for the full runtime suite if you want end-to-end validation.
…tional JSValue arrays, using tmp stacks and JSValue helpers, and Swift intrinsics gained Optional<[JSValue]> bridging (`Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift`, `Sources/JavaScriptKit/BridgeJSIntrinsics.swift`). - Expanded runtime coverage with JSValue array round-trips (including optionals) on both import and export paths plus JS prelude wiring and d.ts definitions (`Tests/BridgeJSRuntimeTests/ExportAPITests.swift`, `Tests/BridgeJSRuntimeTests/ImportAPITests.swift`, `Tests/BridgeJSRuntimeTests/bridge-js.d.ts`, `Tests/prelude.mjs`), and regenerated BridgeJS outputs (`Tests/BridgeJSRuntimeTests/Generated/*`, `Tests/BridgeJSGlobalTests/Generated/*`, plugin outputs). - Runtime tests now include JSValue array cases and all suites pass with the prescribed SDK. Tests: `make unittest SWIFT_SDK_ID=DEVELOPMENT-SNAPSHOT-2025-11-03-a-wasm32-unknown-wasip1`.
BridgeJS: Split out OptionalSupportTests.swift
BridgeJS: Fix optional String return handling in generated JS glue code
BridgeJS: Add support for `[JSValue]`
BridgeJS: Skip directories in generate input file processing
Three `StackCodegen` helpers built their `for`-loops from separate
`CodeBlockItemSyntax` fragments ("for ... {", body, "}"). swift-syntax
603's formatter then renders such partial statements with the closing
brace glued to the previous line. Combine each for-loop into a single
multi-line `CodeBlockItemSyntax` so the formatter produces consistent
output across swift-syntax 600-603.
Also fix a latent bug in `StructCodegen.generateStructLowerCode` and
`EnumCodegen.generatePayloadPushingCode`: they concatenated lowering
statements via `CodeBlockItemListSyntax(statements).description` which
does not insert separators between items that lack leading trivia. The
thunk builder path was fine because `append` explicitly adds `.newline`
trivia, but any multi-statement lowering routed through a struct field
or enum payload was silently glued onto a single line. Iterate over the
statements and write each one individually through the printer.
Add regression coverage for the previously untested codepaths:
- `[String: MyProtocol]` as a function return, class property getter,
and parameter (exercises `lowerProtocolDictionaryStatements`).
- A `@JS struct` field of type `[String: Int?]` (exercises
`lowerDictionaryStatementsInline` via `generateStructLowerCode`).
makes `Package.swift` be the newest, while supporting older versions with concrete versions baked in as mentioned in https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/swiftversionspecificpackaging/#Version-specific-Manifest-Selection
…p-emission BridgeJS: Fix for-loop emission in stack codegen
The TypeScript `.d.ts` namespace-entry builder for `@JS(namespace:)` classes only emitted the constructor, silently dropping any `@JS static func` or `@JS static var` declared on the class. The equivalent path for non-namespaced classes (`renderExportedClass` → `dtsExportEntryPrinter`) iterates `klass.methods.filter(\.effects.isStatic)` and the static subset of `klass.properties`, so the output mismatched between the two paths. The generated JS class still carries the static members via `declarationPrefixKeyword: "static"` in `renderExportedClass`, and the namespace tree references it by symbol, so the JavaScript runtime works. TypeScript consumers, however, see an incomplete type and cannot call the static factory through `typeof MyNamespace.MyClass` without a hand-written augmentation. Mirror the non-namespaced path inside the `renderClassEntry` closure in `generateTypeScript` so namespaced classes emit their static methods and static properties alongside `new(...)`. Extended `Namespaces.swift` to exercise the codepath by adding a static factory and a static readonly property on the existing `__Swift.Foundation.Greeter` class. The Namespaces snapshot set captures the fixed output.
…endering
The `renderClassEntry` closure passed to
`buildHierarchicalExportsType` manually rebuilt the same
`ClassName: { new(...); staticMethod(); ... }` block that
`renderExportedClass` already produces as its `dtsExportEntry` return
value. The two paths had to be kept in sync by hand.
Replace the inline closure with a direct call to `renderExportedClass`
that discards the JS and DTS-type outputs and returns only the
`dtsExportEntry` slice. This makes the class namespace entry for
namespaced and non-namespaced classes identical by construction.
Thread `throws` through `buildHierarchicalExportsType`,
`populateTypeScriptExportLines`, and `generateTypeScript` to
accommodate the fact that `renderExportedClass` is throwing. Hoist the
`buildHierarchicalExportsType` call out of the `printer.indent` closure
so the `try` expression is in a throwing context.
…lass Extends the existing `__Swift.Foundation.UUID` class (which already has an `@JS init` and an `@JS func`) with a static factory `fromValue(_:)` and a static readonly property `placeholder`, then asserts both are reachable via `exports.__Swift.Foundation.UUID.fromValue` and `exports.__Swift.Foundation.UUID.placeholder` in `prelude.mjs`. This is the e2e counterpart to the snapshot regression added in the previous commit — it proves the generated JavaScript actually routes calls to the correct static thunks at runtime, not just that the `.d.ts` types are well-formed.
`renderExportedClass` was being called twice for every namespaced class: once in `collectLinkData` (to produce the JS body and instance interface) and once more inside the `renderClassEntry` closure (to produce the export-entry for `buildHierarchicalExportsType`), with the JS and instance-interface outputs discarded on the second call. Store the `dtsExportEntry` slice in `LinkData.namespacedClassDtsExportEntries` during the single `collectLinkData` pass, keyed by class name. The `renderClassEntry` closure is now a non-throwing dictionary lookup, so `buildHierarchicalExportsType`, `populateTypeScriptExportLines`, and `generateTypeScript` revert to non-throwing.
* relax swift-syntax version constraint to allow 603 Packages are updating to 603 and this can fail the dependency solver. * .. and also test against it
Static properties on `@JS(namespace:)` classes used `property.callName()` to build the Swift call expression. That method consults `property.staticContext`, which is stored as `.className(abiName)` (e.g. `__Swift_Foundation_UUID`), and emits `\(abiName).\(propertyName)`. The ABI-mangled name is not a valid Swift identifier so the generated thunk failed to compile. Static methods were unaffected because `renderSingleExportedMethod` passes `klass.swiftCallName` directly. Fix `PropertyRenderingContext.callName(for:)` for the `.classStatic` case to bypass `property.callName()` and build the expression directly from `klass.swiftCallName`. This preserves the ABI symbol name (which still comes through `context.className` → `klass.abiName` → `property.getterAbiName(className:)`) while producing a valid Swift call expression in the thunk body. Also remove the now-unnecessary comment from `prelude.mjs` that described what the test was checking (the assertion itself is self-explanatory).
BridgeJS: Emit static methods and properties on namespaced class entries
Building JavaScriptKit for the Swift 6.3 Android SDK triples
(e.g. aarch64-unknown-linux-android28, x86_64-unknown-linux-android30)
fails in ThreadLocal.swift with:
error: cannot find 'pthread_key_create' in scope
error: cannot find 'pthread_key_t' in scope
Android uses Bionic, exposed to Swift as the `Android` module, rather
than Glibc. The existing conditional falls through to
`#error("Unsupported platform")` on Android.
Add a `canImport(Android)` branch between the Darwin and Glibc
branches, matching the pattern already used by Foundation and
swift-corelibs-libdispatch. No Wasm, Darwin, or Glibc behavior
changes.
Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 4 to 5. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](actions/upload-pages-artifact@v4...v5) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]>
feat: Add opt-in pointer identity mode for SwiftHeapObject wrappers
Wraps the manual steps already documented in CONTRIBUTING.md:
- Verifies required tools (swiftly, swift, jq, npm, make, curl).
- If a .swift-version file is present, installs the pinned toolchain via
swiftly.
- Resolves and installs a matching Wasm SDK from swift-sdk-index
(idempotent — skipped if already installed).
- Runs `make bootstrap` to install JS deps.
- Prints SWIFT_SDK_ID for use with `make unittest`.
The script runs under bash via shebang; the export instructions it prints
work unchanged in zsh and bash. The repo does not track .swift-version;
contributors who want it ignored locally can add it to .git/info/exclude.
The original manual instructions are kept in CONTRIBUTING.md as a fallback.
* BridgeJS: Use `@JS` types from other modules in the same package * BridgeJS: Improve diagnostics with multi-module AOT * BridgeJS: Fix an issue where the skeleton was being treated as a resource * Fix typo * Documentation improvements
…ace (#709) (#727) * [BridgeJS] Synthesize typed-closure init access from declaration surface Resolves #709: a public `@JSClass` exposing a `JSTypedClosure<...>` parameter could not be consumed from another target because the synthesized `extension JSTypedClosure { init(...) }` was always internal, leaving downstream callers no way to construct the closure value without hand-rolling a public wrapper. Imported skeleton entries now record the source access level (`public`/`package`/`internal`); the closure-signature collector takes the maximum across every surface that references a given signature, and `ClosureCodegen` prefixes the synthesized init with the resulting modifier (internal stays bare). This matches the pattern `JSClassMacro` already uses for `init(unsafelyWrapping:)`. * [BridgeJS] Address PR feedback and refresh generated artifacts - Make `accessLevel` decode-tolerant on imported skeleton structs (`ImportedFunctionSkeleton`, `ImportedConstructorSkeleton`, `ImportedGetterSkeleton`, `ImportedSetterSkeleton`, `ImportedTypeSkeleton`) by writing explicit `init(from:)` decoders that fall back to `.internal` when the key is missing. Without this, any pre-existing skeleton JSON without the new field fails decoding — the `build-examples` CI job hit `DecodingError.keyNotFound` for `accessLevel` against externally consumed skeletons. - Extract a private `recordSignature` helper so `visitClosure` and `recordInjectedSignature` share a single merge implementation. - Assert in `withAccessLevel(rawLevel:)` so unknown access strings ("open", "private", future schema additions) surface in debug builds instead of silently inheriting the outer level. - Document the `.internal` seeding assumption on `ClosureSignatureCollectorVisitor.init(moduleName:signatures:)`. - Regenerate the BridgeJS pre-generated artifacts under Benchmarks/, Examples/PlayBridgeJS/, Tests/BridgeJSIdentityTests/, and Tests/BridgeJSRuntimeTests/ via `./Utilities/bridge-js-generate.sh`, per CONTRIBUTING.md. The runtime-tests Swift output now emits `public init` on three `JSTypedClosure` extensions whose signatures surface through public exported types. * [BridgeJS] Refresh identity tests skeleton after merge with main #731 added the GC lifecycle test (with new imported function entries) to main while this branch was open. Re-running the BridgeJS regen against the merged tree fills in the `accessLevel` field on the new entries that were absent at merge time. * ci: retry flaky JSPromiseTests.testPromiseAndTimer
BridgeJS: Add swift-format-ignore-file to generated Swift sources
BridgeJS: Support nested @js types inside structs and classes
BridgeJS: Diagnose struct initializer parameter order mismatch
Remove @_spi(BridgeJS) from _BridgedAsOptional protocol and its Optional/JSUndefinedOr conformances so the conformances are visible in Embedded Swift mode. The underscore-prefixed protocol name already signals internal API, and all extension methods remain @_spi-gated. Fixes #689
JSString.Guts previously held a raw JavaScriptObjectRef and released it unconditionally on whatever thread ran deinit. In the multithreaded Wasm runtime each thread has its own JSObjectSpace, so releasing a ref on the wrong thread caused a TypeError crash (BugSnag: rc property of undefined). JSObject already handles this correctly by capturing ownerTid at init time and routing deinit through swjs_release_remote when destroyed off-thread. This change makes Guts hold a JSObject instead of a raw ref, delegating the correct cross-thread release behaviour to the existing JSObject.deinit path. Adds a regression test testDeinitJSStringOnDifferentThread that reproduces the crash deterministically: it forces JS ref allocation on the main thread via asInternalJSRef(), then drops the last reference on a worker thread. Fixes the crash seen in v292745-rc4 after upgrading to JavaScriptKit 0.50.2. https://claude.ai/code/session_01Qhg5GLXZYNJtH63Gs1SwJH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )