Skip to content

Commit 5f6ef01

Browse files
committed
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. Canonical link: https://commits.webkit.org/217704@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252723 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent d3f96d9 commit 5f6ef01

34 files changed

Lines changed: 277 additions & 126 deletions

Source/WebCore/ChangeLog

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,88 @@
1+
2019-11-19 Ryosuke Niwa <[email protected]>
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+
186
2019-11-20 Wenson Hsieh <[email protected]>
287

388
Unreviewed, remove an unnecessary null check after r252561

Source/WebCore/animation/DocumentTimeline.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "DOMWindow.h"
3333
#include "DeclarativeAnimation.h"
3434
#include "Document.h"
35+
#include "EventLoop.h"
3536
#include "EventNames.h"
3637
#include "GraphicsLayer.h"
3738
#include "KeyframeEffect.h"
@@ -388,7 +389,8 @@ void DocumentTimeline::internalUpdateAnimationsAndSendEvents()
388389
removeReplacedAnimations();
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.
394396
// 5. Clear doc's pending animation event queue.

Source/WebCore/animation/WebAnimation.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -796,12 +796,14 @@ void WebAnimation::updateFinishedState(DidSeek didSeek, SynchronouslyNotify sync
796796
// Otherwise, if synchronously notify is false, queue a microtask to run finish notification steps for animation unless there
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
}
807809

Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ using namespace JSC;
3838

3939
class JSGlobalObjectCallback final : public RefCounted<JSGlobalObjectCallback>, private ActiveDOMCallback {
4040
public:
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)));
4444
}
@@ -64,18 +64,18 @@ class JSGlobalObjectCallback final : public RefCounted<JSGlobalObjectCallback>,
6464
}
6565

6666
private:
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 }
7070
, m_task { WTFMove(task) }
7171
{
7272
}
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)
78+
JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject& globalObject, Ref<JSC::Microtask>&& task)
7979
: ScriptExecutionContext::Task({ })
8080
{
8181
auto callback = JSGlobalObjectCallback::create(globalObject, WTFMove(task));

Source/WebCore/bindings/js/JSDOMWindowBase.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "CommonVM.h"
3030
#include "DOMWindow.h"
3131
#include "Document.h"
32+
#include "EventLoop.h"
3233
#include "FetchResponse.h"
3334
#include "Frame.h"
3435
#include "InspectorController.h"
@@ -70,7 +71,7 @@ const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = {
7071
&supportsRichSourceInfo,
7172
&shouldInterruptScript,
7273
&javaScriptRuntimeFlags,
73-
&queueTaskToEventLoop,
74+
&queueMicrotaskToEventLoop,
7475
&shouldInterruptScriptBeforeTimeout,
7576
&moduleLoaderImportModule,
7677
&moduleLoaderResolve,
@@ -204,16 +205,16 @@ RuntimeFlags JSDOMWindowBase::javaScriptRuntimeFlags(const JSGlobalObject* objec
204205
return frame->settings().javaScriptRuntimeFlags();
205206
}
206207

207-
void JSDOMWindowBase::queueTaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
208+
void 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

219220
void JSDOMWindowBase::willRemoveFromWindowProxy()

Source/WebCore/bindings/js/JSDOMWindowBase.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class WEBCORE_EXPORT JSDOMWindowBase : public JSDOMGlobalObject {
7777
static bool shouldInterruptScript(const JSC::JSGlobalObject*);
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;
8383

Source/WebCore/bindings/js/JSExecState.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "config.h"
2727
#include "JSExecState.h"
2828

29+
#include "EventLoop.h"
2930
#include "Microtasks.h"
3031
#include "RejectedPromiseTracker.h"
3132
#include "ScriptExecutionContext.h"
@@ -39,7 +40,7 @@ void JSExecState::didLeaveScriptContext(JSC::JSGlobalObject* lexicalGlobalObject
3940
ScriptExecutionContext* context = scriptExecutionContextFromExecState(lexicalGlobalObject);
4041
if (!context)
4142
return;
42-
MicrotaskQueue::contextQueue(*context).performMicrotaskCheckpoint();
43+
context->eventLoop().performMicrotaskCheckpoint();
4344
context->ensureRejectedPromiseTracker().processQueueSoon();
4445
}
4546

Source/WebCore/bindings/js/JSRemoteDOMWindowBase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const GlobalObjectMethodTable JSRemoteDOMWindowBase::s_globalObjectMethodTable =
3939
nullptr, // shellSupportsRichSourceInfo
4040
nullptr, // shouldInterruptScript
4141
&javaScriptRuntimeFlags,
42-
nullptr, // queueTaskToEventLoop
42+
nullptr, // queueMicrotaskToEventLoop
4343
nullptr, // shouldInterruptScriptBeforeTimeout
4444
nullptr, // moduleLoaderImportModule
4545
nullptr, // moduleLoaderResolve

Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "ActiveDOMCallbackMicrotask.h"
3232
#include "DOMWrapperWorld.h"
33+
#include "EventLoop.h"
3334
#include "JSDOMGlobalObjectTask.h"
3435
#include "JSDOMGuardedObject.h"
3536
#include "JSDedicatedWorkerGlobalScope.h"
@@ -57,7 +58,7 @@ const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable
5758
&supportsRichSourceInfo,
5859
&shouldInterruptScript,
5960
&javaScriptRuntimeFlags,
60-
&queueTaskToEventLoop,
61+
&queueMicrotaskToEventLoop,
6162
&shouldInterruptScriptBeforeTimeout,
6263
nullptr, // moduleLoaderImportModule
6364
nullptr, // moduleLoaderResolve
@@ -130,17 +131,16 @@ RuntimeFlags JSWorkerGlobalScopeBase::javaScriptRuntimeFlags(const JSGlobalObjec
130131
return thisObject->m_wrapped->thread().runtimeFlags();
131132
}
132133

133-
void JSWorkerGlobalScopeBase::queueTaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
134+
void JSWorkerGlobalScopeBase::queueMicrotaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
134135
{
135136
JSWorkerGlobalScopeBase& thisObject = static_cast<JSWorkerGlobalScopeBase&>(object);
136137

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

146146
JSValue toJS(JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject*, WorkerGlobalScope& workerGlobalScope)

Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class JSWorkerGlobalScopeBase : public JSDOMGlobalObject {
6969
static bool shouldInterruptScript(const JSC::JSGlobalObject*);
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();
7575

0 commit comments

Comments
 (0)