Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 53e97afd3421bd259df1beeb7d58f7d33d9c8b63
https://github.com/WebKit/WebKit/commit/53e97afd3421bd259df1beeb7d58f7d33d9c8b63
Author: Vassili Bykov <[email protected]>
Date: 2026-02-11 (Wed, 11 Feb 2026)
Changed paths:
A JSTests/wasm/stress/jspi-basic.js
A JSTests/wasm/stress/jspi-exceptions-from-js.js
A JSTests/wasm/stress/jspi-exceptions-from-wasm.js
A JSTests/wasm/stress/jspi-rejection.js
A JSTests/wasm/stress/jspi-resuspension.js
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/js-promise-integration.any-expected.txt
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/js-promise-integration.any.html
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/js-promise-integration.any.worker-expected.txt
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/js-promise-integration.any.worker.html
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/notraps.any-expected.txt
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/notraps.any.html
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/notraps.any.worker-expected.txt
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/notraps.any.worker.html
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/rejects.any-expected.txt
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/rejects.any.html
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/rejects.any.worker-expected.txt
M
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi/rejects.any.worker.html
M Source/JavaScriptCore/CMakeLists.txt
M Source/JavaScriptCore/DerivedSources-input.xcfilelist
M Source/JavaScriptCore/DerivedSources-output.xcfilelist
M Source/JavaScriptCore/DerivedSources.make
M Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
M Source/JavaScriptCore/Sources.txt
M Source/JavaScriptCore/heap/Heap.cpp
M Source/JavaScriptCore/heap/Heap.h
M Source/JavaScriptCore/llint/InPlaceInterpreter.asm
M Source/JavaScriptCore/llint/LLIntData.cpp
M Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
M Source/JavaScriptCore/llint/LLIntThunks.cpp
M Source/JavaScriptCore/llint/LLIntThunks.h
M Source/JavaScriptCore/llint/LowLevelInterpreter.asm
A Source/JavaScriptCore/runtime/EvacuatedStack.cpp
A Source/JavaScriptCore/runtime/EvacuatedStack.h
M Source/JavaScriptCore/runtime/Gate.h
M Source/JavaScriptCore/runtime/JSFunctionWithFields.h
M Source/JavaScriptCore/runtime/JSGlobalObject.cpp
M Source/JavaScriptCore/runtime/JSGlobalObject.h
M Source/JavaScriptCore/runtime/OptionsList.h
A Source/JavaScriptCore/runtime/PinballCompletion.cpp
A Source/JavaScriptCore/runtime/PinballCompletion.h
M Source/JavaScriptCore/runtime/StackAlignment.h
M Source/JavaScriptCore/runtime/VM.cpp
M Source/JavaScriptCore/runtime/VM.h
M Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp
A Source/JavaScriptCore/wasm/js/JSWebAssemblySuspendError.cpp
A Source/JavaScriptCore/wasm/js/JSWebAssemblySuspendError.h
A Source/JavaScriptCore/wasm/js/WebAssemblyPromising.cpp
A Source/JavaScriptCore/wasm/js/WebAssemblyPromising.h
A Source/JavaScriptCore/wasm/js/WebAssemblySuspendErrorConstructor.cpp
A Source/JavaScriptCore/wasm/js/WebAssemblySuspendErrorConstructor.h
A Source/JavaScriptCore/wasm/js/WebAssemblySuspendErrorPrototype.cpp
A Source/JavaScriptCore/wasm/js/WebAssemblySuspendErrorPrototype.h
A Source/JavaScriptCore/wasm/js/WebAssemblySuspending.cpp
A Source/JavaScriptCore/wasm/js/WebAssemblySuspending.h
A Source/JavaScriptCore/wasm/js/WebAssemblySuspendingConstructor.cpp
A Source/JavaScriptCore/wasm/js/WebAssemblySuspendingConstructor.h
A Source/JavaScriptCore/wasm/js/WebAssemblySuspendingPrototype.cpp
A Source/JavaScriptCore/wasm/js/WebAssemblySuspendingPrototype.h
M Source/WTF/wtf/MathExtras.h
Log Message:
-----------
[JSC] JSPI Implementation
Reviewed by Yusuke Suzuki.
This implements the WebAssembly JavaScript Promise Integration proposal:
https://github.com/WebAssembly/js-promise-integration
Controlled by the feature flag `useJSPI`, disabled by default.
The proposal adds a new API function and a constructor to the WebAssembly
object:
- WebAssembly.promising(wasmFun)
- new WebAssembly.Suspending(jsFun)
Each creates a wrapper function with special behavior around the function
passed as the argument.
We will refer to these as a "promising wrapper" and a "suspending wrapper".
The behavior of a promising wrapper is implemented by
runWebAssemblyPromisingFunction() in
WebAssemblyPromising.cpp. The wrapper does the following:
- Creates a promise which will later be resolved or rejected based on the
execution outcome
of the wrapped function ("result promise").
- Makes arrangements so that if a suspending wrapper is invoked during the
call to the wrapped
function, the suspending wrapper can locate the stack frame associated with
the promising
wrapper.
- Calls the wrapped function ('wasmFun').
The behavior of a suspending wrapper is implemented by
runWebAssemblySuspendingFunction() in
WebAssemblySuspending.cpp, though the actual entry point is an offlineasm
function
'enterWebAssemblySuspendingFunction' in InPlaceInterpreter.asm. The separate
entry function is
necessary to capture callee-save registers on entry, before the C++ function
prologue can tamper
with them.
The suspending wrapper:
- Calls the wrapped function ('jsFun'). If the value returned by the call is
not a promise,
creates a promise ("suspending promise") and resolves it with the returned
value.
Otherwise, the promise returned by jsFun is the suspending promise.
- Captures the stack between its own frame and the frame of the nearest
promising wrapper
invocation as a heap object (class EvacuatedStack).
- Creates an object (class PinballCompletion) that bundles together the
evacuated stack
representing the suspended Wasm computation and the result promise.
- Sets a fulfillment handler on the suspending promise. When the promise is
resolved, the handler will take the resolution result and feed it into the
suspended
Wasm computation. To do that, the handler will "implant" some or all of the
previously
evacuated stack frames onto the stack of the microtask it is executing on,
and return
into those frames. ("Pinball" in the name comes from the ability to not
implant all
of the evacuated frames at once, instead returning down the evacuated Wasm
stack
in a series of "bumps"). When the entire evacuated Wasm stack returns with
the result,
that result is used to resolve the result promise.
- Also sets a rejection handler on the suspending promise. If the rejection
reason is NOT
a Wasm exception, the evacuated Wasm stack is discarded and the rejection
reason is used to
reject the result promise. If the rejection reason is a Wasm exception, the
evacuated Wasm stack
is implanted back onto the current stack and the exception is propagated
down that stack.
- Finally, the suspending wrapper "teleports" into the frame of the promising
wrapper by returning
so that the evacuated stack frames are bypassed.
Fulfillment and rejection handlers of the suspending promise are implemented in
offlineasm
and C++ in InPlaceInterpreter.asm and PinballCompletion.cpp.
>From the perspective of the promising wrapper, a teleport from the suspending
>wrapper appears as a
return from the wrapped function. The wrapped function can also return as a
result of Wasm
computation completing without ever suspending, or as a result of an exception
thrown in Wasm code.
The wrapper checks which scenario is the case. In cases of a normal or
exception return, it fulfills
or rejects the result promise. In the case of a teleport, nothing needs to be
done because the
result promise is already hooked up to be resolved or rejected by
PinballCompletion.
Testing:
- added multiple stress tests (JSTests/wasm/stress/jspi-*.js)
- enabled w3c tests under
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/jspi
Canonical link: https://commits.webkit.org/307271@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications