Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 51cc3feb729804866ae63510d837f4df674bbc59
https://github.com/WebKit/WebKit/commit/51cc3feb729804866ae63510d837f4df674bbc59
Author: Sosuke Suzuki <[email protected]>
Date: 2026-06-04 (Thu, 04 Jun 2026)
Changed paths:
A JSTests/stress/cross-realm-await-thenable-resolve-realm.js
A JSTests/stress/cross-realm-promise-internal-reaction-realm.js
A JSTests/stress/cross-realm-promise-microtask-ordering.js
M Source/JavaScriptCore/API/JSAPIGlobalObject.mm
M Source/JavaScriptCore/dfg/DFGOperations.cpp
M Source/JavaScriptCore/jsc.cpp
M Source/JavaScriptCore/runtime/Completion.cpp
M Source/JavaScriptCore/runtime/CyclicModuleRecord.cpp
M Source/JavaScriptCore/runtime/JSGlobalObject.cpp
M Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
M Source/JavaScriptCore/runtime/JSMicrotask.cpp
M Source/JavaScriptCore/runtime/JSModuleLoader.cpp
M Source/JavaScriptCore/runtime/JSModuleRecord.cpp
M Source/JavaScriptCore/runtime/JSPromise.cpp
M Source/JavaScriptCore/runtime/JSPromise.h
M Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp
M Source/JavaScriptCore/runtime/JSPromisePrototype.cpp
M Source/JavaScriptCore/runtime/ModuleRegistryEntry.cpp
M Source/JavaScriptCore/runtime/PinballCompletion.cpp
M Source/JavaScriptCore/runtime/ShadowRealmPrototype.cpp
M Source/JavaScriptCore/tools/JSDollarVM.cpp
M Source/JavaScriptCore/wasm/WasmStreamingCompiler.cpp
M Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp
M Source/JavaScriptCore/wasm/js/WebAssemblyPromising.cpp
M Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
M Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp
M Source/WebCore/bindings/js/ScriptModuleLoader.cpp
M Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
M Source/WebCore/bindings/scripts/test/JS/JSTestCallbackInterface.cpp
Log Message:
-----------
[JSC] Promise jobs must not run with the realm of a cross-realm settle site
https://bugs.webkit.org/show_bug.cgi?id=316187
Reviewed by Yusuke Suzuki.
In a VM with multiple JSGlobalObjects, two defects let a foreign realm leak
into observable objects (e.g. the resolving functions passed to an awaited
thenable's then(f, j)):
1. The await fast paths in resolveWithInternalMicrotaskForAsyncAwait and
resolveWithInternalMicrotask adopted cross-realm vanilla promises directly,
skipping the intermediate promise that PromiseResolve[1] requires for them.
Now they require the promise's realm to match the current globalObject, so
cross-realm promises take the thenable path, whose resolving functions
re-anchor the realm; cross-realm await now costs one extra microtask,
matching V8. resolvePromise has no such check in the spec and keeps its
fast path, but enqueues the thenable job with the promise's realm.
2. Internal microtask handlers used the queue entry's globalObject, which is
the settle site's realm and can be foreign (e.g. then/catch/finally called
on a cross-realm promise). Per spec, each job's realm is fixed at creation
(e.g. Await[2] step 4), so runInternalMicrotask now derives the realm from
the object each job drives (the generator, the result promise, or the
module) and passes it to the handlers, following the precedent of
JSPromise::pipeFrom. fulfillPromise, rejectPromise, and
performPromiseThenWithInternalMicrotask now anchor on the promise's realm
instead of taking a globalObject.
V8 behaves correctly in all of these cases. Same-realm fast paths only pay
one extra pointer comparison; same-realm microtask ordering is unchanged and
async/promise microbenchmarks are neutral.
const other = createGlobalObject();
other.MainFunction = Function;
other.subject = somePendingMainRealmPromise;
new other.Function(`
(async () => {
await subject;
await { then(f) {
// f.constructor must be this realm's Function,
// but was MainFunction before this patch.
} };
})();
`)();
[1]: https://tc39.es/ecma262/#sec-promise-resolve
[2]: https://tc39.es/ecma262/#await
Tests: JSTests/stress/cross-realm-await-thenable-resolve-realm.js
JSTests/stress/cross-realm-promise-internal-reaction-realm.js
* JSTests/stress/cross-realm-await-thenable-resolve-realm.js: Added.
(shouldBe):
(async return):
* JSTests/stress/cross-realm-promise-internal-reaction-realm.js: Added.
(shouldBe):
(makePending):
(makePendingRejection):
(async settles):
(async return):
* Source/JavaScriptCore/runtime/JSMicrotask.cpp:
(JSC::asyncFromSyncIteratorContinueOrDone):
(JSC::promiseFinallyReactionJob):
(JSC::asyncModuleExecutionDone):
(JSC::asyncModuleExecutionResume):
(JSC::promiseResolveWithoutHandlerJob):
(JSC::runInternalMicrotask):
* Source/JavaScriptCore/runtime/JSPromise.cpp:
(JSC::JSPromise::resolvePromise):
(JSC::JSPromise::resolveWithInternalMicrotaskForAsyncAwait):
(JSC::JSPromise::resolveWithInternalMicrotask):
Canonical link: https://commits.webkit.org/314528@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications