BridgeJS: Support optional @JSClass as exported function parameters by krodak · Pull Request #754 · swiftwasm/JavaScriptKit
Overview
Fixes #751. A @JS exported function taking (or returning) an optional @JSClass such as JSAbortSignal? failed to compile with no exact matches in call to static method 'bridgeJSLiftParameter' for Optional<JSAbortSignal>.
Optional jsObject (incl. @JSClass) parameters now use the direct (isSome, objId) ABI in both directions, matching plain Optional<JSObject> and exported @JS class parameters; only return values use the stack ABI.
1. Export parameters: use the direct ABI. ExportSwift no longer special-cases .nullable(.jsObject), so exported parameters lift via Optional<T>.bridgeJSLiftParameter(isSome, value). Adds the missing Optional<_JSBridgedClass>.bridgeJSLiftParameter(isSome, objId) and bridgeJSLowerReturn() so optional @JSClass values round-trip as both parameters and return values.
2. Import parameters: align to the direct ABI. loweringParameterInfo already lowered optional jsObject import parameters as direct (isSome, value), but the JS lift still popped the object id off the stack that Swift never pushed, throwing ReferenceError: Attempted to use invalid reference undefined for a non-nil value. The JS lift now reads the object id directly, matching the extern.
A new optionalParameterUsesStackABI keeps the stack ABI only for the return direction of optional jsObject.
Tests
- Export direction: end-to-end runtime test passing an optional imported
@JSClassdirectly as an exported function parameter and return value (present andnullcases), plus snapshot coverage for optionalJSObject?and@JSClass?. - Import direction: end-to-end runtime test passing an optional
JSObject?into an imported JS function (present andnullcases), plus updated snapshot coverage for the optional@JSClass?import parameter. - Regenerated in-package snapshots and the AoT-committed bindings. Snapshot suites, the BridgeJS TypeScript declaration check, and the full wasm test suite pass.