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 context
  • suspend(cx) — switches Active → Suspended, parks the stack in suspendedStacks_
  • resume(cx) — wakes a Suspended stack, swaps back SP/FP registers
  • leave(cx) — teardown when the promising function returns
  • forwardToSuspendable() — 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, .Exception
  • WebAssembly.compile(), WebAssembly.compileStreaming() (async)
  • WebAssembly.instantiate(), WebAssembly.instantiateStreaming() (async)
  • WebAssembly.validate()
  • WebAssembly.promising(fn) — wraps a wasm export to return a Promise
  • new 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


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