diff --git a/Source/JavaScriptCore/runtime/JSModuleLoader.cpp b/Source/JavaScriptCore/runtime/JSModuleLoader.cpp index f7c2294e7ab3a..1b3586fee0ec0 100644 --- a/Source/JavaScriptCore/runtime/JSModuleLoader.cpp +++ b/Source/JavaScriptCore/runtime/JSModuleLoader.cpp @@ -1189,7 +1189,11 @@ void JSModuleLoader::drainSynchronousModuleQueue(JSGlobalObject* globalObject) while (i < tasks.size()) { auto t = tasks[i++]; std::array args { { t.arg0, t.arg1, t.arg2, jsUndefined() } }; - runInternalMicrotask(globalObject, vm, t.task, t.payload, args); + // The reaction may belong to a different realm than the drain's caller + // (e.g. a ShadowRealm module load that started while this queue was + // active). Run it against the realm it was diverted from so its module + // loader sees its own registry, matching what queueMicrotask would do. + runInternalMicrotask(t.globalObject, vm, t.task, t.payload, args); if (scope.exception()) [[unlikely]] { // The remaining entries are reactions that performPromiseThen…/ // triggerPromiseReactions diverted off the global microtask queue. @@ -1199,7 +1203,7 @@ void JSModuleLoader::drainSynchronousModuleQueue(JSGlobalObject* globalObject) // the exception. They run on the next normal microtask drain. while (i < tasks.size()) { auto rest = tasks[i++]; - globalObject->queueMicrotask(vm, rest.task, rest.payload, rest.arg0, rest.arg1, rest.arg2); + rest.globalObject->queueMicrotask(vm, rest.task, rest.payload, rest.arg0, rest.arg1, rest.arg2); } tasks.shrink(0); return; diff --git a/Source/JavaScriptCore/runtime/JSPromise.cpp b/Source/JavaScriptCore/runtime/JSPromise.cpp index d73cf3cf298cc..cb15817414a8b 100644 --- a/Source/JavaScriptCore/runtime/JSPromise.cpp +++ b/Source/JavaScriptCore/runtime/JSPromise.cpp @@ -491,7 +491,7 @@ void JSPromise::performPromiseThenWithInternalMicrotask(VM& vm, InternalMicrotas #if USE(BUN_JSC_ADDITIONS) if (vm.m_synchronousModuleQueue && isModuleLoaderInternalMicrotask(task)) [[unlikely]] { markAsHandled(); - vm.m_synchronousModuleQueue->tasks.append({ task, static_cast(Status::Rejected), cellValue, settled, context }); + vm.m_synchronousModuleQueue->tasks.append({ task, static_cast(Status::Rejected), globalObject, cellValue, settled, context }); break; } #endif @@ -504,7 +504,7 @@ void JSPromise::performPromiseThenWithInternalMicrotask(VM& vm, InternalMicrotas JSValue settled = settlementValue(); #if USE(BUN_JSC_ADDITIONS) if (vm.m_synchronousModuleQueue && isModuleLoaderInternalMicrotask(task)) [[unlikely]] { - vm.m_synchronousModuleQueue->tasks.append({ task, static_cast(Status::Fulfilled), cellValue, settled, context }); + vm.m_synchronousModuleQueue->tasks.append({ task, static_cast(Status::Fulfilled), globalObject, cellValue, settled, context }); break; } #endif @@ -576,7 +576,7 @@ ALWAYS_INLINE void JSPromise::settleInlineInternalMicrotask(VM& vm, JSGlobalObje setPackedCell(vm, settledFlags, nullptr); #if USE(BUN_JSC_ADDITIONS) if (vm.m_synchronousModuleQueue && isModuleLoaderInternalMicrotask(task)) [[unlikely]] { - vm.m_synchronousModuleQueue->tasks.append({ task, static_cast(newStatus), cellValue, argument, context }); + vm.m_synchronousModuleQueue->tasks.append({ task, static_cast(newStatus), globalObject, cellValue, argument, context }); return; } #endif @@ -892,7 +892,7 @@ void JSPromise::triggerPromiseReactions(VM& vm, JSGlobalObject* globalObject, St arg = slimReaction->handlerOrContext(); #if USE(BUN_JSC_ADDITIONS) if (vm.m_synchronousModuleQueue && isModuleLoaderInternalMicrotask(task)) [[unlikely]] { - vm.m_synchronousModuleQueue->tasks.append({ task, static_cast(status), promise, handler, arg }); + vm.m_synchronousModuleQueue->tasks.append({ task, static_cast(status), globalObject, promise, handler, arg }); return; } #endif diff --git a/Source/JavaScriptCore/runtime/VM.cpp b/Source/JavaScriptCore/runtime/VM.cpp index 9647ab39e2170..ed5a1d87bf14f 100644 --- a/Source/JavaScriptCore/runtime/VM.cpp +++ b/Source/JavaScriptCore/runtime/VM.cpp @@ -1900,6 +1900,7 @@ void VM::visitAggregateImpl(Visitor& visitor) // module evaluates) and mark every pending task's arguments. for (auto* q = m_synchronousModuleQueue; q; q = q->prev) { for (auto& t : q->tasks) { + visitor.appendUnbarriered(t.globalObject); visitor.appendUnbarriered(t.arg0); visitor.appendUnbarriered(t.arg1); visitor.appendUnbarriered(t.arg2); diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h index e57882627c62c..06025fc99681c 100644 --- a/Source/JavaScriptCore/runtime/VM.h +++ b/Source/JavaScriptCore/runtime/VM.h @@ -1312,6 +1312,7 @@ class VM : public ThreadSafeRefCountedWithSuppressingSaferCPPChecking { struct SynchronousModuleTask { InternalMicrotask task; uint8_t payload; + JSGlobalObject* globalObject; JSValue arg0; JSValue arg1; JSValue arg2;