MicrotaskQueue should be accessed via EventLoop
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Nov 2019 01:47:56 +0000 (01:47 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Nov 2019 01:47:56 +0000 (01:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=204397

Reviewed by Antti Koivisto.

This patch refactors the existing code so that a microtask is always queued via EventLoopTaskGroup.
It preserves all other (broken) semantics and behavior like all origins sharing a single microtask queue.

The singleton MicrotaskQueue for the main thread has been moved from MicrotaskQueue::mainThreadQueue
to WindowEventLoop, and an instance of MicrotaskQueue for each worker has been moved from WorkerGlobalScope
to WorkerEventLoop.

* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents):
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::updateFinishedState):
* bindings/js/JSDOMGlobalObjectTask.cpp:
(WebCore::JSGlobalObjectTask::JSGlobalObjectTask):
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::queueMicrotaskToEventLoop): Renamed from queueTaskToEventLoop.
* bindings/js/JSDOMWindowBase.h:
* bindings/js/JSExecState.cpp:
(WebCore::JSExecState::didLeaveScriptContext):
* bindings/js/JSRemoteDOMWindowBase.cpp:
* bindings/js/JSWorkerGlobalScopeBase.cpp:
(WebCore::JSWorkerGlobalScopeBase::queueMicrotaskToEventLoop): Renamed from queueTaskToEventLoop.
* bindings/js/JSWorkerGlobalScopeBase.h:
* bindings/js/JSWorkletGlobalScopeBase.cpp:
* bindings/js/JSWorkletGlobalScopeBase.h:
* dom/CustomElementReactionQueue.cpp:
(WebCore::BackupElementQueueMicrotask): Deleted.
(WebCore::CustomElementReactionQueue::enqueueElementOnAppropriateElementQueue):
(WebCore::CustomElementReactionQueue::ensureBackupQueue):
* dom/CustomElementReactionQueue.h:
* dom/Document.cpp:
(WebCore::Document::finishedParsing):
* dom/DocumentStorageAccess.cpp:
(WebCore::DocumentStorageAccess::requestStorageAccess):
* dom/EventLoop.cpp:
(WebCore::EventLoop::queueMicrotask): Added.
(WebCore::EventLoop::performMicrotaskCheckpoint): Added.
(WebCore::EventLoopTaskGroup::queueMicrotaskCallback): Added.
(WebCore::EventLoopTaskGroup::queueMicrotask): Added.
(WebCore::EventLoopTaskGroup::performMicrotaskCheckpoint): Added.
* dom/EventLoop.h:
(WebCore::EventLoopTaskGroup::microtaskQueue):
* dom/Microtasks.cpp:
(WebCore::MicrotaskQueue::mainThreadQueue): Deleted.
(WebCore::MicrotaskQueue::contextQueue): Deleted.
* dom/Microtasks.h:
* dom/MutationObserver.cpp:
(WebCore::MutationObserverMicrotask): Deleted.
(WebCore::MutationObserver::queueMutationObserverCompoundMicrotask): Made this a member function
so that it can call notifyMutationObservers in its lambda.
(WebCore::MutationObserver::enqueueMutationRecord):
(WebCore::MutationObserver::enqueueSlotChangeEvent):
(WebCore::MutationObserver::setHasTransientRegistration):
* dom/MutationObserver.h:
* dom/MutationObserverRegistration.cpp:
(WebCore::MutationObserverRegistration::observedSubtreeNodeWillDetach):
* dom/WindowEventLoop.cpp:
(WebCore::WindowEventLoop::microtaskQueue):
* dom/WindowEventLoop.h:
* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder):
* html/parser/HTMLScriptRunner.cpp:
(WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent):
(WebCore::HTMLScriptRunner::runScript):
* inspector/agents/InspectorCanvasAgent.cpp:
(WebCore::InspectorCanvasAgent::recordCanvasAction):
* testing/Internals.cpp:
(WebCore::Internals::queueMicroTask):
* workers/WorkerEventLoop.cpp:
(WebCore::WorkerEventLoop::~WorkerEventLoop):
(WebCore::WorkerEventLoop::microtaskQueue):
(WebCore::WorkerEventLoop::clearMicrotaskQueue):
* workers/WorkerEventLoop.h:
* workers/WorkerGlobalScope.cpp:
(WebCore::WorkerGlobalScope::WorkerGlobalScope):
(WebCore::WorkerGlobalScope::prepareForTermination):
* workers/WorkerGlobalScope.h:
(WebCore::WorkerGlobalScope::microtaskQueue const): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252723 268f45cc-cd09-0410-ab3c-d52691b4dbfc

34 files changed:
Source/WebCore/ChangeLog
Source/WebCore/animation/DocumentTimeline.cpp
Source/WebCore/animation/WebAnimation.cpp
Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.h
Source/WebCore/bindings/js/JSExecState.cpp
Source/WebCore/bindings/js/JSRemoteDOMWindowBase.cpp
Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp
Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.cpp
Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.h
Source/WebCore/dom/CustomElementReactionQueue.cpp
Source/WebCore/dom/CustomElementReactionQueue.h
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/DocumentStorageAccess.cpp
Source/WebCore/dom/EventLoop.cpp
Source/WebCore/dom/EventLoop.h
Source/WebCore/dom/Microtasks.cpp
Source/WebCore/dom/Microtasks.h
Source/WebCore/dom/MutationObserver.cpp
Source/WebCore/dom/MutationObserver.h
Source/WebCore/dom/MutationObserverRegistration.cpp
Source/WebCore/dom/WindowEventLoop.cpp
Source/WebCore/dom/WindowEventLoop.h
Source/WebCore/html/parser/HTMLDocumentParser.cpp
Source/WebCore/html/parser/HTMLScriptRunner.cpp
Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp
Source/WebCore/testing/Internals.cpp
Source/WebCore/workers/WorkerEventLoop.cpp
Source/WebCore/workers/WorkerEventLoop.h
Source/WebCore/workers/WorkerGlobalScope.cpp
Source/WebCore/workers/WorkerGlobalScope.h
Source/WebCore/worklets/WorkletGlobalScope.cpp

