Now I have a comprehensive picture. Let me compile everything into a thorough response.
WebAssembly in Firefox: Source Code, APIs, and Test Cases
The dev-platform thread 8cOxM-dWaNs is the “Intent to ship: WebAssembly JS Promise Integration (JSPI)” announcement, closely related to the earlier Intent to Prototype thread which describes JSPI as allowing synchronous WebAssembly code to use async Web APIs via stack suspension. JSPI was standardized by the W3C WebAssembly CG in April 2025 and is now shipping in both Chrome and Firefox. The feature pref is javascript.options.wasm_js_promise_integration. bugzilla.mozilla
Core WebAssembly Source Tree
All WebAssembly engine code in Firefox/SpiderMonkey lives under js/src/wasm/ in the mozilla-firefox/firefox repository . The directory contains ~70 files. Below is a structured breakdown:
Compilation Pipeline
| File | Role |
|---|---|
WasmCompile.cpp/.h |
Top-level compilation entry point; dispatches to baseline or Ion |
WasmBaselineCompile.cpp/.h |
Baseline (Liftoff-style) one-pass compiler — ~415KB, largest single source file |
WasmIonCompile.cpp/.h |
IonMonkey optimising compiler backend — ~383KB |
WasmGenerator.cpp/.h |
Module-level codegen coordinator |
WasmOpIter.cpp/.h |
Instruction validation/iteration (OpIter) — .h is ~150KB |
WasmValidate.cpp/.h |
Module/function-body validator (~203KB) |
WasmStubs.cpp/.h |
JIT entry/exit stubs, trampoline code (~136KB) |
WasmBuiltins.cpp/.h |
Built-in function call helpers (~91KB) |
Runtime / Instance
| File | Role |
|---|---|
WasmInstance.cpp/.h |
Module instance execution and call dispatch (~166KB) |
WasmJS.cpp/.h |
The JS-facing WebAssembly API (WebAssembly.*) — ~194KB, the main JS API layer |
WasmModule.cpp/.h |
Serializable module object; caching |
WasmCode.cpp/.h |
Executable code ownership, code segments |
WasmMemory.cpp/.h |
Linear memory management |
WasmTable.cpp/.h |
Table object implementation |
WasmSignalHandlers.cpp |
SIGSEGV/trap signal handling for OOB access |
WasmValue.cpp/.h |
Val type boxing/unboxing |
Type System & Binary
| File | Role |
|---|---|
WasmTypeDef.cpp/.h |
Struct/array type definitions (GC proposal support) — .h ~57KB |
WasmValType.cpp/.h |
Wasm value type representations |
WasmBinary.cpp/.h |
Binary format decoding primitives |
WasmConstants.h |
Opcode enumerations, section IDs, limits |
WasmCodegenTypes.h |
IR types used throughout codegen (~62KB) |
GC, Stack & Debugging
| File | Role |
|---|---|
WasmGC.cpp/.h |
Frame scanning and GC rooting for wasm frames |
WasmGcObject.cpp/.h |
GC-managed struct/array heap objects |
WasmStacks.cpp/.h |
Suspendable stack infrastructure for JSPI (~75KB) |
WasmFrameIter.cpp/.h |
Stack frame iterator for unwinding and stack traces (~97KB) |
WasmDebug.cpp/.h |
Debugger integration (breakpoints, stepping) |
WasmComponent.cpp/.h |
Component Model support (~30KB) |
WasmBuiltinModule.cpp/.yaml |
Built-in module definitions (YAML-driven codegen) |
AsmJS Legacy
AsmJS.cpp/.h — Backward-compatible asm.js → wasm translator (~217KB, the single largest file) .
JS Promise Integration (JSPI) API Functions
The JSPI implementation is split across two files, gated by #ifdef ENABLE_WASM_JSPI:
js/src/wasm/WasmPI.h — Public API Surface
These are the key exported C++ functions declared in the header (all under namespace js::wasm): developer.mozilla
// Stack execution control
bool CallOnMainStack(JSContext* cx, CallOnMainStackFn fn, void* data);
// Suspending function wrapper: wraps an async JS function so it can be
// called from a suspendable wasm stack and yield a Promise
JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func,
wasm::ValTypeVector&& params,
wasm::ValTypeVector&& results);
JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func,
const FuncType& type);
// Promising function wrapper: wraps a wasm export so its return value is a
// Promise, enabling async callers
JSFunction* WasmPromisingFunctionCreate(JSContext* cx, HandleObject func,
wasm::ValTypeVector&& params,
wasm::ValTypeVector&& results);
// Suspender lifecycle
SuspenderObject* CurrentSuspender(Instance* instance, int reserved);
SuspenderObject* CreateSuspender(Instance* instance, int reserved);
// Promise plumbing
PromiseObject* CreatePromisingPromise(Instance* instance,
SuspenderObject* suspender);
JSObject* GetSuspendingPromiseResult(Instance* instance, void* result,
SuspenderObject* suspender);
void* AddPromiseReactions(Instance* instance, SuspenderObject* suspender,
void* result, JSFunction* continueOnSuspendable);
void* ForwardExceptionToSuspended(Instance* instance,
SuspenderObject* suspender,
void* exception);
// Result settlement and state management
int32_t SetPromisingPromiseResults(Instance* instance,
SuspenderObject* suspender,
WasmStructObject* results);
void UpdateSuspenderState(Instance* instance, SuspenderObject* suspender,
UpdateSuspenderStateAction action);
js/src/wasm/WasmPI.cpp — Implementation (~48KB)
The implementation contains the SuspenderObject class (a NativeObject), SuspenderObjectData with raw stack pointer fields, and SuspenderContext which owns the doubly-linked list of suspended stacks. Key internal state transitions on SuspenderObject are: developer.mozilla
enter(cx)— switches from Initial → Active, sets the active suspender on contextsuspend(cx)— switches Active → Suspended, parks the stack insuspendedStacks_resume(cx)— wakes a Suspended stack, swaps back SP/FP registersleave(cx)— teardown when the promising function returnsforwardToSuspendable()— injects the parked stack back into the JIT activation chain
Platform-specific simulator switches (switchSimulatorToMain/switchSimulatorToSuspendable) are implemented for ARM64, ARM32, and RISCV64 simulators. developer.mozilla
js/src/wasm/WasmJS.cpp — JS API (~194KB)
This is where the WebAssembly global object and all its constructors/methods are exposed:
WebAssembly.Module,.Instance,.Memory,.Table,.Global,.Tag,.ExceptionWebAssembly.compile(),WebAssembly.compileStreaming()(async)WebAssembly.instantiate(),WebAssembly.instantiateStreaming()(async)WebAssembly.validate()WebAssembly.promising(fn)— wraps a wasm export to return a Promisenew WebAssembly.Suspending(fn)— wraps an async JS function for use as a suspending import
Test Cases: Async and Synchronous JSPI
SpiderMonkey JIT Tests (js/src/jit-test/tests/wasm/js-promise-integration/)
These are shell-level tests run with ./mach jit-test and require the javascript.options.wasm_js_promise_integration pref. The directory contains 38 test files : firefox-source-docs.mozilla
| File | What it tests |
|---|---|
simple.js |
Basic round-trip: Suspending import → promising export |
js-promise-integration.new.js |
Comprehensive integration tests — 17KB, the primary spec-coverage file |
basic2.js |
Extended basic scenarios |
concurrent.js |
Multiple simultaneous suspenders |
many-outstanding.js |
Many unresolved promises in flight at once |
multiple-suspending.js |
Multiple suspending imports within one module |
multivalue.js |
Multi-value return types across the boundary |
types.js |
Type checking and validation |
exception-handling.js |
Exception propagation across stack switches |
sync-throw.js |
Synchronous throw within a promising call |
error-stack.js |
Stack trace accuracy after suspension |
thenable.js |
Thenable (non-native Promise) objects as return values |
timeout.js |
Delayed resolution via setTimeout-style microtask |
recursive-promising.js |
Nested/recursive promising calls |
cross-realm.js |
Cross-realm (multiple global) behaviour |
proxy.js |
JS Proxy objects as suspending callables |
gc.js |
GC correctness while stacks are suspended |
gc-2.js / gc-3.js / gc-4.js |
Further GC edge cases |
gc-barrier.js |
Write barrier correctness on suspended stacks |
gc-update-data-pointers.js |
Tenuring/moving GC pointer updates |
saved-stacks.js |
Error.captureStackTrace interaction |
debug.js |
Debugger API with JSPI |
debug-mixed-frames.js |
Mixed JS+wasm frames in debugger |
debug-onStep-suspended.js |
Debugger stepping across suspension points |
debug-stale-cont-frame.js |
Stale continuation frame safety |
debug-frame-offset-non-debug.js |
Debug-mode frame offsets in non-debug builds |
jitexit.js |
JIT-exit code paths during suspension |
jitexit-profiler.js |
Profiler frame validity at JIT exits |
basic-profiler-1.js / basic-profiler-2.js |
Profiler stack sampling correctness |
suspender.js |
SuspenderObject lifetime and state machine |
guard-suspending.js |
Guards against calling suspending import off a main stack |
suspending-canonical-type.js |
Canonical type identity for Suspending wrappers |
promising-nonfinal-type.js |
Non-final (subtype) result types on promising |
multi.js |
Multi-module JSPI interactions |
stress.js |
Rapid repeated suspension/resumption cycles |
shutdown.js |
Clean teardown with outstanding suspenders |
oom-1.js / oom-2.js |
OOM handling during stack allocation |
bug2043040.js |
Regression test for Bug 2043040 |
no-directives/ subdirectory |
Tests that must run without JSPI-enabling directives (negative tests) |
Web Platform Tests (WPT) — testing/web-platform/tests/wasm/jsapi/jspi/
These are the cross-browser interop tests tracked at wpt.fyi/results/wasm/jsapi/jspi : groups.google
| File | Description |
|---|---|
js-promise-integration.any.js |
~11KB; primary cross-browser async JSPI API tests (runs in Window, Worker, ServiceWorker) |
rejects.any.js |
Async rejection paths — Promise rejection propagation into wasm |
notraps.any.js |
Async paths that must not produce wasm traps |
testharness-additions.js |
Shared test helpers (e.g., promise_test wrappers for JSPI) |
README.txt |
Points to the upstream WPT repo |
The .any.js suffix means these tests execute in all global scopes (Window, dedicated Worker, shared Worker, ServiceWorker), covering the full async runtime environment. groups.google
Other Async-Related Wasm Tests
js/src/jit-test/tests/wasm/async-instantiate.js— TestsWebAssembly.instantiateStreaming()andWebAssembly.compileStreaming()async paths searchfoxjs/src/jit-test/tests/wasm/streaming.js— Streaming compilation APIjs/src/jit-test/tests/wasm/stack-switching/— Stack-switching proposal tests (related but distinct from JSPI) searchfoxjs/src/jit-test/tests/wasm/spec/stack-switching/— Shared Wasm CG spec tests for stack switching searchfox
How to Enable and Run
Enable the pref for local testing:
// about:config
javascript.options.wasm_js_promise_integration = true
Run all JSPI jit-tests:
./mach jit-test js/src/jit-test/tests/wasm/js-promise-integration
Run WPT JSPI tests:
./mach web-platform-tests wasm/jsapi/jspi