Changeset 252723 in webkit


Ignore:
Timestamp:
Nov 20, 2019, 5:47:56 PM (6 years ago)
Author:
rniwa@webkit.org
Message:

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.

Location:
trunk/Source/WebCore
Files:
34 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r252718 r252723  
     12019-11-19  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        MicrotaskQueue should be accessed via EventLoop
     4        https://bugs.webkit.org/show_bug.cgi?id=204397
     5
     6        Reviewed by Antti Koivisto.
     7
     8        This patch refactors the existing code so that a microtask is always queued via EventLoopTaskGroup.
     9        It preserves all other (broken) semantics and behavior like all origins sharing a single microtask queue.
     10
     11        The singleton MicrotaskQueue for the main thread has been moved from MicrotaskQueue::mainThreadQueue
     12        to WindowEventLoop, and an instance of MicrotaskQueue for each worker has been moved from WorkerGlobalScope
     13        to WorkerEventLoop.
     14
     15        * animation/DocumentTimeline.cpp:
     16        (WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents):
     17        * animation/WebAnimation.cpp:
     18        (WebCore::WebAnimation::updateFinishedState):
     19        * bindings/js/JSDOMGlobalObjectTask.cpp:
     20        (WebCore::JSGlobalObjectTask::JSGlobalObjectTask):
     21        * bindings/js/JSDOMWindowBase.cpp:
     22        (WebCore::JSDOMWindowBase::queueMicrotaskToEventLoop): Renamed from queueTaskToEventLoop.
     23        * bindings/js/JSDOMWindowBase.h:
     24        * bindings/js/JSExecState.cpp:
     25        (WebCore::JSExecState::didLeaveScriptContext):
     26        * bindings/js/JSRemoteDOMWindowBase.cpp:
     27        * bindings/js/JSWorkerGlobalScopeBase.cpp:
     28        (WebCore::JSWorkerGlobalScopeBase::queueMicrotaskToEventLoop): Renamed from queueTaskToEventLoop.
     29        * bindings/js/JSWorkerGlobalScopeBase.h:
     30        * bindings/js/JSWorkletGlobalScopeBase.cpp:
     31        * bindings/js/JSWorkletGlobalScopeBase.h:
     32        * dom/CustomElementReactionQueue.cpp:
     33        (WebCore::BackupElementQueueMicrotask): Deleted.
     34        (WebCore::CustomElementReactionQueue::enqueueElementOnAppropriateElementQueue):
     35        (WebCore::CustomElementReactionQueue::ensureBackupQueue):
     36        * dom/CustomElementReactionQueue.h:
     37        * dom/Document.cpp:
     38        (WebCore::Document::finishedParsing):
     39        * dom/DocumentStorageAccess.cpp:
     40        (WebCore::DocumentStorageAccess::requestStorageAccess):
     41        * dom/EventLoop.cpp:
     42        (WebCore::EventLoop::queueMicrotask): Added.
     43        (WebCore::EventLoop::performMicrotaskCheckpoint): Added.
     44        (WebCore::EventLoopTaskGroup::queueMicrotaskCallback): Added.
     45        (WebCore::EventLoopTaskGroup::queueMicrotask): Added.
     46        (WebCore::EventLoopTaskGroup::performMicrotaskCheckpoint): Added.
     47        * dom/EventLoop.h:
     48        (WebCore::EventLoopTaskGroup::microtaskQueue):
     49        * dom/Microtasks.cpp:
     50        (WebCore::MicrotaskQueue::mainThreadQueue): Deleted.
     51        (WebCore::MicrotaskQueue::contextQueue): Deleted.
     52        * dom/Microtasks.h:
     53        * dom/MutationObserver.cpp:
     54        (WebCore::MutationObserverMicrotask): Deleted.
     55        (WebCore::MutationObserver::queueMutationObserverCompoundMicrotask): Made this a member function
     56        so that it can call notifyMutationObservers in its lambda.
     57        (WebCore::MutationObserver::enqueueMutationRecord):
     58        (WebCore::MutationObserver::enqueueSlotChangeEvent):
     59        (WebCore::MutationObserver::setHasTransientRegistration):
     60        * dom/MutationObserver.h:
     61        * dom/MutationObserverRegistration.cpp:
     62        (WebCore::MutationObserverRegistration::observedSubtreeNodeWillDetach):
     63        * dom/WindowEventLoop.cpp:
     64        (WebCore::WindowEventLoop::microtaskQueue):
     65        * dom/WindowEventLoop.h:
     66        * html/parser/HTMLDocumentParser.cpp:
     67        (WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder):
     68        * html/parser/HTMLScriptRunner.cpp:
     69        (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent):
     70        (WebCore::HTMLScriptRunner::runScript):
     71        * inspector/agents/InspectorCanvasAgent.cpp:
     72        (WebCore::InspectorCanvasAgent::recordCanvasAction):
     73        * testing/Internals.cpp:
     74        (WebCore::Internals::queueMicroTask):
     75        * workers/WorkerEventLoop.cpp:
     76        (WebCore::WorkerEventLoop::~WorkerEventLoop):
     77        (WebCore::WorkerEventLoop::microtaskQueue):
     78        (WebCore::WorkerEventLoop::clearMicrotaskQueue):
     79        * workers/WorkerEventLoop.h:
     80        * workers/WorkerGlobalScope.cpp:
     81        (WebCore::WorkerGlobalScope::WorkerGlobalScope):
     82        (WebCore::WorkerGlobalScope::prepareForTermination):
     83        * workers/WorkerGlobalScope.h:
     84        (WebCore::WorkerGlobalScope::microtaskQueue const): Deleted.
     85
    1862019-11-20  Wenson Hsieh  <wenson_hsieh@apple.com>
    287
  • trunk/Source/WebCore/animation/DocumentTimeline.cpp

    r252527 r252723  
    3333#include "DeclarativeAnimation.h"
    3434#include "Document.h"
     35#include "EventLoop.h"
    3536#include "EventNames.h"
    3637#include "GraphicsLayer.h"
     
    389390
    390391    // 3. Perform a microtask checkpoint.
    391     MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
     392    if (auto document = makeRefPtr(this->document()))
     393        document->eventLoop().performMicrotaskCheckpoint();
    392394
    393395    // 4. Let events to dispatch be a copy of doc's pending animation event queue.
  • trunk/Source/WebCore/animation/WebAnimation.cpp

    r252658 r252723  
    797797            // is already a microtask queued to run those steps for animation.
    798798            m_finishNotificationStepsMicrotaskPending = true;
    799             MicrotaskQueue::mainThreadQueue().append(makeUnique<VoidMicrotask>([this, protectedThis = makeRef(*this)] () {
    800                 if (m_finishNotificationStepsMicrotaskPending) {
    801                     m_finishNotificationStepsMicrotaskPending = false;
    802                     finishNotificationSteps();
    803                 }
    804             }));
     799            if (auto* context = scriptExecutionContext()) {
     800                context->eventLoop().queueMicrotask([this, protectedThis = makeRef(*this)] {
     801                    if (m_finishNotificationStepsMicrotaskPending) {
     802                        m_finishNotificationStepsMicrotaskPending = false;
     803                        finishNotificationSteps();
     804                    }
     805                });
     806            }
    805807        }
    806808    }
  • trunk/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp

    r251425 r252723  
    3939class JSGlobalObjectCallback final : public RefCounted<JSGlobalObjectCallback>, private ActiveDOMCallback {
    4040public:
    41     static Ref<JSGlobalObjectCallback> create(JSDOMGlobalObject& globalObject, Ref<Microtask>&& task)
     41    static Ref<JSGlobalObjectCallback> create(JSDOMGlobalObject& globalObject, Ref<JSC::Microtask>&& task)
    4242    {
    4343        return adoptRef(*new JSGlobalObjectCallback(globalObject, WTFMove(task)));
     
    6565
    6666private:
    67     JSGlobalObjectCallback(JSDOMGlobalObject& globalObject, Ref<Microtask>&& task)
     67    JSGlobalObjectCallback(JSDOMGlobalObject& globalObject, Ref<JSC::Microtask>&& task)
    6868        : ActiveDOMCallback { globalObject.scriptExecutionContext() }
    6969        , m_globalObject { globalObject.vm(), &globalObject }
     
    7373
    7474    Strong<JSDOMGlobalObject> m_globalObject;
    75     Ref<Microtask> m_task;
     75    Ref<JSC::Microtask> m_task;
    7676};
    7777
    78 JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject& globalObject, Ref<Microtask>&& task)
     78JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject& globalObject, Ref<JSC::Microtask>&& task)
    7979    : ScriptExecutionContext::Task({ })
    8080{
  • trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp

    r251691 r252723  
    3030#include "DOMWindow.h"
    3131#include "Document.h"
     32#include "EventLoop.h"
    3233#include "FetchResponse.h"
    3334#include "Frame.h"
     
    7172    &shouldInterruptScript,
    7273    &javaScriptRuntimeFlags,
    73     &queueTaskToEventLoop,
     74    &queueMicrotaskToEventLoop,
    7475    &shouldInterruptScriptBeforeTimeout,
    7576    &moduleLoaderImportModule,
     
    205206}
    206207
    207 void JSDOMWindowBase::queueTaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
     208void JSDOMWindowBase::queueMicrotaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
    208209{
    209210    JSDOMWindowBase& thisObject = static_cast<JSDOMWindowBase&>(object);
    210211
    211212    auto callback = JSMicrotaskCallback::create(thisObject, WTFMove(task));
    212     auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(MicrotaskQueue::mainThreadQueue(), *thisObject.scriptExecutionContext(), [callback = WTFMove(callback)]() mutable {
     213    auto& eventLoop = thisObject.scriptExecutionContext()->eventLoop();
     214    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(eventLoop.microtaskQueue(), *thisObject.scriptExecutionContext(), [callback = WTFMove(callback)]() mutable {
    213215        callback->call();
    214216    });
    215 
    216     MicrotaskQueue::mainThreadQueue().append(WTFMove(microtask));
     217    eventLoop.queueMicrotaskCallback(WTFMove(microtask));
    217218}
    218219
  • trunk/Source/WebCore/bindings/js/JSDOMWindowBase.h

    r251691 r252723  
    7878    static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*);
    7979    static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
    80     static void queueTaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
     80    static void queueMicrotaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
    8181
    8282    void printErrorMessage(const String&) const;
  • trunk/Source/WebCore/bindings/js/JSExecState.cpp

    r251425 r252723  
    2727#include "JSExecState.h"
    2828
     29#include "EventLoop.h"
    2930#include "Microtasks.h"
    3031#include "RejectedPromiseTracker.h"
     
    4041    if (!context)
    4142        return;
    42     MicrotaskQueue::contextQueue(*context).performMicrotaskCheckpoint();
     43    context->eventLoop().performMicrotaskCheckpoint();
    4344    context->ensureRejectedPromiseTracker().processQueueSoon();
    4445}
  • trunk/Source/WebCore/bindings/js/JSRemoteDOMWindowBase.cpp

    r231194 r252723  
    4040    nullptr, // shouldInterruptScript
    4141    &javaScriptRuntimeFlags,
    42     nullptr, // queueTaskToEventLoop
     42    nullptr, // queueMicrotaskToEventLoop
    4343    nullptr, // shouldInterruptScriptBeforeTimeout
    4444    nullptr, // moduleLoaderImportModule
  • trunk/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp

    r251425 r252723  
    3131#include "ActiveDOMCallbackMicrotask.h"
    3232#include "DOMWrapperWorld.h"
     33#include "EventLoop.h"
    3334#include "JSDOMGlobalObjectTask.h"
    3435#include "JSDOMGuardedObject.h"
     
    5859    &shouldInterruptScript,
    5960    &javaScriptRuntimeFlags,
    60     &queueTaskToEventLoop,
     61    &queueMicrotaskToEventLoop,
    6162    &shouldInterruptScriptBeforeTimeout,
    6263    nullptr, // moduleLoaderImportModule
     
    131132}
    132133
    133 void JSWorkerGlobalScopeBase::queueTaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
     134void JSWorkerGlobalScopeBase::queueMicrotaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
    134135{
    135136    JSWorkerGlobalScopeBase& thisObject = static_cast<JSWorkerGlobalScopeBase&>(object);
     
    137138    auto callback = JSMicrotaskCallback::create(thisObject, WTFMove(task));
    138139    auto& context = thisObject.wrapped();
    139     auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(context.microtaskQueue(), context, [callback = WTFMove(callback)]() mutable {
     140    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(context.eventLoop().microtaskQueue(), context, [callback = WTFMove(callback)]() mutable {
    140141        callback->call();
    141142    });
    142 
    143     context.microtaskQueue().append(WTFMove(microtask));
     143    context.eventLoop().queueMicrotaskCallback(WTFMove(microtask));
    144144}
    145145
  • trunk/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h

    r251425 r252723  
    7070    static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*);
    7171    static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
    72     static void queueTaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
     72    static void queueMicrotaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
    7373
    7474    void clearDOMGuardedObjects();
  • trunk/Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.cpp

    r251425 r252723  
    5050    &shouldInterruptScript,
    5151    &javaScriptRuntimeFlags,
    52     nullptr, // queueTaskToEventLoop
     52    nullptr, // queueMicrotaskToEventLoop
    5353    &shouldInterruptScriptBeforeTimeout,
    5454    nullptr, // moduleLoaderImportModule
  • trunk/Source/WebCore/bindings/js/JSWorkletGlobalScopeBase.h

    r251425 r252723  
    6060    static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*);
    6161    static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
    62     static void queueTaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
     62    static void queueMicrotaskToEventLoop(JSC::JSGlobalObject&, Ref<JSC::Microtask>&&);
    6363
    6464    void clearDOMGuardedObjects();
  • trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp

    r251425 r252723  
    3131#include "Document.h"
    3232#include "Element.h"
     33#include "EventLoop.h"
    3334#include "HTMLNames.h"
    3435#include "JSCustomElementInterface.h"
     
    294295    ASSERT(element.reactionQueue());
    295296    if (!CustomElementReactionStack::s_currentProcessingStack) {
    296         auto& queue = ensureBackupQueue();
     297        auto& queue = ensureBackupQueue(element.document());
    297298        queue.add(element);
    298299        return;
     
    319320}
    320321
    321 class BackupElementQueueMicrotask final : public Microtask {
    322     WTF_MAKE_FAST_ALLOCATED;
    323 private:
    324     Result run() final
    325     {
    326         CustomElementReactionQueue::processBackupQueue();
    327         return Result::Done;
    328     }
    329 };
    330 
    331322static bool s_processingBackupElementQueue = false;
    332323
    333 CustomElementReactionQueue::ElementQueue& CustomElementReactionQueue::ensureBackupQueue()
     324// FIXME: BackupQueue must be per event loop.
     325CustomElementReactionQueue::ElementQueue& CustomElementReactionQueue::ensureBackupQueue(Document& document)
    334326{
    335327    if (!s_processingBackupElementQueue) {
    336328        s_processingBackupElementQueue = true;
    337         MicrotaskQueue::mainThreadQueue().append(makeUnique<BackupElementQueueMicrotask>());
     329        document.eventLoop().queueMicrotask([] {
     330            CustomElementReactionQueue::processBackupQueue();
     331        });
    338332    }
    339333    return backupElementQueue();
  • trunk/Source/WebCore/dom/CustomElementReactionQueue.h

    r251425 r252723  
    8181private:
    8282    static void enqueueElementOnAppropriateElementQueue(Element&);
    83     static ElementQueue& ensureBackupQueue();
     83    static ElementQueue& ensureBackupQueue(Document&);
    8484    static ElementQueue& backupElementQueue();
    8585
  • trunk/Source/WebCore/dom/Document.cpp

    r252667 r252723  
    57945794    if (!page() || !page()->isForSanitizingWebContent()) {
    57955795        // FIXME: Schedule a task to fire DOMContentLoaded event instead. See webkit.org/b/82931
    5796         MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
     5796        eventLoop().performMicrotaskCheckpoint();
    57975797    }
    57985798
  • trunk/Source/WebCore/dom/DocumentStorageAccess.cpp

    r251361 r252723  
    3232#include "ChromeClient.h"
    3333#include "Document.h"
     34#include "EventLoop.h"
    3435#include "Frame.h"
    3536#include "FrameLoader.h"
    3637#include "FrameLoaderClient.h"
    3738#include "JSDOMPromiseDeferred.h"
    38 #include "Microtasks.h"
    3939#include "Page.h"
    4040#include "RegistrableDomain.h"
     
    183183
    184184        if (shouldPreserveUserGesture) {
    185             MicrotaskQueue::mainThreadQueue().append(makeUnique<VoidMicrotask>([this, weakThis] () {
     185            m_document.eventLoop().queueMicrotask([this, weakThis = makeWeakPtr(*this)] {
    186186                if (weakThis)
    187187                    enableTemporaryTimeUserGesture();
    188             }));
     188            });
    189189        }
    190190
     
    198198
    199199        if (shouldPreserveUserGesture) {
    200             MicrotaskQueue::mainThreadQueue().append(makeUnique<VoidMicrotask>([this, weakThis = WTFMove(weakThis)] () {
     200            m_document.eventLoop().queueMicrotask([this, weakThis = makeWeakPtr(*this)] {
    201201                if (weakThis)
    202202                    consumeTemporaryTimeUserGesture();
    203             }));
     203            });
    204204        }
    205205    });
  • trunk/Source/WebCore/dom/EventLoop.cpp

    r252646 r252723  
    2727#include "EventLoop.h"
    2828
     29#include "ActiveDOMCallbackMicrotask.h"
     30#include "Microtasks.h"
     31
    2932namespace WebCore {
    3033
     
    3538    scheduleToRunIfNeeded();
    3639    m_tasks.append(WTFMove(task));
     40}
     41
     42void EventLoop::queueMicrotask(std::unique_ptr<Microtask>&& microtask)
     43{
     44    microtaskQueue().append(WTFMove(microtask));
     45}
     46
     47void EventLoop::performMicrotaskCheckpoint()
     48{
     49    microtaskQueue().performMicrotaskCheckpoint();
    3750}
    3851
     
    121134}
    122135
     136void EventLoopTaskGroup::queueMicrotaskCallback(std::unique_ptr<ActiveDOMCallbackMicrotask>&& microtask)
     137{
     138    if (m_state == State::Stopped || !m_eventLoop)
     139        return;
     140    m_eventLoop->queueMicrotask(WTFMove(microtask));
     141}
     142
     143class VoidMicrotask final : public Microtask {
     144public:
     145    explicit VoidMicrotask(Function<void()>&& function)
     146        : m_function(WTFMove(function))
     147    {
     148    }
     149
     150private:
     151    Result run() final
     152    {
     153        m_function();
     154        return Result::Done;
     155    }
     156
     157    Function<void()> m_function;
     158};
     159
     160void EventLoopTaskGroup::queueMicrotask(EventLoop::TaskFunction&& function)
     161{
     162    if (m_state == State::Stopped || !m_eventLoop)
     163        return;
     164    m_eventLoop->queueMicrotask(makeUnique<VoidMicrotask>(WTFMove(function)));
     165}
     166
     167void EventLoopTaskGroup::performMicrotaskCheckpoint()
     168{
     169    if (m_eventLoop)
     170        m_eventLoop->performMicrotaskCheckpoint();
     171}
     172
    123173} // namespace WebCore
  • trunk/Source/WebCore/dom/EventLoop.h

    r252646 r252723  
    3535namespace WebCore {
    3636
     37class ActiveDOMCallbackMicrotask;
    3738class EventLoopTaskGroup;
    3839class EventTarget;
     40class Microtask;
     41class MicrotaskQueue;
    3942class ScriptExecutionContext;
    4043
     
    6669    typedef Function<void ()> TaskFunction;
    6770    void queueTask(std::unique_ptr<EventLoopTask>&&);
     71
     72    // https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-microtask
     73    void queueMicrotask(std::unique_ptr<Microtask>&&);
     74
     75    // https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
     76    void performMicrotaskCheckpoint();
     77    virtual MicrotaskQueue& microtaskQueue() = 0;
    6878
    6979    void resumeGroup(EventLoopTaskGroup&);
     
    131141    WEBCORE_EXPORT void queueTask(TaskSource, EventLoop::TaskFunction&&);
    132142
     143    // https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-microtask
     144    void queueMicrotask(EventLoop::TaskFunction&&);
     145    MicrotaskQueue& microtaskQueue() { return m_eventLoop->microtaskQueue(); }
     146
     147    // FIXME: This function and ActiveDOMCallbackMicrotask should go away.
     148    WEBCORE_EXPORT void queueMicrotaskCallback(std::unique_ptr<ActiveDOMCallbackMicrotask>&&);
     149
     150    // https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
     151    void performMicrotaskCheckpoint();
     152
    133153private:
    134154    enum class State : uint8_t { Running, Suspended, Stopped };
  • trunk/Source/WebCore/dom/Microtasks.cpp

    r246565 r252723  
    4343
    4444MicrotaskQueue::~MicrotaskQueue() = default;
    45 
    46 MicrotaskQueue& MicrotaskQueue::mainThreadQueue()
    47 {
    48     ASSERT(isMainThread());
    49     static NeverDestroyed<MicrotaskQueue> queue(commonVM());
    50     return queue;
    51 }
    52 
    53 MicrotaskQueue& MicrotaskQueue::contextQueue(ScriptExecutionContext& context)
    54 {
    55     // While main thread has many ScriptExecutionContexts, WorkerGlobalScope and worker thread have
    56     // one on one correspondence. The lifetime of MicrotaskQueue is aligned to this semantics.
    57     // While main thread MicrotaskQueue is persistently held, worker's MicrotaskQueue is held by
    58     // WorkerGlobalScope.
    59     if (isMainThread())
    60         return mainThreadQueue();
    61     return downcast<WorkerGlobalScope>(context).microtaskQueue();
    62 }
    6345
    6446void MicrotaskQueue::append(std::unique_ptr<Microtask>&& task)
  • trunk/Source/WebCore/dom/Microtasks.h

    r248762 r252723  
    5353};
    5454
    55 class VoidMicrotask final : public Microtask {
    56 public:
    57     explicit VoidMicrotask(Function<void()>&& function)
    58         : m_function(WTFMove(function))
    59     {
    60     }
    61 
    62 private:
    63     Result run() final
    64     {
    65         m_function();
    66         return Result::Done;
    67     }
    68 
    69     Function<void()> m_function;
    70 };
    71 
    7255class MicrotaskQueue final {
    7356    WTF_MAKE_FAST_ALLOCATED;
     
    7558    friend class Microtask;
    7659public:
    77     WEBCORE_EXPORT static MicrotaskQueue& mainThreadQueue();
    78     WEBCORE_EXPORT static MicrotaskQueue& contextQueue(ScriptExecutionContext&);
    79 
    8060    WEBCORE_EXPORT MicrotaskQueue(JSC::VM&);
    8161    WEBCORE_EXPORT ~MicrotaskQueue();
  • trunk/Source/WebCore/dom/MutationObserver.cpp

    r250672 r252723  
    3535
    3636#include "Document.h"
     37#include "EventLoop.h"
    3738#include "GCReachableRef.h"
    3839#include "HTMLSlotElement.h"
     
    159160}
    160161
    161 static bool mutationObserverCompoundMicrotaskQueuedFlag;
    162 
    163 class MutationObserverMicrotask final : public Microtask {
    164     WTF_MAKE_FAST_ALLOCATED;
    165 private:
    166     Result run() final
    167     {
    168         MutationObserver::notifyMutationObservers();
    169         return Result::Done;
    170     }
    171 };
    172 
    173 static void queueMutationObserverCompoundMicrotask()
     162// This state must be per event loop.
     163static bool mutationObserverCompoundMicrotaskQueuedFlag = false;
     164
     165void MutationObserver::queueMutationObserverCompoundMicrotask(Document& document)
    174166{
    175167    if (mutationObserverCompoundMicrotaskQueuedFlag)
    176168        return;
    177169    mutationObserverCompoundMicrotaskQueuedFlag = true;
    178     MicrotaskQueue::mainThreadQueue().append(makeUnique<MutationObserverMicrotask>());
     170    document.eventLoop().queueMicrotask([] {
     171        notifyMutationObservers();
     172    });
    179173}
    180174
     
    183177    ASSERT(isMainThread());
    184178    ASSERT(mutation->target());
     179    auto document = makeRef(mutation->target()->document());
     180
    185181    m_pendingTargets.add(*mutation->target());
    186182    m_records.append(WTFMove(mutation));
    187183    activeMutationObservers().add(this);
    188184
    189     queueMutationObserverCompoundMicrotask();
     185    queueMutationObserverCompoundMicrotask(document.get());
    190186}
    191187
     
    196192    signalSlotList().append(slot);
    197193
    198     queueMutationObserverCompoundMicrotask();
    199 }
    200 
    201 void MutationObserver::setHasTransientRegistration()
     194    queueMutationObserverCompoundMicrotask(slot.document());
     195}
     196
     197void MutationObserver::setHasTransientRegistration(Document& document)
    202198{
    203199    ASSERT(isMainThread());
    204200    activeMutationObservers().add(this);
    205201
    206     queueMutationObserverCompoundMicrotask();
     202    queueMutationObserverCompoundMicrotask(document);
    207203}
    208204
  • trunk/Source/WebCore/dom/MutationObserver.h

    r239427 r252723  
    4141namespace WebCore {
    4242
     43class Document;
    4344class HTMLSlotElement;
    4445class MutationCallback;
     
    5253class MutationObserver final : public RefCounted<MutationObserver> {
    5354    WTF_MAKE_ISO_ALLOCATED(MutationObserver);
    54     friend class MutationObserverMicrotask;
    5555public:
    5656    enum MutationType {
     
    9898    void observationEnded(MutationObserverRegistration&);
    9999    void enqueueMutationRecord(Ref<MutationRecord>&&);
    100     void setHasTransientRegistration();
     100    void setHasTransientRegistration(Document&);
    101101    bool canDeliver();
    102102
     
    111111    void deliver();
    112112
     113    static void queueMutationObserverCompoundMicrotask(Document&);
    113114    static void notifyMutationObservers();
    114115    static bool validateOptions(MutationObserverOptions);
  • trunk/Source/WebCore/dom/MutationObserverRegistration.cpp

    r248846 r252723  
    6666
    6767    node.registerTransientMutationObserver(*this);
    68     m_observer->setHasTransientRegistration();
     68    m_observer->setHasTransientRegistration(node.document());
    6969
    7070    if (!m_transientRegistrationNodes) {
  • trunk/Source/WebCore/dom/WindowEventLoop.cpp

    r252646 r252723  
    2727#include "WindowEventLoop.h"
    2828
     29#include "CommonVM.h"
    2930#include "Document.h"
     31#include "Microtasks.h"
    3032
    3133namespace WebCore {
     
    7274}
    7375
     76MicrotaskQueue& WindowEventLoop::microtaskQueue()
     77{
     78    // MicrotaskQueue must be one per event loop.
     79    static NeverDestroyed<MicrotaskQueue> queue(commonVM());
     80    return queue;
     81}
     82
    7483} // namespace WebCore
  • trunk/Source/WebCore/dom/WindowEventLoop.h

    r252646 r252723  
    4040    static Ref<WindowEventLoop> ensureForRegistrableDomain(const RegistrableDomain&);
    4141
    42     ~WindowEventLoop();
     42    virtual ~WindowEventLoop();
    4343
    4444private:
     
    4747    void scheduleToRun() final;
    4848    bool isContextThread() const final;
     49    MicrotaskQueue& microtaskQueue() final;
    4950
    5051    RegistrableDomain m_domain;
  • trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp

    r248846 r252723  
    3232#include "DocumentFragment.h"
    3333#include "DocumentLoader.h"
     34#include "EventLoop.h"
    3435#include "Frame.h"
    3536#include "HTMLDocument.h"
     
    4142#include "JSCustomElementInterface.h"
    4243#include "LinkLoader.h"
    43 #include "Microtasks.h"
    4444#include "NavigationScheduler.h"
    4545#include "ScriptElement.h"
     
    217217            ThrowOnDynamicMarkupInsertionCountIncrementer incrementer(*document());
    218218
    219             MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
     219            document()->eventLoop().performMicrotaskCheckpoint();
    220220
    221221            CustomElementReactionStack reactionStack(document()->execState());
  • trunk/Source/WebCore/html/parser/HTMLScriptRunner.cpp

    r243459 r252723  
    3030#include "Element.h"
    3131#include "Event.h"
     32#include "EventLoop.h"
    3233#include "EventNames.h"
    3334#include "Frame.h"
     
    3738#include "IgnoreDestructiveWriteCountIncrementer.h"
    3839#include "InlineClassicScript.h"
    39 #include "Microtasks.h"
    4040#include "MutationObserver.h"
    4141#include "NestingLevelIncrementer.h"
     
    107107        stopWatchingForLoad(pendingScript);
    108108
    109     if (!isExecutingScript())
    110         MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
     109    if (!isExecutingScript() && m_document)
     110        m_document->eventLoop().performMicrotaskCheckpoint();
    111111
    112112    {
     
    242242    // unfortunately no obvious way to tell if prepareScript is going to
    243243    // execute the script before calling it.
    244     if (!isExecutingScript())
    245         MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
     244    if (!isExecutingScript() && m_document)
     245        m_document->eventLoop().performMicrotaskCheckpoint();
    246246
    247247    InsertionPointRecord insertionPointRecord(m_host.inputStream());
  • trunk/Source/WebCore/inspector/agents/InspectorCanvasAgent.cpp

    r251630 r252723  
    3232#include "Document.h"
    3333#include "Element.h"
     34#include "EventLoop.h"
    3435#include "Frame.h"
    3536#include "HTMLCanvasElement.h"
     
    454455    if (!inspectorCanvas->currentFrameHasData()) {
    455456        if (auto* scriptExecutionContext = inspectorCanvas->scriptExecutionContext()) {
    456             auto& queue = MicrotaskQueue::mainThreadQueue();
    457             queue.append(makeUnique<ActiveDOMCallbackMicrotask>(queue, *scriptExecutionContext, [&, protectedInspectorCanvas = inspectorCanvas.copyRef()] {
     457            auto& eventLoop = scriptExecutionContext->eventLoop();
     458            auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(eventLoop.microtaskQueue(), *scriptExecutionContext, [&, protectedInspectorCanvas = inspectorCanvas.copyRef()] {
    458459                if (auto* canvasElement = protectedInspectorCanvas->canvasElement()) {
    459460                    if (canvasElement->isDescendantOf(canvasElement->document()))
     
    463464                if (canvasRenderingContext.callTracingActive())
    464465                    didFinishRecordingCanvasFrame(canvasRenderingContext);
    465             }));
     466            });
     467            eventLoop.queueMicrotaskCallback(WTFMove(microtask));
    466468        }
    467469    }
  • trunk/Source/WebCore/testing/Internals.cpp

    r252646 r252723  
    43284328        return;
    43294329
    4330     auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(MicrotaskQueue::mainThreadQueue(), *document, [document, testNumber]() {
     4330    ScriptExecutionContext* context = document;
     4331    auto& eventLoop = context->eventLoop();
     4332    auto microtask = makeUnique<ActiveDOMCallbackMicrotask>(eventLoop.microtaskQueue(), *document, [document, testNumber]() {
    43314333        document->addConsoleMessage(MessageSource::JS, MessageLevel::Debug, makeString("MicroTask #", testNumber, " has run."));
    43324334    });
    4333 
    4334     MicrotaskQueue::mainThreadQueue().append(WTFMove(microtask));
     4335    eventLoop.queueMicrotaskCallback(WTFMove(microtask));
    43354336}
    43364337
  • trunk/Source/WebCore/workers/WorkerEventLoop.cpp

    r252607 r252723  
    2727#include "WorkerEventLoop.h"
    2828
     29#include "Microtasks.h"
    2930#include "WorkerGlobalScope.h"
    3031#include "WorkletGlobalScope.h"
     
    4950}
    5051
     52WorkerEventLoop::~WorkerEventLoop()
     53{
     54}
     55
    5156void WorkerEventLoop::scheduleToRun()
    5257{
     
    6267}
    6368
     69MicrotaskQueue& WorkerEventLoop::microtaskQueue()
     70{
     71    ASSERT(scriptExecutionContext());
     72    if (!m_microtaskQueue)
     73        m_microtaskQueue = makeUnique<MicrotaskQueue>(scriptExecutionContext()->vm());
     74    return *m_microtaskQueue;
     75}
     76
     77void WorkerEventLoop::clearMicrotaskQueue()
     78{
     79    m_microtaskQueue = nullptr;
     80}
     81
    6482} // namespace WebCore
    6583
  • trunk/Source/WebCore/workers/WorkerEventLoop.h

    r252646 r252723  
    4343#endif
    4444
     45    virtual ~WorkerEventLoop();
     46
     47    // FIXME: This should be removed once MicrotaskQueue is integrated with EventLoopTaskGroup.
     48    void clearMicrotaskQueue();
     49
    4550private:
    4651    explicit WorkerEventLoop(ScriptExecutionContext&);
     
    4853    void scheduleToRun() final;
    4954    bool isContextThread() const;
     55    MicrotaskQueue& microtaskQueue() final;
     56
     57    std::unique_ptr<MicrotaskQueue> m_microtaskQueue;
    5058};
    5159
  • trunk/Source/WebCore/workers/WorkerGlobalScope.cpp

    r252607 r252723  
    6969    , m_script(makeUnique<WorkerScriptController>(this))
    7070    , m_inspectorController(makeUnique<WorkerInspectorController>(*this))
    71     , m_microtaskQueue(makeUnique<MicrotaskQueue>(m_script->vm()))
    7271    , m_isOnline(isOnline)
    7372    , m_shouldBypassMainWorldContentSecurityPolicy(shouldBypassMainWorldContentSecurityPolicy)
     
    144143
    145144    // MicrotaskQueue and RejectedPromiseTracker reference Heap.
    146     m_microtaskQueue = nullptr;
     145    if (m_eventLoop)
     146        m_eventLoop->clearMicrotaskQueue();
    147147    removeRejectedPromiseTracker();
    148148}
  • trunk/Source/WebCore/workers/WorkerGlobalScope.h

    r252607 r252723  
    4646class Crypto;
    4747class EventLoopTaskGroup;
    48 class MicrotaskQueue;
    4948class Performance;
    5049class ScheduledAction;
     
    9089
    9190    WorkerInspectorController& inspectorController() const { return *m_inspectorController; }
    92 
    93     MicrotaskQueue& microtaskQueue() const { return *m_microtaskQueue; }
    9491
    9592    WorkerThread& thread() const { return m_thread; }
     
    192189    std::unique_ptr<WorkerScriptController> m_script;
    193190    std::unique_ptr<WorkerInspectorController> m_inspectorController;
    194     std::unique_ptr<MicrotaskQueue> m_microtaskQueue;
    195191
    196192    bool m_closing { false };
  • trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp

    r252607 r252723  
    8181        m_defaultTaskGroup->stopAndDiscardAllTasks();
    8282    stopActiveDOMObjects();
     83    removeAllEventListeners();
     84    if (m_eventLoop)
     85        m_eventLoop->clearMicrotaskQueue();
    8386    removeRejectedPromiseTracker();
    84     removeAllEventListeners();
    8587    m_script->vm().notifyNeedTermination();
    8688    m_script = nullptr;
Note: See TracChangeset for help on using the changeset viewer.