index 4e182f6..2d8efe7 100644 (file)
@@ -1,3 +1,88 @@
+2019-11-19  Ryosuke Niwa  <rniwa@webkit.org>
+
+        MicrotaskQueue should be accessed via EventLoop
+        https://bugs.webkit.org/show_bug.cgi?id=204397
+
+        Reviewed by Antti Koivisto.
+
+        This patch refactors the existing code so that a microtask is always queued via EventLoopTaskGroup.
+        It preserves all other (broken) semantics and behavior like all origins sharing a single microtask queue.
+
+        The singleton MicrotaskQueue for the main thread has been moved from MicrotaskQueue::mainThreadQueue
+        to WindowEventLoop, and an instance of MicrotaskQueue for each worker has been moved from WorkerGlobalScope
+        to WorkerEventLoop.
+
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents):
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::updateFinishedState):
+        * bindings/js/JSDOMGlobalObjectTask.cpp:
+        (WebCore::JSGlobalObjectTask::JSGlobalObjectTask):
+        * bindings/js/JSDOMWindowBase.cpp:
+        (WebCore::JSDOMWindowBase::queueMicrotaskToEventLoop): Renamed from queueTaskToEventLoop.
+        * bindings/js/JSDOMWindowBase.h:
+        * bindings/js/JSExecState.cpp:
+        (WebCore::JSExecState::didLeaveScriptContext):
+        * bindings/js/JSRemoteDOMWindowBase.cpp:
+        * bindings/js/JSWorkerGlobalScopeBase.cpp:
+        (WebCore::JSWorkerGlobalScopeBase::queueMicrotaskToEventLoop): Renamed from queueTaskToEventLoop.
+        * bindings/js/JSWorkerGlobalScopeBase.h:
+        * bindings/js/JSWorkletGlobalScopeBase.cpp:
+        * bindings/js/JSWorkletGlobalScopeBase.h:
+        * dom/CustomElementReactionQueue.cpp:
+        (WebCore::BackupElementQueueMicrotask): Deleted.
+        (WebCore::CustomElementReactionQueue::enqueueElementOnAppropriateElementQueue):
+        (WebCore::CustomElementReactionQueue::ensureBackupQueue):
+        * dom/CustomElementReactionQueue.h:
+        * dom/Document.cpp:
+        (WebCore::Document::finishedParsing):
+        * dom/DocumentStorageAccess.cpp:
+        (WebCore::DocumentStorageAccess::requestStorageAccess):
+        * dom/EventLoop.cpp:
+        (WebCore::EventLoop::queueMicrotask): Added.
+        (WebCore::EventLoop::performMicrotaskCheckpoint): Added.
+        (WebCore::EventLoopTaskGroup::queueMicrotaskCallback): Added.
+        (WebCore::EventLoopTaskGroup::queueMicrotask): Added.
+        (WebCore::EventLoopTaskGroup::performMicrotaskCheckpoint): Added.
+        * dom/EventLoop.h:
+        (WebCore::EventLoopTaskGroup::microtaskQueue):
+        * dom/Microtasks.cpp:
+        (WebCore::MicrotaskQueue::mainThreadQueue): Deleted.
+        (WebCore::MicrotaskQueue::contextQueue): Deleted.
+        * dom/Microtasks.h:
+        * dom/MutationObserver.cpp:
+        (WebCore::MutationObserverMicrotask): Deleted.
+        (WebCore::MutationObserver::queueMutationObserverCompoundMicrotask): Made this a member function
+        so that it can call notifyMutationObservers in its lambda.
+        (WebCore::MutationObserver::enqueueMutationRecord):
+        (WebCore::MutationObserver::enqueueSlotChangeEvent):
+        (WebCore::MutationObserver::setHasTransientRegistration):
+        * dom/MutationObserver.h:
+        * dom/MutationObserverRegistration.cpp:
+        (WebCore::MutationObserverRegistration::observedSubtreeNodeWillDetach):
+        * dom/WindowEventLoop.cpp:
+        (WebCore::WindowEventLoop::microtaskQueue):
+        * dom/WindowEventLoop.h:
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder):
+        * html/parser/HTMLScriptRunner.cpp:
+        (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent):
+        (WebCore::HTMLScriptRunner::runScript):
+        * inspector/agents/InspectorCanvasAgent.cpp:
+        (WebCore::InspectorCanvasAgent::recordCanvasAction):
+        * testing/Internals.cpp:
+        (WebCore::Internals::queueMicroTask):
+        * workers/WorkerEventLoop.cpp:
+        (WebCore::WorkerEventLoop::~WorkerEventLoop):
+        (WebCore::WorkerEventLoop::microtaskQueue):
+        (WebCore::WorkerEventLoop::clearMicrotaskQueue):
+        * workers/WorkerEventLoop.h:
+        * workers/WorkerGlobalScope.cpp:
+        (WebCore::WorkerGlobalScope::WorkerGlobalScope):
+        (WebCore::WorkerGlobalScope::prepareForTermination):
+        * workers/WorkerGlobalScope.h:
+        (WebCore::WorkerGlobalScope::microtaskQueue const): Deleted.
+
 2019-11-20  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Unreviewed, remove an unnecessary null check after r252561
index d373a57..aea558d 100644 (file)
@@ -32,6 +32,7 @@
 #include "DOMWindow.h"
 #include "DeclarativeAnimation.h"
 #include "Document.h"
+#include "EventLoop.h"
 #include "EventNames.h"
 #include "GraphicsLayer.h"
 #include "KeyframeEffect.h"
@@ -388,7 +389,8 @@ void DocumentTimeline::internalUpdateAnimationsAndSendEvents()
     removeReplacedAnimations();
 
     // 3. Perform a microtask checkpoint.
