Skip to content

BridgeJS: Support generic functions on imported JS APIs - #18

Draft
krodak wants to merge 2 commits into
mainfrom
kr/stack-abi-generics-import
Draft

BridgeJS: Support generic functions on imported JS APIs#18
krodak wants to merge 2 commits into
mainfrom
kr/stack-abi-generics-import

Conversation

@krodak

@krodak krodak commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Overview

Import-side half of BridgeJS generic function support, split out of swiftwasm#787 and reworked around the review feedback there. An imported @JSFunction can be generic over a type parameter constrained to BridgedSwiftGenericBridgeable, so one declaration serves every bridged type instead of a wrapper per deserialized type:

@JSFunction func parse<T: BridgedSwiftGenericBridgeable>(_ json: String) throws(JSException) -> T

let user: User = try parse(jsonString)   // T inferred from the call site

T may be a primitive, String, JSValue, or a @JS struct, @JS enum or final @JS class, used bare or wrapped as T?, [T] or [String: T]. Initializers, methods and static methods on an imported @JSClass are supported too, as are return-only generics. Generic parameters on exported @JS declarations are rejected with a diagnostic; the export side lands separately on top of this ABI.

1. Handle-based type identity. Each conforming type owns a BridgeJSTypeHandle whose pointer is its runtime type ID, replacing the string interning of swiftwasm#787. Cross-module name conflicts become structurally impossible, and because the path uses no existentials it works under Embedded Swift.

2. Unconditional conformance emission. A module cannot know its dependents, so conformances are emitted for every @JS type whether or not the defining module declares generics — a type from module A can be the generic argument of a generic import in module B.

3. Combinator codecs. Each container's stack ABI is described once — __bjs_arrayCodec, __bjs_optionalCodec, __bjs_dictCodec — and instantiated with an element codec. The non-generic array, dictionary and optional paths now go through the same combinators, so each shape has one description rather than an inline clone per thunk.

Each module registers its handle IDs against the JS codec table through an exported bjs_<Module>_register_type_handles, driven by a new optional afterInitialize instantiator hook, with a lazy first-call fallback for worker threads. A build that declares no generics pays one wasm import and export per module with bridgeable types; the JavaScript-side generic runtime is link-gated and absent entirely.

Adds codegen and link snapshots for the full matrix (free functions, initializers, methods, statics, multiple and mixed parameters, return-only, wrapped forms), import and export-rejection diagnostics, and gating tests for the registration runtime. ImportGenericAPITests round-trips every bridgeable type through real JavaScript implementations, and Examples/Embedded builds a generic round-trip in CI.

@krodak
krodak force-pushed the kr/stack-abi-generics-import branch from 7188a52 to c995dfb Compare August 7, 2026 09:25
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.

1 participant