Skip to content

[pull] main from swiftwasm:main#7

Open
pull[bot] wants to merge 1200 commits intomajacQ:mainfrom
swiftwasm:main
Open

[pull] main from swiftwasm:main#7
pull[bot] wants to merge 1200 commits intomajacQ:mainfrom
swiftwasm:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Jul 19, 2021

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 : )

@pull pull Bot added ⤵️ pull merge-conflict Resolve conflicts manually labels Jul 19, 2021
@atomist atomist Bot added auto-branch-delete:on-close Delete branch when pull request gets closed auto-merge-method:merge Auto-merge with merge commit auto-merge:on-bpr-success Auto-merge on passed branch protection rule labels Jul 19, 2021
@pull pull Bot removed auto-branch-delete:on-close Delete branch when pull request gets closed auto-merge-method:merge Auto-merge with merge commit auto-merge:on-bpr-success Auto-merge on passed branch protection rule labels Jul 19, 2021
kateinoigakukun and others added 22 commits February 4, 2026 14:19
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
The compiler crash should be fixed in `swift-DEVELOPMENT-SNAPSHOT-2026-01-07-a`.

Resolves #449.
…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: Skip directories in generate input file processing
krodak and others added 30 commits April 9, 2026 13:20
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⤵️ pull merge-conflict Resolve conflicts manually

Projects

None yet

Development

Successfully merging this pull request may close these issues.