-    MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
+    if (auto document = makeRefPtr(this->document()))
+        document->eventLoop().performMicrotaskCheckpoint();
 
     // 4. Let events to dispatch be a copy of doc's pending animation event queue.
     // 5. Clear doc's pending animation event queue.
index 49e0b0b..baf820c 100644 (file)
@@ -796,12 +796,14 @@ void WebAnimation::updateFinishedState(DidSeek didSeek, SynchronouslyNotify sync
             // Otherwise, if synchronously notify is false, queue a microtask to run finish notification steps for animation unless there
             // is already a microtask queued to run those steps for animation.
             m_finishNotificationStepsMicrotaskPending = true;
-            MicrotaskQueue::mainThreadQueue().append(makeUnique<VoidMicrotask>([this, protectedThis = makeRef(*this)] () {
-                if (m_finishNotificationStepsMicrotaskPending) {
-                    m_finishNotificationStepsMicrotaskPending = false;
-                    finishNotificationSteps();
-                }
-            }));
+            if (auto* context = scriptExecutionContext()) {
+                context->eventLoop().queueMicrotask([this, protectedThis = makeRef(*this)] {
+                    if (m_finishNotificationStepsMicrotaskPending) {
+                        m_finishNotificationStepsMicrotaskPending = false;
+                        finishNotificationSteps();
+                    }
+                });
+            }
         }
     }
 
index 43181e2..0eb26c9 100644 (file)
@@ -38,7 +38,7 @@ using namespace JSC;
 
 class JSGlobalObjectCallback final : public RefCounted<JSGlobalObjectCallback>, private ActiveDOMCallback {
 public:
-    static Ref<JSGlobalObjectCallback> create(JSDOMGlobalObject& globalObject, Ref<Microtask>&& task)
+    static Ref<JSGlobalObjectCallback> create(JSDOMGlobalObject& globalObject, Ref<JSC::Microtask>&& task)
     {
         return adoptRef(*new JSGlobalObjectCallback(globalObject, WTFMove(task)));
     }
@@ -64,7 +64,7 @@ public:
     }
 
 private:
-    JSGlobalObjectCallback(JSDOMGlobalObject& globalObject, Ref<Microtask>&& task)
+    JSGlobalObjectCallback(JSDOMGlobalObject& globalObject, Ref<JSC::Microtask>&& task)
         : ActiveDOMCallback { globalObject.scriptExecutionContext() }
         , m_globalObject { globalObject.vm(), &globalObject }
         , m_task { WTFMove(task) }
@@ -72,10 +72,10 @@ private:
     }
 
     Strong<JSDOMGlobalObject> m_globalObject;
-    Ref<Microtask> m_task;
+    Ref<JSC::Microtask> m_task;
 };
 
-JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject& globalObject, Ref<Microtask>&& task)
+JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject& globalObject, Ref<JSC::Microtask>&& task)
     : ScriptExecutionContext::Task({ })
 {
     auto callback = JSGlobalObjectCallback::create(globalObject, WTFMove(task));
index 57dc31b..8d4c7f3 100644 (file)
@@ -29,6 +29,7 @@
 #include "CommonVM.h"
 #include "DOMWindow.h"
 #include "Document.h"
+#include "EventLoop.h"
 #include "FetchResponse.h"
 #include "Frame.h"
 #include "InspectorController.h"
@@ -70,7 +71,7 @@ const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = {
     &supportsRichSourceInfo,
     &shouldInterruptScript,
     &javaScriptRuntimeFlags,
-    &queueTaskToEventLoop,
+    &queueMicrotaskToEventLoop,
     &shouldInterruptScriptBeforeTimeout,
     &moduleLoaderImportModule,
     &moduleLoaderResolve,
@@ -204,16 +205,16 @@ RuntimeFlags JSDOMWindowBase::javaScriptRuntimeFlags(const JSGlobalObject* objec
     return frame->settings().javaScriptRuntimeFlags();
 }
 
-void JSDOMWindowBase::queueTaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
+void JSDOMWindowBase::queueMicrotaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
 {
     JSDOMWindowBase& thisObject = static_cast<JSDOMWindowBase&>(object);
 
     auto callback = JSMicrotaskCallback::create(thisObject, WTFMove(task));
-    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(MicrotaskQueue::mainThreadQueue(), *thisObject.scriptExecutionContext(), [callback = WTFMove(callback)]() mutable {
+    auto& eventLoop = thisObject.scriptExecutionContext()->eventLoop();
+    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(eventLoop.microtaskQueue(), *thisObject.scriptExecutionContext(), [callback = WTFMove(callback)]() mutable {
         callback->call();
     });
-
-    MicrotaskQueue::mainThreadQueue().append(WTFMove(microtask));
+    eventLoop.queueMicrotaskCallback(WTFMove(microtask));
 }
 
 void JSDOMWindowBase::willRemoveFromWindowProxy()
index 598c11b..52dff03 100644 (file)
@@ -77,7 +77,7 @@ public:
     static bool shouldInterruptScript(const JSC::JSGlobalObject*);
     static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*);
     static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
-    static void queueTaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
+    static void queueMicrotaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
 
     void printErrorMessage(const String&) const;
 
index edb8782..0b3a490 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "JSExecState.h"
 
+#include "EventLoop.h"
 #include "Microtasks.h"
 #include "RejectedPromiseTracker.h"
 #include "ScriptExecutionContext.h"
@@ -39,7 +40,7 @@ void JSExecState::didLeaveScriptContext(JSC::JSGlobalObject* lexicalGlobalObject
     ScriptExecutionContext* context = scriptExecutionContextFromExecState(lexicalGlobalObject);
     if (!context)
         return;
-    MicrotaskQueue::contextQueue(*context).performMicrotaskCheckpoint();
+    context->eventLoop().performMicrotaskCheckpoint();
     context->ensureRejectedPromiseTracker().processQueueSoon();
 }
 
index 66d2c8d..49df439 100644 (file)
@@ -39,7 +39,7 @@ const GlobalObjectMethodTable JSRemoteDOMWindowBase::s_globalObjectMethodTable =
     nullptr, // shellSupportsRichSourceInfo
     nullptr, // shouldInterruptScript
     &javaScriptRuntimeFlags,
-    nullptr, // queueTaskToEventLoop
+    nullptr, // queueMicrotaskToEventLoop
     nullptr, // shouldInterruptScriptBeforeTimeout
     nullptr, // moduleLoaderImportModule
     nullptr, // moduleLoaderResolve
index 5ba13c1..35d64ba 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "ActiveDOMCallbackMicrotask.h"
 #include "DOMWrapperWorld.h"
+#include "EventLoop.h"
 #include "JSDOMGlobalObjectTask.h"
 #include "JSDOMGuardedObject.h"
 #include "JSDedicatedWorkerGlobalScope.h"
@@ -57,7 +58,7 @@ const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable
     &supportsRichSourceInfo,
     &shouldInterruptScript,
     &javaScriptRuntimeFlags,
-    &queueTaskToEventLoop,
+    &queueMicrotaskToEventLoop,
     &shouldInterruptScriptBeforeTimeout,
     nullptr, // moduleLoaderImportModule
     nullptr, // moduleLoaderResolve
@@ -130,17 +131,16 @@ RuntimeFlags JSWorkerGlobalScopeBase::javaScriptRuntimeFlags(const JSGlobalObjec
     return thisObject->m_wrapped->thread().runtimeFlags();
 }
 
-void JSWorkerGlobalScopeBase::queueTaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
+void JSWorkerGlobalScopeBase::queueMicrotaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
 {
     JSWorkerGlobalScopeBase& thisObject = static_cast<JSWorkerGlobalScopeBase&>(object);
 
     auto callback = JSMicrotaskCallback::create(thisObject, WTFMove(task));
     auto& context = thisObject.wrapped();
-    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(context.microtaskQueue(), context, [callback = WTFMove(callback)]() mutable {
+    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(context.eventLoop().microtaskQueue(), context, [callback = WTFMove(callback)]() mutable {
         callback->call();
     });
-
-    context.microtaskQueue().append(WTFMove(microtask));
+    context.eventLoop().queueMicrotaskCallback(WTFMove(microtask));
 }
 
 JSValue toJS(JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject*, WorkerGlobalScope& workerGlobalScope)
index 5d34241..8e5b298 100644 (file)
@@ -69,7 +69,7 @@ public:
     static bool shouldInterruptScript(const JSC::JSGlobalObject*);
     static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*);
     static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
-    static void queueTaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
+    static void queueMicrotaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
 
     void clearDOMGuardedObjects();
 
index 377d3df..0965a86 100644 (file)
@@ -49,7 +49,7 @@ const GlobalObjectMethodTable JSWorkletGlobalScopeBase::s_globalObjectMethodTabl
     &supportsRichSourceInfo,
     &shouldInterruptScript,
     &javaScriptRuntimeFlags,
-    nullptr, // queueTaskToEventLoop
+    nullptr, // queueMicrotaskToEventLoop
     &shouldInterruptScriptBeforeTimeout,
     nullptr, // moduleLoaderImportModule
     nullptr, // moduleLoaderResolve
index c83e348..c4a386b 100644 (file)
@@ -59,7 +59,7 @@ public:
     static bool shouldInterruptScript(const JSC::JSGlobalObject*);
     static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*);
     static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
-    static void queueTaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
+    static void queueMicrotaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
 
     void clearDOMGuardedObjects();
 
index 6040d5c..47309c7 100644 (file)
@@ -30,6 +30,7 @@
 #include "DOMWindow.h"
 #include "Document.h"
 #include "Element.h"
+#include "EventLoop.h"
 #include "HTMLNames.h"
 #include "JSCustomElementInterface.h"
 #include "JSDOMBinding.h"
@@ -293,7 +294,7 @@ void CustomElementReactionQueue::enqueueElementOnAppropriateElementQueue(Element
 {
     ASSERT(element.reactionQueue());
     if (!CustomElementReactionStack::s_currentProcessingStack) {
-        auto& queue = ensureBackupQueue();
+        auto& queue = ensureBackupQueue(element.document());
         queue.add(element);
         return;
     }
@@ -318,23 +319,16 @@ void CustomElementReactionStack::processQueue(JSC::JSGlobalObject* state)
     m_queue = nullptr;
 }
 
-class BackupElementQueueMicrotask final : public Microtask {
-    WTF_MAKE_FAST_ALLOCATED;
-private:
-    Result run() final
-    {
-        CustomElementReactionQueue::processBackupQueue();
-        return Result::Done;
-    }
-};
-
 static bool s_processingBackupElementQueue = false;
 
-CustomElementReactionQueue::ElementQueue& CustomElementReactionQueue::ensureBackupQueue()
+// FIXME: BackupQueue must be per event loop.
+CustomElementReactionQueue::ElementQueue& CustomElementReactionQueue::ensureBackupQueue(Document& document)
 {
     if (!s_processingBackupElementQueue) {
         s_processingBackupElementQueue = true;
-        MicrotaskQueue::mainThreadQueue().append(makeUnique<BackupElementQueueMicrotask>());
+        document.eventLoop().queueMicrotask([] {
+            CustomElementReactionQueue::processBackupQueue();
+        });
     }
     return backupElementQueue();
 }
index 72160c5..19e9560 100644 (file)
@@ -80,7 +80,7 @@ public:
 
 private:
     static void enqueueElementOnAppropriateElementQueue(Element&);
-    static ElementQueue& ensureBackupQueue();
+    static ElementQueue& ensureBackupQueue(Document&);
     static ElementQueue& backupElementQueue();
 
     Ref<JSCustomElementInterface> m_interface;
index 8545ee7..c968e5d 100644 (file)
@@ -5793,7 +5793,7 @@ void Document::finishedParsing()
 
     if (!page() || !page()->isForSanitizingWebContent()) {
         // FIXME: Schedule a task to fire DOMContentLoaded event instead. See webkit.org/b/82931
-        MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
+        eventLoop().performMicrotaskCheckpoint();
     }
 
     dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, Event::CanBubble::Yes, Event::IsCancelable::No));
index 547405e..be6944d 100644 (file)
 #include "Chrome.h"
 #include "ChromeClient.h"
 #include "Document.h"
+#include "EventLoop.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
 #include "JSDOMPromiseDeferred.h"
-#include "Microtasks.h"
 #include "Page.h"
 #include "RegistrableDomain.h"
 #include "SecurityOrigin.h"
@@ -182,10 +182,10 @@ void DocumentStorageAccess::requestStorageAccess(Ref<DeferredPromise>&& promise)
         bool shouldPreserveUserGesture = wasGranted == StorageAccessWasGranted::Yes || promptWasShown == StorageAccessPromptWasShown::No;
 
         if (shouldPreserveUserGesture) {
-            MicrotaskQueue::mainThreadQueue().append(makeUnique<VoidMicrotask>([this, weakThis] () {
+            m_document.eventLoop().queueMicrotask([this, weakThis = makeWeakPtr(*this)] {
                 if (weakThis)
                     enableTemporaryTimeUserGesture();
-            }));
+            });
         }
 
         if (wasGranted == StorageAccessWasGranted::Yes)
@@ -197,10 +197,10 @@ void DocumentStorageAccess::requestStorageAccess(Ref<DeferredPromise>&& promise)
         }
 
         if (shouldPreserveUserGesture) {
-            MicrotaskQueue::mainThreadQueue().append(makeUnique<VoidMicrotask>([this, weakThis = WTFMove(weakThis)] () {
+            m_document.eventLoop().queueMicrotask([this, weakThis = makeWeakPtr(*this)] {
                 if (weakThis)
                     consumeTemporaryTimeUserGesture();
-            }));
+            });
         }
     });
 }
