Skip to content

BridgeJS: Lower imported optional stack parameters fully on the stack - #19

Closed
krodak wants to merge 3 commits into
mainfrom
kr/optional-param-stack-flag
Closed

BridgeJS: Lower imported optional stack parameters fully on the stack#19
krodak wants to merge 3 commits into
mainfrom
kr/optional-param-stack-flag

Conversation

@krodak

@krodak krodak commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Imported optional parameters with stack-only payloads ([T]?, [String: V]?, @JS struct?) used a hybrid convention: the isSome flag crossed as a wasm i32 argument while the payload went on the shared stacks. Optional returns and optional array elements of the same types already put both on the stacks.

This lowers those parameters the same way. The wasm signature carries no argument for them; JS pops the flag and conditionally lifts, through the same fragment as optional returns. Scalars, strings, JSObject, closures, enums and heap objects keep their current optional ABIs, as do all exported signatures.

// before: flag as a wasm argument, payload on the stacks
let aIsSome = a.bridgeJSLowerParameter()
let ret = bjs_f(aIsSome)      // JS: function bjs_f(a) { if (a) { ...lift... } }

// after: all-stack
let _ = a.bridgeJSLowerParameter()
let ret = bjs_f()             // JS: pops flag, conditionally lifts

This also removes the mixed parameter representation that caused the argument-order bug fixed in swiftwasm#794. Optional stack-based values now use the same stack-only representation as other stack-based parameters.

Test plan

  • BridgeJS plugin tests / snapshots (8 snapshot files, all imported optional-stack shapes)
  • make unittest: ImportAPITests.testStackLoweredParameterOrder, optional round-trips with some and nil
  • check:bridgejs-dts, formatter, no generated drift

@krodak krodak self-assigned this Aug 11, 2026
@krodak
krodak force-pushed the kr/optional-param-stack-flag branch 2 times, most recently from 3f508a1 to 1087efe Compare August 13, 2026 14:17
@krodak
krodak marked this pull request as ready for review August 13, 2026 14:17
@krodak
krodak force-pushed the kr/optional-param-stack-flag branch 2 times, most recently from dbb07a2 to f85d854 Compare August 13, 2026 14:24
An imported optional whose payload is stack-only ([T]?, [String: V]?,
@js struct?) used a hybrid convention: the isSome flag crossed as a wasm
i32 parameter while the payload was conditionally pushed onto the shared
stacks. Optional returns and optional array elements of the same types
already travel entirely on the stacks: payload first, then a 0/1 flag on
the i32 stack.

This lowers those parameters the same way. The Swift thunk pushes the
payload (if some) followed by the flag, the wasm signature carries no
argument for the parameter, and the JS handler pops the flag before
conditionally lifting the payload, through the same fragment already
used for optional returns and elements.

The hybrid shape was the last parameter category that both passed a wasm
argument and pushed stack data, which is what enabled the argument
transposition fixed in swiftwasm#794. Every stack-touching parameter is now
flagless and reverse-ordered, matching returns and elements. All other
optional parameter ABIs (scalars, strings, JSObject, closures, enums,
heap objects) are unchanged.
@krodak
krodak force-pushed the kr/optional-param-stack-flag branch from f85d854 to 129a15d Compare August 13, 2026 14:44
@krodak

krodak commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

Moved upstream: swiftwasm#802

@krodak krodak closed this Aug 13, 2026
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.

2 participants