Skip to content

BridgeJS: Unify thunk argument preparation - #22

Draft
krodak wants to merge 2 commits into
mainfrom
fix/struct-self-stack-order
Draft

BridgeJS: Unify thunk argument preparation#22
krodak wants to merge 2 commits into
mainfrom
fix/struct-self-stack-order

Conversation

@krodak

@krodak krodak commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Overview

Prepare Swift arguments before invoking user code instead of embedding their lifting expressions in calls. JavaScript pushes stack-backed values in parameter order, so Swift must lift them in reverse order, including a struct receiver. Those lifts must also finish before an async task is scheduled.

The previous code only hoisted synchronous arguments when more than one used the stack. A struct method with one such argument could therefore pop self before the argument. Separate closure handlers had the same ordering problem and left async argument lifts inside the deferred task.

1. One parameter preparation step

Emit local bindings for all parameters in reverse order, then call the function using those values. Remove the parameter-count guard, receiver flag, and stack-type classification. Type conversion and async scheduling continue to use the existing BridgeJS intrinsics.

let liftRet_values = [Int].bridgeJSStackPop()
let liftRet_self = ArrayMembers.bridgeJSLiftParameter()
return _bjs_makePromise(resolve: Promise_resolve_Si, reject: Promise_reject) {
    return await liftRet_self.sumAsync(_: liftRet_values)
}

2. Reuse the thunk builders

Generate Swift closure invocation handlers through the same builder as exported functions and methods. Generate struct JavaScript wrappers through the normal JS thunk builder, which also fixes their missing Promise lifting and exception checks.

3. Disambiguate continuation callbacks

Generate named JSTypedClosure.sending(...) factories for internal continuation callbacks instead of additional initializers. Ordinary (Int) -> Void callbacks can then coexist with generated (sending Int) -> Void callbacks without ambiguous initializer errors. The callback ABI is unchanged.

References

  • #472: introduced parameter-count-based stack argument hoisting.
  • #479: introduced Swift structs and their instance-method wrappers.
  • #463: introduced Swift closure invocation handlers; #524 later extracted them into ClosureCodegen and extended them to imported APIs.
  • #578: introduced JSTypedClosure and the commented-out array callback tests.
  • #610: unified JS-side closure lifting/lowering and closed #598, but did not enable those tests.
  • #707: introduced sending continuation callback signatures.
  • #758: introduced stack-argument hoisting for async Swift exports.
  • #766: introduced async and throwing Swift closure handlers.

Test Plan

  • Reproduced reversed closure arguments and invalid async struct results before the changes.
  • Added runtime coverage for concurrent async struct calls, synchronous and async array closures, and throwing struct methods.
  • Reproduced the initializer ambiguity, restored the Int-returning async array regression in both directions, and enabled the existing integer-array callback round-trip test.
  • BridgeJS diagnostics and snapshots with SwiftSyntax 600, 601, 602, and 603.
  • Verified ABI names and signatures remain unchanged across existing codegen snapshots.
  • ./Utilities/format.swift
  • ./Utilities/bridge-js-generate.sh
  • npm run check:bridgejs-dts
  • make unittest SWIFT_SDK_ID=swift-6.3-RELEASE_wasm BUILD_SYSTEM=native
  • git diff --check

@krodak krodak self-assigned this Sep 8, 2026
@krodak krodak changed the title BridgeJS: Lift struct method arguments before self BridgeJS: Unify thunk argument preparation Sep 8, 2026
@krodak
krodak force-pushed the fix/struct-self-stack-order branch 3 times, most recently from 4ab3314 to b373b2b Compare September 9, 2026 10:13
@krodak
krodak force-pushed the fix/struct-self-stack-order branch from b373b2b to 67cf95d Compare September 9, 2026 10:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BridgeJS] Support Array as parameter/return types as closure

1 participant