index b22eb2a..7e2ea24 100644 (file)
@@ -26,6 +26,9 @@
 #include "config.h"
 #include "EventLoop.h"
 
+#include "ActiveDOMCallbackMicrotask.h"
+#include "Microtasks.h"
+
 namespace WebCore {
 
 void EventLoop::queueTask(std::unique_ptr<EventLoopTask>&& task)
@@ -36,6 +39,16 @@ void EventLoop::queueTask(std::unique_ptr<EventLoopTask>&& task)
     m_tasks.append(WTFMove(task));
 }
 
+void EventLoop::queueMicrotask(std::unique_ptr<Microtask>&& microtask)
+{
+    microtaskQueue().append(WTFMove(microtask));
+}
+
+void EventLoop::performMicrotaskCheckpoint()
+{
+    microtaskQueue().performMicrotaskCheckpoint();
+}
+
 void EventLoop::resumeGroup(EventLoopTaskGroup& group)
 {
     ASSERT(isContextThread());
@@ -120,4 +133,41 @@ void EventLoopTaskGroup::queueTask(TaskSource source, EventLoop::TaskFunction&&
     return queueTask(makeUnique<EventLoopFunctionDispatchTask>(source, *this, WTFMove(function)));
 }
 
+void EventLoopTaskGroup::queueMicrotaskCallback(std::unique_ptr<ActiveDOMCallbackMicrotask>&& microtask)
+{
+    if (m_state == State::Stopped || !m_eventLoop)
+        return;
+    m_eventLoop->queueMicrotask(WTFMove(microtask));
+}
+
+class VoidMicrotask final : public Microtask {
+public:
+    explicit VoidMicrotask(Function<void()>&& function)
+        : m_function(WTFMove(function))
+    {
+    }
+
+private:
+    Result run() final
+    {
+        m_function();
+        return Result::Done;
+    }
+
+    Function<void()> m_function;
+};
+
+void EventLoopTaskGroup::queueMicrotask(EventLoop::TaskFunction&& function)
+{
+    if (m_state == State::Stopped || !m_eventLoop)
+        return;
+    m_eventLoop->queueMicrotask(makeUnique<VoidMicrotask>(WTFMove(function)));
+}
+
+void EventLoopTaskGroup::performMicrotaskCheckpoint()
+{
+    if (m_eventLoop)
+        m_eventLoop->performMicrotaskCheckpoint();
+}
+
 } // namespace WebCore
