BridgeJS: Support generic functions on imported JS APIs - #18
Draft
krodak wants to merge 2 commits into
Draft
Conversation
krodak
force-pushed
the
kr/stack-abi-generics-import
branch
from
August 7, 2026 09:25
7188a52 to
c995dfb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Import-side half of BridgeJS generic function support, split out of swiftwasm#787 and reworked around the review feedback there. An imported
@JSFunctioncan be generic over a type parameter constrained toBridgedSwiftGenericBridgeable, so one declaration serves every bridged type instead of a wrapper per deserialized type:Tmay be a primitive,String,JSValue, or a@JSstruct,@JSenum orfinal @JS class, used bare or wrapped asT?,[T]or[String: T]. Initializers, methods and static methods on an imported@JSClassare supported too, as are return-only generics. Generic parameters on exported@JSdeclarations 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
BridgeJSTypeHandlewhose 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
@JStype 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 optionalafterInitializeinstantiator 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.
ImportGenericAPITestsround-trips every bridgeable type through real JavaScript implementations, andExamples/Embeddedbuilds a generic round-trip in CI.