index 52fade4..0417520 100644 (file)
 
 namespace WebCore {
 
+class ActiveDOMCallbackMicrotask;
 class EventLoopTaskGroup;
 class EventTarget;
+class Microtask;
+class MicrotaskQueue;
 class ScriptExecutionContext;
 
 class EventLoopTask {
@@ -66,6 +69,13 @@ public:
     typedef Function<void ()> TaskFunction;
     void queueTask(std::unique_ptr<EventLoopTask>&&);
 
+    // https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-microtask
+    void queueMicrotask(std::unique_ptr<Microtask>&&);
+
+    // https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
+    void performMicrotaskCheckpoint();
+    virtual MicrotaskQueue& microtaskQueue() = 0;
+
     void resumeGroup(EventLoopTaskGroup&);
     void stopGroup(EventLoopTaskGroup&);
 
@@ -130,6 +140,16 @@ public:
     void queueTask(std::unique_ptr<EventLoopTask>&&);
     WEBCORE_EXPORT void queueTask(TaskSource, EventLoop::TaskFunction&&);
 
+    // https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-microtask
+    void queueMicrotask(EventLoop::TaskFunction&&);
+    MicrotaskQueue& microtaskQueue() { return m_eventLoop->microtaskQueue(); }
+
+    // FIXME: This function and ActiveDOMCallbackMicrotask should go away.
+    WEBCORE_EXPORT void queueMicrotaskCallback(std::unique_ptr<ActiveDOMCallbackMicrotask>&&);
+
+    // https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
+    void performMicrotaskCheckpoint();
+
 private:
     enum class State : uint8_t { Running, Suspended, Stopped };
 
index a2b96e9..9fa6a32 100644 (file)
@@ -43,24 +43,6 @@ MicrotaskQueue::MicrotaskQueue(JSC::VM& vm)
 
 MicrotaskQueue::~MicrotaskQueue() = default;
 
-MicrotaskQueue& MicrotaskQueue::mainThreadQueue()
-{
-    ASSERT(isMainThread());
-    static NeverDestroyed<MicrotaskQueue> queue(commonVM());
-    return queue;
-}
-
-MicrotaskQueue& MicrotaskQueue::contextQueue(ScriptExecutionContext& context)
-{
-    // While main thread has many ScriptExecutionContexts, WorkerGlobalScope and worker thread have
-    // one on one correspondence. The lifetime of MicrotaskQueue is aligned to this semantics.
-    // While main thread MicrotaskQueue is persistently held, worker's MicrotaskQueue is held by
-    // WorkerGlobalScope.
-    if (isMainThread())
-        return mainThreadQueue();
-    return downcast<WorkerGlobalScope>(context).microtaskQueue();
-}
-
 void MicrotaskQueue::append(std::unique_ptr<Microtask>&& task)
 {
     m_microtaskQueue.append(WTFMove(task));
index a9f2eb9..2cbb048 100644 (file)
@@ -52,31 +52,11 @@ protected:
     void removeSelfFromQueue(MicrotaskQueue&);
 };
 
-class VoidMicrotask final : public Microtask {
-public:
-    explicit VoidMicrotask(Function<void()>&& function)
-        : m_function(WTFMove(function))
-    {
-    }
-
-private:
-    Result run() final
-    {
-        m_function();
-        return Result::Done;
-    }
-
-    Function<void()> m_function;
-};
-
 class MicrotaskQueue final {
     WTF_MAKE_FAST_ALLOCATED;
     friend NeverDestroyed<MicrotaskQueue>;
     friend class Microtask;
 public:
-    WEBCORE_EXPORT static MicrotaskQueue& mainThreadQueue();
-    WEBCORE_EXPORT static MicrotaskQueue& contextQueue(ScriptExecutionContext&);
-
     WEBCORE_EXPORT MicrotaskQueue(JSC::VM&);
     WEBCORE_EXPORT ~MicrotaskQueue();
 
index c0d8166..af0f71f 100644 (file)
@@ -34,6 +34,7 @@
 #include "MutationObserver.h"
 
 #include "Document.h"
+#include "EventLoop.h"
 #include "GCReachableRef.h"
 #include "HTMLSlotElement.h"
 #include "InspectorInstrumentation.h"
@@ -158,35 +159,30 @@ static Vector<GCReachableRef<HTMLSlotElement>>& signalSlotList()
     return list;
 }
 
-static bool mutationObserverCompoundMicrotaskQueuedFlag;
+// This state must be per event loop.
+static bool mutationObserverCompoundMicrotaskQueuedFlag = false;
 
-class MutationObserverMicrotask final : public Microtask {
-    WTF_MAKE_FAST_ALLOCATED;
-private:
-    Result run() final
-    {
-        MutationObserver::notifyMutationObservers();
-        return Result::Done;
-    }
-};
-
-static void queueMutationObserverCompoundMicrotask()
+void MutationObserver::queueMutationObserverCompoundMicrotask(Document& document)
 {
     if (mutationObserverCompoundMicrotaskQueuedFlag)
         return;
     mutationObserverCompoundMicrotaskQueuedFlag = true;
-    MicrotaskQueue::mainThreadQueue().append(makeUnique<MutationObserverMicrotask>());
+    document.eventLoop().queueMicrotask([] {
+        notifyMutationObservers();
+    });
 }
 
 void MutationObserver::enqueueMutationRecord(Ref<MutationRecord>&& mutation)
 {
     ASSERT(isMainThread());
     ASSERT(mutation->target());
+    auto document = makeRef(mutation->target()->document());
+
     m_pendingTargets.add(*mutation->target());
     m_records.append(WTFMove(mutation));
     activeMutationObservers().add(this);
 
-    queueMutationObserverCompoundMicrotask();
+    queueMutationObserverCompoundMicrotask(document.get());
 }
 
 void MutationObserver::enqueueSlotChangeEvent(HTMLSlotElement& slot)
@@ -195,15 +191,15 @@ void MutationObserver::enqueueSlotChangeEvent(HTMLSlotElement& slot)
     ASSERT(signalSlotList().findMatching([&slot](auto& entry) { return entry.ptr() == &slot; }) == notFound);
     signalSlotList().append(slot);
 
-    queueMutationObserverCompoundMicrotask();
+    queueMutationObserverCompoundMicrotask(slot.document());
 }
 
-void MutationObserver::setHasTransientRegistration()
+void MutationObserver::setHasTransientRegistration(Document& document)
 {
     ASSERT(isMainThread());
     activeMutationObservers().add(this);
 
-    queueMutationObserverCompoundMicrotask();
+    queueMutationObserverCompoundMicrotask(document);
 }
 
 HashSet<Node*> MutationObserver::observedNodes() const
index d3825e2..c567bca 100644 (file)
@@ -40,6 +40,7 @@
 
 namespace WebCore {
 
+class Document;
 class HTMLSlotElement;
 class MutationCallback;
 class MutationObserverRegistration;
@@ -51,7 +52,6 @@ using MutationRecordDeliveryOptions = unsigned char;
 
 class MutationObserver final : public RefCounted<MutationObserver> {
     WTF_MAKE_ISO_ALLOCATED(MutationObserver);
-    friend class MutationObserverMicrotask;
 public:
     enum MutationType {
         ChildList = 1 << 0,
@@ -97,7 +97,7 @@ public:
     void observationStarted(MutationObserverRegistration&);
     void observationEnded(MutationObserverRegistration&);
     void enqueueMutationRecord(Ref<MutationRecord>&&);
-    void setHasTransientRegistration();
+    void setHasTransientRegistration(Document&);
     bool canDeliver();
 
     HashSet<Node*> observedNodes() const;
@@ -110,6 +110,7 @@ private:
     explicit MutationObserver(Ref<MutationCallback>&&);
     void deliver();
 
+    static void queueMutationObserverCompoundMicrotask(Document&);
     static void notifyMutationObservers();
     static bool validateOptions(MutationObserverOptions);
 
index e5c6dd1..0ecb05b 100644 (file)
@@ -65,7 +65,7 @@ void MutationObserverRegistration::observedSubtreeNodeWillDetach(Node& node)
         return;
 
     node.registerTransientMutationObserver(*this);
-    m_observer->setHasTransientRegistration();
+    m_observer->setHasTransientRegistration(node.document());
 
     if (!m_transientRegistrationNodes) {
         m_transientRegistrationNodes = makeUnique<HashSet<GCReachableRef<Node>>>();
index 90fe346..16c8304 100644 (file)
@@ -26,7 +26,9 @@
 #include "config.h"
 #include "WindowEventLoop.h"
 
+#include "CommonVM.h"
 #include "Document.h"
+#include "Microtasks.h"
 
 namespace WebCore {
 
@@ -71,4 +73,11 @@ bool WindowEventLoop::isContextThread() const
     return isMainThread();
 }
 
+MicrotaskQueue& WindowEventLoop::microtaskQueue()
+{
+    // MicrotaskQueue must be one per event loop.
+    static NeverDestroyed<MicrotaskQueue> queue(commonVM());
+    return queue;
+}
+
 } // namespace WebCore
index f633464..bed10d0 100644 (file)
@@ -39,13 +39,14 @@ class WindowEventLoop final : public EventLoop {
 public:
     static Ref<WindowEventLoop> ensureForRegistrableDomain(const RegistrableDomain&);
 
-    ~WindowEventLoop();
+    virtual ~WindowEventLoop();
 
 private:
     WindowEventLoop(const RegistrableDomain&);
 
     void scheduleToRun() final;
     bool isContextThread() const final;
+    MicrotaskQueue& microtaskQueue() final;
 
     RegistrableDomain m_domain;
 };
index dd9ea04..9b39816 100644 (file)
@@ -31,6 +31,7 @@
 #include "CustomElementReactionQueue.h"
 #include "DocumentFragment.h"
 #include "DocumentLoader.h"
+#include "EventLoop.h"
 #include "Frame.h"
 #include "HTMLDocument.h"
 #include "HTMLParserScheduler.h"
@@ -40,7 +41,6 @@
 #include "HTMLUnknownElement.h"
 #include "JSCustomElementInterface.h"
 #include "LinkLoader.h"
-#include "Microtasks.h"
 #include "NavigationScheduler.h"
 #include "ScriptElement.h"
 #include "ThrowOnDynamicMarkupInsertionCountIncrementer.h"
@@ -216,7 +216,7 @@ void HTMLDocumentParser::runScriptsForPausedTreeBuilder()
             // Prevent document.open/write during reactions by allocating the incrementer before the reactions stack.
             ThrowOnDynamicMarkupInsertionCountIncrementer incrementer(*document());
 
-            MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
+            document()->eventLoop().performMicrotaskCheckpoint();
 
             CustomElementReactionStack reactionStack(document()->execState());
             auto& elementInterface = constructionData->elementInterface.get();
index eb925d8..1658639 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "Element.h"
 #include "Event.h"
+#include "EventLoop.h"
 #include "EventNames.h"
 #include "Frame.h"
 #include "HTMLInputStream.h"
@@ -36,7 +37,6 @@
 #include "HTMLScriptRunnerHost.h"
 #include "IgnoreDestructiveWriteCountIncrementer.h"
 #include "InlineClassicScript.h"
-#include "Microtasks.h"
 #include "MutationObserver.h"
 #include "NestingLevelIncrementer.h"
 #include "ScriptElement.h"
@@ -106,8 +106,8 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
     if (pendingScript.watchingForLoad())
         stopWatchingForLoad(pendingScript);
 
-    if (!isExecutingScript())
-        MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
+    if (!isExecutingScript() && m_document)
+        m_document->eventLoop().performMicrotaskCheckpoint();
 
     {
         NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
@@ -241,8 +241,8 @@ void HTMLScriptRunner::runScript(ScriptElement& scriptElement, const TextPositio
     // every script element, even if it's not ready to execute yet. There's
     // unfortunately no obvious way to tell if prepareScript is going to
     // execute the script before calling it.
-    if (!isExecutingScript())
-        MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
+    if (!isExecutingScript() && m_document)
+        m_document->eventLoop().performMicrotaskCheckpoint();
 
     InsertionPointRecord insertionPointRecord(m_host.inputStream());
     NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
index 0198f0d..3d10481 100644 (file)
@@ -31,6 +31,7 @@
 #include "CanvasRenderingContext2D.h"
 #include "Document.h"
 #include "Element.h"
+#include "EventLoop.h"
 #include "Frame.h"
 #include "HTMLCanvasElement.h"
 #include "ImageBitmap.h"
@@ -453,8 +454,8 @@ void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRend
     // covered by the initial microtask until the next frame.
     if (!inspectorCanvas->currentFrameHasData()) {
         if (auto* scriptExecutionContext = inspectorCanvas->scriptExecutionContext()) {
-            auto& queue = MicrotaskQueue::mainThreadQueue();
-            queue.append(makeUnique<ActiveDOMCallbackMicrotask>(queue, *scriptExecutionContext, [&, protectedInspectorCanvas = inspectorCanvas.copyRef()] {
+            auto& eventLoop = scriptExecutionContext->eventLoop();
+            auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(eventLoop.microtaskQueue(), *scriptExecutionContext, [&, protectedInspectorCanvas = inspectorCanvas.copyRef()] {
                 if (auto* canvasElement = protectedInspectorCanvas->canvasElement()) {
                     if (canvasElement->isDescendantOf(canvasElement->document()))
                         return;
@@ -462,7 +463,8 @@ void InspectorCanvasAgent::recordCanvasAction(CanvasRenderingContext& canvasRend
 
                 if (canvasRenderingContext.callTracingActive())
                     didFinishRecordingCanvasFrame(canvasRenderingContext);
-            }));
+            });
+            eventLoop.queueMicrotaskCallback(WTFMove(microtask));
         }
     }
 
index 244d191..d26c624 100644 (file)
@@ -4327,11 +4327,12 @@ void Internals::queueMicroTask(int testNumber)
     if (!document)
         return;
 
-    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(MicrotaskQueue::mainThreadQueue(), *document, [document, testNumber]() {
+    ScriptExecutionContext* context = document;
+    auto& eventLoop = context->eventLoop();
+    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(eventLoop.microtaskQueue(), *document, [document, testNumber]() {
         document->addConsoleMessage(MessageSource::JS, MessageLevel::Debug, makeString("MicroTask #", testNumber, " has run."));
     });
-
-    MicrotaskQueue::mainThreadQueue().append(WTFMove(microtask));
+    eventLoop.queueMicrotaskCallback(WTFMove(microtask));
 }
 
 #if ENABLE(CONTENT_FILTERING)
index 87c59dc..7dacc0d 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "WorkerEventLoop.h"
 
+#include "Microtasks.h"
 #include "WorkerGlobalScope.h"
 #include "WorkletGlobalScope.h"
 
@@ -48,6 +49,10 @@ WorkerEventLoop::WorkerEventLoop(ScriptExecutionContext& context)
 {
 }
 
+WorkerEventLoop::~WorkerEventLoop()
+{
+}
+
 void WorkerEventLoop::scheduleToRun()
 {
     ASSERT(scriptExecutionContext());
@@ -61,5 +66,18 @@ bool WorkerEventLoop::isContextThread() const
     return scriptExecutionContext()->isContextThread();
 }
 
+MicrotaskQueue& WorkerEventLoop::microtaskQueue()
+{
+    ASSERT(scriptExecutionContext());
+    if (!m_microtaskQueue)
+        m_microtaskQueue = makeUnique<MicrotaskQueue>(scriptExecutionContext()->vm());
+    return *m_microtaskQueue;
+}
+
+void WorkerEventLoop::clearMicrotaskQueue()
+{
+    m_microtaskQueue = nullptr;
+}
+
 } // namespace WebCore
 
index 9063f94..dc4f404 100644 (file)
@@ -42,11 +42,19 @@ public:
     static Ref<WorkerEventLoop> create(WorkletGlobalScope&);
 #endif
 
+    virtual ~WorkerEventLoop();
+
+    // FIXME: This should be removed once MicrotaskQueue is integrated with EventLoopTaskGroup.
+    void clearMicrotaskQueue();
+
 private:
     explicit WorkerEventLoop(ScriptExecutionContext&);
 
     void scheduleToRun() final;
     bool isContextThread() const;
+    MicrotaskQueue& microtaskQueue() final;
+
+    std::unique_ptr<MicrotaskQueue> m_microtaskQueue;
 };
 
 } // namespace WebCore
index de950b9..1d4e728 100644 (file)
@@ -68,7 +68,6 @@ WorkerGlobalScope::WorkerGlobalScope(const URL& url, Ref<SecurityOrigin>&& origi
     , m_thread(thread)
     , m_script(makeUnique<WorkerScriptController>(this))
     , m_inspectorController(makeUnique<WorkerInspectorController>(*this))
-    , m_microtaskQueue(makeUnique<MicrotaskQueue>(m_script->vm()))
     , m_isOnline(isOnline)
     , m_shouldBypassMainWorldContentSecurityPolicy(shouldBypassMainWorldContentSecurityPolicy)
     , m_eventQueue(*this)
@@ -143,7 +142,8 @@ void WorkerGlobalScope::prepareForTermination()
     removeAllEventListeners();
 
     // MicrotaskQueue and RejectedPromiseTracker reference Heap.
-    m_microtaskQueue = nullptr;
+    if (m_eventLoop)
+        m_eventLoop->clearMicrotaskQueue();
     removeRejectedPromiseTracker();
 }
 
index 5b02602..7ad606e 100644 (file)
@@ -45,7 +45,6 @@ namespace WebCore {
 class ContentSecurityPolicyResponseHeaders;
 class Crypto;
 class EventLoopTaskGroup;
-class MicrotaskQueue;
 class Performance;
 class ScheduledAction;
 class WorkerEventLoop;
@@ -90,8 +89,6 @@ public:
 
     WorkerInspectorController& inspectorController() const { return *m_inspectorController; }
 
-    MicrotaskQueue& microtaskQueue() const { return *m_microtaskQueue; }
-
     WorkerThread& thread() const { return m_thread; }
 
     using ScriptExecutionContext::hasPendingActivity;
@@ -191,7 +188,6 @@ private:
     WorkerThread& m_thread;
     std::unique_ptr<WorkerScriptController> m_script;
     std::unique_ptr<WorkerInspectorController> m_inspectorController;
-    std::unique_ptr<MicrotaskQueue> m_microtaskQueue;
 
     bool m_closing { false };
     bool m_isOnline;
index 4cd9575..c4bdaaf 100644 (file)
@@ -80,8 +80,10 @@ void WorkletGlobalScope::prepareForDestruction()
     if (m_defaultTaskGroup)
         m_defaultTaskGroup->stopAndDiscardAllTasks();
     stopActiveDOMObjects();
-    removeRejectedPromiseTracker();
     removeAllEventListeners();
+    if (m_eventLoop)
+        m_eventLoop->clearMicrotaskQueue();
+    removeRejectedPromiseTracker();
     m_script->vm().notifyNeedTermination();
     m_script = nullptr;
 }