Title: [252607] trunk/Source/WebCore
Revision
252607
Author
[email protected]
Date
2019-11-18 16:54:57 -0800 (Mon, 18 Nov 2019)

Log Message

Share more code between WindowEventLoop and WorkerEventLoop by introducing EventLoopTaskGroup
https://bugs.webkit.org/show_bug.cgi?id=204263

Reviewed by Antti Koivisto.

This patch abstracts the logic in WindowEventLoop to deal with a set of tasks associated with
a particular documents all suspending, resuming, or stopping at the same time using a new abstraction
called EventLoopTaskGroup in order to group tasks for media code and elsewhere.

Each task is now represented as an instance of a concrete subclass of EventLoopTask, which has
a pure virtual execute() member function. Its primary purpose is to know EventLoopTaskGroup to which
each task belongs. One of subclasss, EventLoopFunctionDispatchTask, is used to store a callback function
and another subclass, ActiveDOMObjectEventDispatchTask, is used to dispatch an async event.

ScriptExecutionContext's eventLoop() method now returns EventLoopTaskGroup. Because this group is
specific to a given ScriptExecutionContext, we no longer have to pass the ScriptExecutionContext
in each call to queueTask everywhere in our codebase.

For now, I kept all the code in WindowEventLoop.cpp to make the patch reviewable. My plan is to create
a new cpp file (e.g. AbstractEventLoop.cpp) and move most of code there instead as a follow up.

No new tests since there should be no observable behavior change.

* Modules/encryptedmedia/MediaKeys.cpp:
(WebCore::MediaKeys::setServerCertificate):
* Modules/entriesapi/FileSystemDirectoryEntry.cpp:
(WebCore::FileSystemDirectoryEntry::getEntry):
* Modules/entriesapi/FileSystemDirectoryReader.cpp:
(WebCore::FileSystemDirectoryReader::readEntries):
* Modules/entriesapi/FileSystemEntry.cpp:
(WebCore::FileSystemEntry::getParent):
* Modules/entriesapi/FileSystemFileEntry.cpp:
(WebCore::FileSystemFileEntry::file):
* Modules/mediarecorder/MediaRecorder.cpp:
(WebCore::MediaRecorder::scheduleDeferredTask):
* Modules/notifications/Notification.cpp:
(WebCore::Notification::queueTask):
* Modules/webdatabase/Database.cpp:
(WebCore::Database::runTransaction):
* Modules/webdatabase/DatabaseManager.cpp:
(WebCore::DatabaseManager::openDatabase):
* Modules/webdatabase/SQLTransaction.cpp:
(WebCore::SQLTransaction::callErrorCallbackDueToInterruption):
(WebCore::SQLTransaction::deliverTransactionErrorCallback):
(WebCore::SQLTransaction::deliverSuccessCallback):
* bindings/js/JSDOMPromiseDeferred.cpp:
(WebCore::DeferredPromise::callFunction):
(WebCore::DeferredPromise::whenSettled):
* dom/AbstractEventLoop.h:
(WebCore::EventLoopTask): Added.
(WebCore::EventLoopTask::taskSource): Added.
(WebCore::EventLoopTask::group const): Added.
(WebCore::EventLoopTask::EventLoopTask): Added.
(WebCore::EventLoopTaskGroup): Added. This class represents a group of tasks. For now, each group is
a distinct ScriptExecutionContext.
(WebCore::EventLoopTaskGroup::matchesTask const): Added.
(WebCore::EventLoopTaskGroup::startRunning): Added.
(WebCore::EventLoopTaskGroup::stopAndDiscardAllTasks): Added.
(WebCore::EventLoopTaskGroup::suspend): Added.
(WebCore::EventLoopTaskGroup::resume): Added.
(WebCore::EventLoopTaskGroup::isStoppedPermanently): Added.
(WebCore::EventLoopTaskGroup::isSuspended): Added.
(WebCore::EventLoopTaskGroup::hasScheduledTasks const): Added.
(WebCore::EventLoopTaskGroup::queueTask): Added.
* dom/ActiveDOMObject.cpp:
(WebCore::ActiveDOMObject::queueTaskInEventLoop):
(WebCore::ActiveDOMObjectEventDispatchTask): Added; A subclass of EventLoopTask to dispatch an async event.
(WebCore::ActiveDOMObjectEventDispatchTask::ActiveDOMObjectEventDispatchTask): Added.
(WebCore::ActiveDOMObjectEventDispatchTask::~ActiveDOMObjectEventDispatchTask): Added.
(WebCore::ActiveDOMObject::queueTaskToDispatchEventInternal): Added.
* dom/ActiveDOMObject.h:
* dom/Document.cpp:
(WebCore::Document::suspendActiveDOMObjects):
(WebCore::Document::resumeActiveDOMObjects):
(WebCore::Document::stopActiveDOMObjects):
(WebCore::Document::eventLoop): Creates EventLoopTaskGroup for this document.
* dom/Document.h:
* dom/IdleCallbackController.cpp:
(WebCore::IdleCallbackController::queueTaskToStartIdlePeriod):
(WebCore::IdleCallbackController::queueTaskToInvokeIdleCallbacks):
* dom/ScriptExecutionContext.h:
* dom/WindowEventLoop.cpp:
(WebCore::AbstractEventLoop::queueTask): The implementation moved from WindowEventLoop to AbstractEventLoop.
(WebCore::AbstractEventLoop::suspend): Removed.
(WebCore::AbstractEventLoop::resumeGroup): Ditto.
(WebCore::AbstractEventLoop::stopGroup): Ditto.
(WebCore::WindowEventLoop::scheduleToRun): Renamed from WindowEventLoop::scheduleToRunIfNeeded.
(WebCore::AbstractEventLoop::scheduleToRunIfNeeded): Extracted from WindowEventLoop::scheduleToRunIfNeeded.
(WebCore::WindowEventLoop::isContextThread const): Added.
(WebCore::AbstractEventLoop::run): The implementation moved from WindowEventLoop to AbstractEventLoop.
(WebCore::AbstractEventLoop::clearAllTasks): Added.
(WebCore::EventLoopFunctionDispatchTask): Added; A subclass of EventLoopTask to call a function.
(WebCore::EventLoopFunctionDispatchTask::EventLoopFunctionDispatchTask): Added.
(WebCore::EventLoopTaskGroup::queueTask): Added.
* dom/WindowEventLoop.h:
* fileapi/FileReader.cpp:
(WebCore::FileReader::enqueueTask):
* testing/Internals.cpp:
(WebCore::Internals::queueTask):
* workers/WorkerEventLoop.cpp:
(WebCore::WorkerEventLoop::WorkerEventLoop):
(WebCore::WorkerEventLoop::queueTask): Deleted.
(WebCore::WorkerEventLoop::activeDOMObjectName const): Deleted.
(WebCore::WorkerEventLoop::suspend): Deleted.
(WebCore::WorkerEventLoop::resume): Deleted.
(WebCore::WorkerEventLoop::stop): Deleted.
(WebCore::WorkerEventLoop::scheduleToRun): Extracted from scheduleToRunIfNeeded.
(WebCore::WorkerEventLoop::scheduleToRunIfNeeded): Deleted.
(WebCore::WorkerEventLoop::run): Deleted.
(WebCore::WorkerEventLoop::isContextThread const): Added.
* workers/WorkerEventLoop.h:
(WebCore::WorkerEventLoop): This class is no longer an active DOM object. WorkerGlobalScope and WorkerGlobalScope
manually stop the task group associated with it.
* workers/WorkerGlobalScope.cpp:
(WebCore::WorkerGlobalScope::eventLoop): Create the default task group for this script execution context.
(WebCore::WorkerGlobalScope::prepareForTermination): Stop the default task group.
* workers/WorkerGlobalScope.h:
* worklets/WorkletGlobalScope.cpp:
(WebCore::WorkletGlobalScope::prepareForDestruction): Similar to WorkerGlobalScope::prepareForTermination.
(WebCore::WorkletGlobalScope::eventLoop): Similar to WorkerGlobalScope::eventLoop.
* worklets/WorkletGlobalScope.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (252606 => 252607)


--- trunk/Source/WebCore/ChangeLog	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/ChangeLog	2019-11-19 00:54:57 UTC (rev 252607)
@@ -1,3 +1,127 @@
+2019-11-15  Ryosuke Niwa  <[email protected]>
+
+        Share more code between WindowEventLoop and WorkerEventLoop by introducing EventLoopTaskGroup
+        https://bugs.webkit.org/show_bug.cgi?id=204263
+
+        Reviewed by Antti Koivisto.
+
+        This patch abstracts the logic in WindowEventLoop to deal with a set of tasks associated with
+        a particular documents all suspending, resuming, or stopping at the same time using a new abstraction
+        called EventLoopTaskGroup in order to group tasks for media code and elsewhere.
+
+        Each task is now represented as an instance of a concrete subclass of EventLoopTask, which has
+        a pure virtual execute() member function. Its primary purpose is to know EventLoopTaskGroup to which
+        each task belongs. One of subclasss, EventLoopFunctionDispatchTask, is used to store a callback function
+        and another subclass, ActiveDOMObjectEventDispatchTask, is used to dispatch an async event.
+
+        ScriptExecutionContext's eventLoop() method now returns EventLoopTaskGroup. Because this group is
+        specific to a given ScriptExecutionContext, we no longer have to pass the ScriptExecutionContext
+        in each call to queueTask everywhere in our codebase.
+
+        For now, I kept all the code in WindowEventLoop.cpp to make the patch reviewable. My plan is to create
+        a new cpp file (e.g. AbstractEventLoop.cpp) and move most of code there instead as a follow up.
+
+        No new tests since there should be no observable behavior change.
+
+        * Modules/encryptedmedia/MediaKeys.cpp:
+        (WebCore::MediaKeys::setServerCertificate):
+        * Modules/entriesapi/FileSystemDirectoryEntry.cpp:
+        (WebCore::FileSystemDirectoryEntry::getEntry):
+        * Modules/entriesapi/FileSystemDirectoryReader.cpp:
+        (WebCore::FileSystemDirectoryReader::readEntries):
+        * Modules/entriesapi/FileSystemEntry.cpp:
+        (WebCore::FileSystemEntry::getParent):
+        * Modules/entriesapi/FileSystemFileEntry.cpp:
+        (WebCore::FileSystemFileEntry::file):
+        * Modules/mediarecorder/MediaRecorder.cpp:
+        (WebCore::MediaRecorder::scheduleDeferredTask):
+        * Modules/notifications/Notification.cpp:
+        (WebCore::Notification::queueTask):
+        * Modules/webdatabase/Database.cpp:
+        (WebCore::Database::runTransaction):
+        * Modules/webdatabase/DatabaseManager.cpp:
+        (WebCore::DatabaseManager::openDatabase):
+        * Modules/webdatabase/SQLTransaction.cpp:
+        (WebCore::SQLTransaction::callErrorCallbackDueToInterruption):
+        (WebCore::SQLTransaction::deliverTransactionErrorCallback):
+        (WebCore::SQLTransaction::deliverSuccessCallback):
+        * bindings/js/JSDOMPromiseDeferred.cpp:
+        (WebCore::DeferredPromise::callFunction):
+        (WebCore::DeferredPromise::whenSettled):
+        * dom/AbstractEventLoop.h:
+        (WebCore::EventLoopTask): Added.
+        (WebCore::EventLoopTask::taskSource): Added.
+        (WebCore::EventLoopTask::group const): Added.
+        (WebCore::EventLoopTask::EventLoopTask): Added.
+        (WebCore::EventLoopTaskGroup): Added. This class represents a group of tasks. For now, each group is
+        a distinct ScriptExecutionContext.
+        (WebCore::EventLoopTaskGroup::matchesTask const): Added.
+        (WebCore::EventLoopTaskGroup::startRunning): Added.
+        (WebCore::EventLoopTaskGroup::stopAndDiscardAllTasks): Added.
+        (WebCore::EventLoopTaskGroup::suspend): Added.
+        (WebCore::EventLoopTaskGroup::resume): Added.
+        (WebCore::EventLoopTaskGroup::isStoppedPermanently): Added.
+        (WebCore::EventLoopTaskGroup::isSuspended): Added.
+        (WebCore::EventLoopTaskGroup::hasScheduledTasks const): Added.
+        (WebCore::EventLoopTaskGroup::queueTask): Added.
+        * dom/ActiveDOMObject.cpp:
+        (WebCore::ActiveDOMObject::queueTaskInEventLoop):
+        (WebCore::ActiveDOMObjectEventDispatchTask): Added; A subclass of EventLoopTask to dispatch an async event.
+        (WebCore::ActiveDOMObjectEventDispatchTask::ActiveDOMObjectEventDispatchTask): Added.
+        (WebCore::ActiveDOMObjectEventDispatchTask::~ActiveDOMObjectEventDispatchTask): Added.
+        (WebCore::ActiveDOMObject::queueTaskToDispatchEventInternal): Added.
+        * dom/ActiveDOMObject.h:
+        * dom/Document.cpp:
+        (WebCore::Document::suspendActiveDOMObjects):
+        (WebCore::Document::resumeActiveDOMObjects):
+        (WebCore::Document::stopActiveDOMObjects):
+        (WebCore::Document::eventLoop): Creates EventLoopTaskGroup for this document.
+        * dom/Document.h:
+        * dom/IdleCallbackController.cpp:
+        (WebCore::IdleCallbackController::queueTaskToStartIdlePeriod):
+        (WebCore::IdleCallbackController::queueTaskToInvokeIdleCallbacks):
+        * dom/ScriptExecutionContext.h:
+        * dom/WindowEventLoop.cpp:
+        (WebCore::AbstractEventLoop::queueTask): The implementation moved from WindowEventLoop to AbstractEventLoop.
+        (WebCore::AbstractEventLoop::suspend): Removed.
+        (WebCore::AbstractEventLoop::resumeGroup): Ditto.
+        (WebCore::AbstractEventLoop::stopGroup): Ditto.
+        (WebCore::WindowEventLoop::scheduleToRun): Renamed from WindowEventLoop::scheduleToRunIfNeeded.
+        (WebCore::AbstractEventLoop::scheduleToRunIfNeeded): Extracted from WindowEventLoop::scheduleToRunIfNeeded.
+        (WebCore::WindowEventLoop::isContextThread const): Added.
+        (WebCore::AbstractEventLoop::run): The implementation moved from WindowEventLoop to AbstractEventLoop.
+        (WebCore::AbstractEventLoop::clearAllTasks): Added.
+        (WebCore::EventLoopFunctionDispatchTask): Added; A subclass of EventLoopTask to call a function.
+        (WebCore::EventLoopFunctionDispatchTask::EventLoopFunctionDispatchTask): Added.
+        (WebCore::EventLoopTaskGroup::queueTask): Added.
+        * dom/WindowEventLoop.h:
+        * fileapi/FileReader.cpp:
+        (WebCore::FileReader::enqueueTask):
+        * testing/Internals.cpp:
+        (WebCore::Internals::queueTask):
+        * workers/WorkerEventLoop.cpp:
+        (WebCore::WorkerEventLoop::WorkerEventLoop):
+        (WebCore::WorkerEventLoop::queueTask): Deleted.
+        (WebCore::WorkerEventLoop::activeDOMObjectName const): Deleted.
+        (WebCore::WorkerEventLoop::suspend): Deleted.
+        (WebCore::WorkerEventLoop::resume): Deleted.
+        (WebCore::WorkerEventLoop::stop): Deleted.
+        (WebCore::WorkerEventLoop::scheduleToRun): Extracted from scheduleToRunIfNeeded.
+        (WebCore::WorkerEventLoop::scheduleToRunIfNeeded): Deleted.
+        (WebCore::WorkerEventLoop::run): Deleted.
+        (WebCore::WorkerEventLoop::isContextThread const): Added.
+        * workers/WorkerEventLoop.h:
+        (WebCore::WorkerEventLoop): This class is no longer an active DOM object. WorkerGlobalScope and WorkerGlobalScope
+        manually stop the task group associated with it.
+        * workers/WorkerGlobalScope.cpp:
+        (WebCore::WorkerGlobalScope::eventLoop): Create the default task group for this script execution context.
+        (WebCore::WorkerGlobalScope::prepareForTermination): Stop the default task group.
+        * workers/WorkerGlobalScope.h:
+        * worklets/WorkletGlobalScope.cpp:
+        (WebCore::WorkletGlobalScope::prepareForDestruction): Similar to WorkerGlobalScope::prepareForTermination.
+        (WebCore::WorkletGlobalScope::eventLoop): Similar to WorkerGlobalScope::eventLoop.
+        * worklets/WorkletGlobalScope.h:
+
 2019-11-18  Antti Koivisto  <[email protected]>
 
         Move RuleSet to Style namespace

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -106,7 +106,7 @@
     // 4. Let promise be a new promise.
     // 5. Run the following steps in parallel:
 
-    context.eventLoop().queueTask(TaskSource::Networking, context, [this, certificate = WTFMove(certificate), promise = WTFMove(promise)] () mutable {
+    context.eventLoop().queueTask(TaskSource::Networking, [this, certificate = WTFMove(certificate), promise = WTFMove(promise)] () mutable {
         // 5.1. Use this object's cdm instance to process certificate.
         if (m_instance->setServerCertificate(WTFMove(certificate)) == CDMInstance::Failed) {
             // 5.2. If the preceding step failed, resolve promise with a new DOMException whose name is the appropriate error name.

Modified: trunk/Source/WebCore/Modules/entriesapi/FileSystemDirectoryEntry.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/entriesapi/FileSystemDirectoryEntry.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/entriesapi/FileSystemDirectoryEntry.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -57,7 +57,7 @@
         auto* document = this->document();
         if (result.hasException()) {
             if (errorCallback && document) {
-                document->eventLoop().queueTask(TaskSource::Networking, *document, [errorCallback = WTFMove(errorCallback), exception = result.releaseException(), pendingActivity = WTFMove(pendingActivity)]() mutable {
+                document->eventLoop().queueTask(TaskSource::Networking, [errorCallback = WTFMove(errorCallback), exception = result.releaseException(), pendingActivity = WTFMove(pendingActivity)]() mutable {
                     errorCallback->handleEvent(DOMException::create(WTFMove(exception)));
                 });
             }
@@ -66,7 +66,7 @@
         auto entry = result.releaseReturnValue();
         if (!matches(entry)) {
             if (errorCallback && document) {
-                document->eventLoop().queueTask(TaskSource::Networking, *document, [errorCallback = WTFMove(errorCallback), pendingActivity = WTFMove(pendingActivity)]() mutable {
+                document->eventLoop().queueTask(TaskSource::Networking, [errorCallback = WTFMove(errorCallback), pendingActivity = WTFMove(pendingActivity)]() mutable {
                     errorCallback->handleEvent(DOMException::create(Exception { TypeMismatchError, "Entry at given path does not match expected type"_s }));
                 });
             }
@@ -73,7 +73,7 @@
             return;
         }
         if (successCallback && document) {
-            document->eventLoop().queueTask(TaskSource::Networking, *document, [successCallback = WTFMove(successCallback), entry = WTFMove(entry), pendingActivity = WTFMove(pendingActivity)]() mutable {
+            document->eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback), entry = WTFMove(entry), pendingActivity = WTFMove(pendingActivity)]() mutable {
                 successCallback->handleEvent(WTFMove(entry));
             });
         }

Modified: trunk/Source/WebCore/Modules/entriesapi/FileSystemDirectoryReader.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/entriesapi/FileSystemDirectoryReader.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/entriesapi/FileSystemDirectoryReader.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -89,7 +89,7 @@
             if (result.hasException()) {
                 m_error = result.releaseException();
                 if (errorCallback && document) {
-                    document->eventLoop().queueTask(TaskSource::Networking, *document, [this, errorCallback = WTFMove(errorCallback), pendingActivity = WTFMove(pendingActivity)]() mutable {
+                    document->eventLoop().queueTask(TaskSource::Networking, [this, errorCallback = WTFMove(errorCallback), pendingActivity = WTFMove(pendingActivity)]() mutable {
                         errorCallback->handleEvent(DOMException::create(*m_error));
                     });
                 }
@@ -97,7 +97,7 @@
             }
             m_isDone = true;
             if (document) {
-                document->eventLoop().queueTask(TaskSource::Networking, *document, [successCallback = WTFMove(successCallback), pendingActivity = WTFMove(pendingActivity), result = result.releaseReturnValue()]() mutable {
+                document->eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback), pendingActivity = WTFMove(pendingActivity), result = result.releaseReturnValue()]() mutable {
                     successCallback->handleEvent(WTFMove(result));
                 });
             }

Modified: trunk/Source/WebCore/Modules/entriesapi/FileSystemEntry.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/entriesapi/FileSystemEntry.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/entriesapi/FileSystemEntry.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -77,7 +77,7 @@
         if (!document)
             return;
 
-        document->eventLoop().queueTask(TaskSource::Networking, *document, [successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), result = WTFMove(result), pendingActivity = WTFMove(pendingActivity)]() mutable {
+        document->eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), result = WTFMove(result), pendingActivity = WTFMove(pendingActivity)]() mutable {
             if (result.hasException()) {
                 if (errorCallback)
                     errorCallback->handleEvent(DOMException::create(result.releaseException()));

Modified: trunk/Source/WebCore/Modules/entriesapi/FileSystemFileEntry.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/entriesapi/FileSystemFileEntry.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/entriesapi/FileSystemFileEntry.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -48,7 +48,7 @@
         if (!document)
             return;
 
-        document->eventLoop().queueTask(TaskSource::Networking, *document, [successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), result = WTFMove(result), pendingActivity = WTFMove(pendingActivity)]() mutable {
+        document->eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), result = WTFMove(result), pendingActivity = WTFMove(pendingActivity)]() mutable {
             if (result.hasException()) {
                 if (errorCallback)
                     errorCallback->handleEvent(DOMException::create(result.releaseException()));

Modified: trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -216,7 +216,7 @@
     if (!document)
         return;
 
-    document->eventLoop().queueTask(TaskSource::Networking, *document, [pendingActivity = makePendingActivity(*this), function = WTFMove(function)] {
+    document->eventLoop().queueTask(TaskSource::Networking, [pendingActivity = makePendingActivity(*this), function = WTFMove(function)] {
         function();
     });
 }

Modified: trunk/Source/WebCore/Modules/notifications/Notification.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/notifications/Notification.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/notifications/Notification.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -152,7 +152,7 @@
     if (!document)
         return;
 
-    document->eventLoop().queueTask(TaskSource::UserInteraction, *document, WTFMove(task));
+    document->eventLoop().queueTask(TaskSource::UserInteraction, WTFMove(task));
 }
 
 void Notification::dispatchShowEvent()

Modified: trunk/Source/WebCore/Modules/webdatabase/Database.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/webdatabase/Database.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/webdatabase/Database.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -689,7 +689,7 @@
     LockHolder locker(m_transactionInProgressMutex);
     if (!m_isTransactionQueueEnabled) {
         if (errorCallback) {
-            m_document->eventLoop().queueTask(TaskSource::Networking, m_document, [errorCallback = makeRef(*errorCallback)]() {
+            m_document->eventLoop().queueTask(TaskSource::Networking, [errorCallback = makeRef(*errorCallback)]() {
                 errorCallback->handleEvent(SQLError::create(SQLError::UNKNOWN_ERR, "database has been closed"));
             });
         }

Modified: trunk/Source/WebCore/Modules/webdatabase/DatabaseManager.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/webdatabase/DatabaseManager.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/webdatabase/DatabaseManager.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -210,7 +210,7 @@
     if (database->isNew() && creationCallback.get()) {
         LOG(StorageAPI, "Scheduling DatabaseCreationCallbackTask for database %p\n", database.get());
         database->setHasPendingCreationEvent(true);
-        database->m_document->eventLoop().queueTask(TaskSource::Networking, database->m_document, [creationCallback, database]() {
+        database->m_document->eventLoop().queueTask(TaskSource::Networking, [creationCallback, database]() {
             creationCallback->handleEvent(*database);
             database->setHasPendingCreationEvent(false);
         });

Modified: trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.cpp (252606 => 252607)


--- trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -141,7 +141,7 @@
     if (!errorCallback)
         return;
 
-    m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(), [errorCallback = WTFMove(errorCallback)]() mutable {
+    m_database->document().eventLoop().queueTask(TaskSource::Networking, [errorCallback = WTFMove(errorCallback)]() mutable {
         errorCallback->handleEvent(SQLError::create(SQLError::DATABASE_ERR, "the database was closed"));
     });
 }
@@ -415,7 +415,7 @@
     // error to have occurred in this transaction.
     RefPtr<SQLTransactionErrorCallback> errorCallback = m_errorCallbackWrapper.unwrap();
     if (errorCallback) {
-        m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(), [errorCallback = WTFMove(errorCallback), transactionError = m_transactionError]() mutable {
+        m_database->document().eventLoop().queueTask(TaskSource::Networking, [errorCallback = WTFMove(errorCallback), transactionError = m_transactionError]() mutable {
             errorCallback->handleEvent(*transactionError);
         });
     }
@@ -466,7 +466,7 @@
     // Spec 4.3.2.8: Deliver success callback.
     RefPtr<VoidCallback> successCallback = m_successCallbackWrapper.unwrap();
     if (successCallback) {
-        m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(), [successCallback = WTFMove(successCallback)]() mutable {
+        m_database->document().eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback)]() mutable {
             successCallback->handleEvent();
         });
     }

Modified: trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp (252606 => 252607)


--- trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -51,7 +51,7 @@
 
     if (activeDOMObjectsAreSuspended()) {
         JSC::Strong<JSC::Unknown, ShouldStrongDestructorGrabLock::Yes> strongResolution(lexicalGlobalObject.vm(), resolution);
-        scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, *scriptExecutionContext(), [this, protectedThis = makeRef(*this), mode, strongResolution = WTFMove(strongResolution)]() mutable {
+        scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = makeRef(*this), mode, strongResolution = WTFMove(strongResolution)]() mutable {
             if (shouldIgnoreRequestToFulfill())
                 return;
 
@@ -83,7 +83,7 @@
         return;
 
     if (activeDOMObjectsAreSuspended()) {
-        scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, *scriptExecutionContext(), [this, protectedThis = makeRef(*this), callback = WTFMove(callback)]() mutable {
+        scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = makeRef(*this), callback = WTFMove(callback)]() mutable {
             whenSettled(WTFMove(callback));
         });
         return;

Modified: trunk/Source/WebCore/dom/AbstractEventLoop.h (252606 => 252607)


--- trunk/Source/WebCore/dom/AbstractEventLoop.h	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/AbstractEventLoop.h	2019-11-19 00:54:57 UTC (rev 252607)
@@ -28,21 +28,125 @@
 #include "TaskSource.h"
 #include <wtf/Function.h>
 #include <wtf/RefCounted.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/WeakHashSet.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 
+class EventLoopTaskGroup;
+class EventTarget;
 class ScriptExecutionContext;
 
+class EventLoopTask {
+    WTF_MAKE_NONCOPYABLE(EventLoopTask);
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    virtual ~EventLoopTask() = default;
+
+    TaskSource taskSource() { return m_taskSource; }
+    virtual void execute() = 0;
+
+    EventLoopTaskGroup* group() const { return m_group.get(); }
+
+protected:
+    EventLoopTask(TaskSource, EventLoopTaskGroup&);
+
+private:
+    const TaskSource m_taskSource;
+    WeakPtr<EventLoopTaskGroup> m_group;
+};
+
 // https://html.spec.whatwg.org/multipage/webappapis.html#event-loop
-class AbstractEventLoop : public RefCounted<AbstractEventLoop> {
+class AbstractEventLoop : public RefCounted<AbstractEventLoop>, public CanMakeWeakPtr<AbstractEventLoop> {
 public:
     virtual ~AbstractEventLoop() = default;
 
-    typedef WTF::Function<void ()> TaskFunction;
-    virtual void queueTask(TaskSource, ScriptExecutionContext&, TaskFunction&&) = 0;
+    typedef Function<void ()> TaskFunction;
+    void queueTask(std::unique_ptr<EventLoopTask>&&);
 
+    void resumeGroup(EventLoopTaskGroup&);
+    void stopGroup(EventLoopTaskGroup&);
+
 protected:
     AbstractEventLoop() = default;
+    void run();
+    void clearAllTasks();
+
+private:
+    void scheduleToRunIfNeeded();
+    virtual void scheduleToRun() = 0;
+    virtual bool isContextThread() const = 0;
+
+    // Use a global queue instead of multiple task queues since HTML5 spec allows UA to pick arbitrary queue.
+    Vector<std::unique_ptr<EventLoopTask>> m_tasks;
+    WeakHashSet<EventLoopTaskGroup> m_groupsWithSuspenedTasks;
+    bool m_isScheduledToRun { false };
 };
 
+class EventLoopTaskGroup : public CanMakeWeakPtr<EventLoopTaskGroup> {
+    WTF_MAKE_NONCOPYABLE(EventLoopTaskGroup);
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    EventLoopTaskGroup(AbstractEventLoop& eventLoop)
+        : m_eventLoop(makeWeakPtr(eventLoop))
+    {
+    }
+
+    bool matchesTask(EventLoopTask& task) const
+    {
+        auto* group = task.group();
+        return group == this;
+    }
+
+    void stopAndDiscardAllTasks()
+    {
+        m_state = State::Stopped;
+        if (auto* eventLoop = m_eventLoop.get())
+            eventLoop->stopGroup(*this);
+    }
+
+    void suspend()
+    {
+        ASSERT(m_state != State::Stopped);
+        m_state = State::Suspended;
+        // We don't remove suspended tasks to preserve the ordering.
+        // AbstractEventLoop::run checks whether each task's group is suspended or not.
+    }
+
+    void resume()
+    {
+        ASSERT(m_state != State::Stopped);
+        m_state = State::Running;
+        if (auto* eventLoop = m_eventLoop.get())
+            eventLoop->resumeGroup(*this);
+    }
+
+    bool isStoppedPermanently() { return m_state == State::Stopped; }
+    bool isSuspended() { return m_state == State::Suspended; }
+
+    void queueTask(std::unique_ptr<EventLoopTask>&& task)
+    {
+        if (m_state == State::Stopped || !m_eventLoop)
+            return;
+        ASSERT(task->group() == this);
+        m_eventLoop->queueTask(WTFMove(task));
+    }
+
+    WEBCORE_EXPORT void queueTask(TaskSource, AbstractEventLoop::TaskFunction&&);
+
+private:
+    enum class State : uint8_t { Running, Suspended, Stopped };
+
+    WeakPtr<AbstractEventLoop> m_eventLoop;
+    State m_state { State::Running };
+};
+
+inline EventLoopTask::EventLoopTask(TaskSource source, EventLoopTaskGroup& group)
+    : m_taskSource(source)
+    , m_group(makeWeakPtr(group))
+{ }
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/ActiveDOMObject.cpp (252606 => 252607)


--- trunk/Source/WebCore/dom/ActiveDOMObject.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/ActiveDOMObject.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -135,12 +135,48 @@
     return scriptExecutionContext() && !scriptExecutionContext()->activeDOMObjectsAreStopped() && !scriptExecutionContext()->activeDOMObjectsAreSuspended();
 }
 
-void ActiveDOMObject::queueTaskInEventLoop(TaskSource source, Function<void ()>&& task)
+void ActiveDOMObject::queueTaskInEventLoop(TaskSource source, Function<void ()>&& function)
 {
     auto* context = scriptExecutionContext();
     if (!context)
         return;
-    context->eventLoop().queueTask(source, *context, WTFMove(task));
+    context->eventLoop().queueTask(source, WTFMove(function));
 }
 
+class ActiveDOMObjectEventDispatchTask : public EventLoopTask {
+public:
+    ActiveDOMObjectEventDispatchTask(TaskSource source, EventLoopTaskGroup& group, ActiveDOMObject& object, EventTarget& target, Ref<Event>&& event)
+        : EventLoopTask(source, group)
+        , m_object(object)
+        , m_target(target)
+        , m_event(WTFMove(event))
+    {
+        ++m_object.m_pendingActivityCount;
+    }
+
+    ~ActiveDOMObjectEventDispatchTask()
+    {
+        ASSERT(m_object.m_pendingActivityCount);
+        --m_object.m_pendingActivityCount;
+    }
+
+    void execute() final { m_target->dispatchEvent(m_event.get()); }
+
+private:
+    ActiveDOMObject& m_object;
+    Ref<EventTarget> m_target;
+    Ref<Event> m_event;
+};
+
+void ActiveDOMObject::queueTaskToDispatchEventInternal(EventTarget& target, TaskSource source, Ref<Event>&& event)
+{
+    ASSERT(!event->target() || &target == event->target());
+    auto* context = scriptExecutionContext();
+    if (!context)
+        return;
+    auto& eventLoopTaskGroup = context->eventLoop();
+    auto task = makeUnique<ActiveDOMObjectEventDispatchTask>(source, eventLoopTaskGroup, *this, target, WTFMove(event));
+    eventLoopTaskGroup.queueTask(WTFMove(task));
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/ActiveDOMObject.h (252606 => 252607)


--- trunk/Source/WebCore/dom/ActiveDOMObject.h	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/ActiveDOMObject.h	2019-11-19 00:54:57 UTC (rev 252607)
@@ -37,6 +37,9 @@
 namespace WebCore {
 
 class Document;
+class Event;
+class EventLoopTaskGroup;
+class EventTarget;
 
 enum class ReasonForSuspension {
     _javascript_DebuggerPaused,
@@ -116,7 +119,7 @@
     template<typename T>
     static void queueTaskKeepingObjectAlive(T& object, TaskSource source, Function<void ()>&& task)
     {
-        object.queueTaskInEventLoop(source, [protectedObject = makeRef(object), activity = object.makePendingActivity(object), task = WTFMove(task)] () {
+        object.queueTaskInEventLoop(source, [protectedObject = makeRef(object), activity = object.ActiveDOMObject::makePendingActivity(object), task = WTFMove(task)] () {
             task();
         });
     }
@@ -124,10 +127,7 @@
     template<typename EventTargetType, typename EventType>
     static void queueTaskToDispatchEvent(EventTargetType& target, TaskSource source, Ref<EventType>&& event)
     {
-        ASSERT(!event->target() || &target == event->target());
-        queueTaskKeepingObjectAlive(target, source, [&target, event = WTFMove(event)] () mutable {
-            target.dispatchEvent(event.get());
-        });
+        target.queueTaskToDispatchEventInternal(target, source, WTFMove(event));
     }
 
 protected:
@@ -141,6 +141,7 @@
     ActiveDOMObject(ScriptExecutionContext*, CheckedScriptExecutionContextType);
 
     void queueTaskInEventLoop(TaskSource, Function<void ()>&&);
+    void queueTaskToDispatchEventInternal(EventTarget&, TaskSource, Ref<Event>&&);
 
     unsigned m_pendingActivityCount { 0 };
 #if !ASSERT_DISABLED
@@ -147,6 +148,8 @@
     bool m_suspendIfNeededWasCalled { false };
     Ref<Thread> m_creationThread { Thread::current() };
 #endif
+
+    friend class ActiveDOMObjectEventDispatchTask;
 };
 
 #if ASSERT_DISABLED

Modified: trunk/Source/WebCore/dom/Document.cpp (252606 => 252607)


--- trunk/Source/WebCore/dom/Document.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/Document.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -2646,8 +2646,8 @@
 
 void Document::suspendActiveDOMObjects(ReasonForSuspension why)
 {
-    if (m_eventLoop)
-        m_eventLoop->suspend(*this);
+    if (m_documentTaskGroup)
+        m_documentTaskGroup->suspend();
     ScriptExecutionContext::suspendActiveDOMObjects(why);
     suspendDeviceMotionAndOrientationUpdates();
     platformSuspendOrStopActiveDOMObjects();
@@ -2655,8 +2655,8 @@
 
 void Document::resumeActiveDOMObjects(ReasonForSuspension why)
 {
-    if (m_eventLoop)
-        m_eventLoop->resume(*this);
+    if (m_documentTaskGroup)
+        m_documentTaskGroup->resume();
     ScriptExecutionContext::resumeActiveDOMObjects(why);
     resumeDeviceMotionAndOrientationUpdates();
     // FIXME: For iOS, do we need to add content change observers that were removed in Document::suspendActiveDOMObjects()?
@@ -2664,8 +2664,8 @@
 
 void Document::stopActiveDOMObjects()
 {
-    if (m_eventLoop)
-        m_eventLoop->stop(*this);
+    if (m_documentTaskGroup)
+        m_documentTaskGroup->stopAndDiscardAllTasks();
     ScriptExecutionContext::stopActiveDOMObjects();
     platformSuspendOrStopActiveDOMObjects();
 }
@@ -6243,12 +6243,18 @@
         task.performTask(*this);
 }
 
-AbstractEventLoop& Document::eventLoop()
+EventLoopTaskGroup& Document::eventLoop()
 {
     ASSERT(isMainThread());
-    if (UNLIKELY(!m_eventLoop))
+    if (UNLIKELY(!m_documentTaskGroup)) {
         m_eventLoop = WindowEventLoop::ensureForRegistrableDomain(RegistrableDomain { securityOrigin().data() });
-    return *m_eventLoop;
+        m_documentTaskGroup = makeUnique<EventLoopTaskGroup>(*m_eventLoop);
+        if (activeDOMObjectsAreStopped())
+            m_documentTaskGroup->stopAndDiscardAllTasks();
+        else if (activeDOMObjectsAreSuspended())
+            m_documentTaskGroup->suspend();
+    }
+    return *m_documentTaskGroup;
 }
 
 void Document::suspendScheduledTasks(ReasonForSuspension reason)

Modified: trunk/Source/WebCore/dom/Document.h (252606 => 252607)


--- trunk/Source/WebCore/dom/Document.h	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/Document.h	2019-11-19 00:54:57 UTC (rev 252607)
@@ -121,6 +121,7 @@
 class DocumentTimeline;
 class DocumentType;
 class EditingBehavior;
+class EventLoopTaskGroup;
 class ExtensionStyleSheets;
 class FloatQuad;
 class FloatRect;
@@ -1063,7 +1064,7 @@
 
     WEBCORE_EXPORT void postTask(Task&&) final; // Executes the task on context's thread asynchronously.
 
-    AbstractEventLoop& eventLoop() final;
+    EventLoopTaskGroup& eventLoop() final;
 
     ScriptedAnimationController* scriptedAnimationController() { return m_scriptedAnimationController.get(); }
     void suspendScriptedAnimationControllerCallbacks();
@@ -2064,6 +2065,7 @@
     DocumentIdentifier m_identifier;
 
     RefPtr<WindowEventLoop> m_eventLoop;
+    std::unique_ptr<EventLoopTaskGroup> m_documentTaskGroup;
 
 #if ENABLE(SERVICE_WORKER)
     RefPtr<SWClientConnection> m_serviceWorkerConnection;

Modified: trunk/Source/WebCore/dom/IdleCallbackController.cpp (252606 => 252607)


--- trunk/Source/WebCore/dom/IdleCallbackController.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/IdleCallbackController.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -71,7 +71,7 @@
 
 void IdleCallbackController::queueTaskToStartIdlePeriod()
 {
-    m_document->eventLoop().queueTask(TaskSource::IdleTask, *m_document, [protectedDocument = makeRef(*m_document), this]() {
+    m_document->eventLoop().queueTask(TaskSource::IdleTask, [protectedDocument = makeRef(*m_document), this] {
         RELEASE_ASSERT(protectedDocument->idleCallbackController() == this);
         startIdlePeriod();
     });
@@ -100,7 +100,7 @@
 
 void IdleCallbackController::queueTaskToInvokeIdleCallbacks(MonotonicTime deadline)
 {
-    m_document->eventLoop().queueTask(TaskSource::IdleTask, *m_document, [protectedDocument = makeRef(*m_document), deadline, this]() {
+    m_document->eventLoop().queueTask(TaskSource::IdleTask, [protectedDocument = makeRef(*m_document), deadline, this] {
         RELEASE_ASSERT(protectedDocument->idleCallbackController() == this);
         invokeIdleCallbacks(deadline);
     });

Modified: trunk/Source/WebCore/dom/ScriptExecutionContext.h (252606 => 252607)


--- trunk/Source/WebCore/dom/ScriptExecutionContext.h	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/ScriptExecutionContext.h	2019-11-19 00:54:57 UTC (rev 252607)
@@ -57,6 +57,7 @@
 class CachedScript;
 class DatabaseContext;
 class EventQueue;
+class EventLoopTaskGroup;
 class EventTarget;
 class MessagePort;
 class PublicURLManager;
@@ -64,6 +65,7 @@
 class ResourceRequest;
 class SecurityOrigin;
 class SocketProvider;
+enum class TaskSource : uint8_t;
 
 #if ENABLE(SERVICE_WORKER)
 class ServiceWorker;
@@ -89,7 +91,7 @@
     virtual bool isContextThread() const { return true; }
     virtual bool isJSExecutionForbidden() const = 0;
 
-    virtual AbstractEventLoop& eventLoop() = 0;
+    virtual EventLoopTaskGroup& eventLoop() = 0;
 
     virtual const URL& url() const = 0;
     virtual URL completeURL(const String& url) const = 0;

Modified: trunk/Source/WebCore/dom/WindowEventLoop.cpp (252606 => 252607)


--- trunk/Source/WebCore/dom/WindowEventLoop.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/WindowEventLoop.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -59,64 +59,71 @@
     RELEASE_ASSERT(didRemove);
 }
 
-void WindowEventLoop::queueTask(TaskSource source, ScriptExecutionContext& context, TaskFunction&& task)
+void AbstractEventLoop::queueTask(std::unique_ptr<EventLoopTask>&& task)
 {
-    ASSERT(isMainThread());
-    ASSERT(is<Document>(context));
+    ASSERT(task->group());
+    ASSERT(isContextThread());
     scheduleToRunIfNeeded();
-    m_tasks.append(Task { source, WTFMove(task), downcast<Document>(context).identifier() });
+    m_tasks.append(WTFMove(task));
 }
 
-void WindowEventLoop::suspend(Document&)
+void AbstractEventLoop::resumeGroup(EventLoopTaskGroup& group)
 {
-    ASSERT(isMainThread());
-}
-
-void WindowEventLoop::resume(Document& document)
-{
-    ASSERT(isMainThread());
-    if (!m_documentIdentifiersForSuspendedTasks.contains(document.identifier()))
+    ASSERT(isContextThread());
+    if (!m_groupsWithSuspenedTasks.contains(group))
         return;
     scheduleToRunIfNeeded();
 }
 
-void WindowEventLoop::stop(Document& document)
+void AbstractEventLoop::stopGroup(EventLoopTaskGroup& group)
 {
-    m_tasks.removeAllMatching([identifier = document.identifier()] (auto& task) {
-        return task.documentIdentifier == identifier;
+    ASSERT(isContextThread());
+    m_tasks.removeAllMatching([&group] (auto& task) {
+        return group.matchesTask(*task);
     });
 }
 
-void WindowEventLoop::scheduleToRunIfNeeded()
+void AbstractEventLoop::scheduleToRunIfNeeded()
 {
     if (m_isScheduledToRun)
         return;
+    m_isScheduledToRun = true;
+    scheduleToRun();
+}
 
-    m_isScheduledToRun = true;
+void WindowEventLoop::scheduleToRun()
+{
     callOnMainThread([eventLoop = makeRef(*this)] () {
-        eventLoop->m_isScheduledToRun = false;
         eventLoop->run();
     });
 }
 
-void WindowEventLoop::run()
+bool WindowEventLoop::isContextThread() const
 {
+    return isMainThread();
+}
+
+void AbstractEventLoop::run()
+{
+    m_isScheduledToRun = false;
     if (m_tasks.isEmpty())
         return;
 
-    Vector<Task> tasks = WTFMove(m_tasks);
-    m_documentIdentifiersForSuspendedTasks.clear();
-    Vector<Task> remainingTasks;
+    auto tasks = std::exchange(m_tasks, { });
+    m_groupsWithSuspenedTasks.clear();
+    Vector<std::unique_ptr<EventLoopTask>> remainingTasks;
     for (auto& task : tasks) {
-        auto* document = Document::allDocumentsMap().get(task.documentIdentifier);
-        if (!document || document->activeDOMObjectsAreStopped())
+        auto* group = task->group();
+        if (!group || group->isStoppedPermanently())
             continue;
-        if (document->activeDOMObjectsAreSuspended()) {
-            m_documentIdentifiersForSuspendedTasks.add(task.documentIdentifier);
+
+        if (group->isSuspended()) {
+            m_groupsWithSuspenedTasks.add(group);
             remainingTasks.append(WTFMove(task));
             continue;
         }
-        task.task();
+
+        task->execute();
     }
     for (auto& task : m_tasks)
         remainingTasks.append(WTFMove(task));
@@ -123,4 +130,29 @@
     m_tasks = WTFMove(remainingTasks);
 }
 
+void AbstractEventLoop::clearAllTasks()
+{
+    m_tasks.clear();
+    m_groupsWithSuspenedTasks.clear();
+}
+
+class EventLoopFunctionDispatchTask : public EventLoopTask {
+public:
+    EventLoopFunctionDispatchTask(TaskSource source, EventLoopTaskGroup& group, AbstractEventLoop::TaskFunction&& function)
+        : EventLoopTask(source, group)
+        , m_function(WTFMove(function))
+    {
+    }
+
+    void execute() final { m_function(); }
+
+private:
+    AbstractEventLoop::TaskFunction m_function;
+};
+
+void EventLoopTaskGroup::queueTask(TaskSource source, AbstractEventLoop::TaskFunction&& function)
+{
+    return queueTask(makeUnique<EventLoopFunctionDispatchTask>(source, *this, WTFMove(function)));
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/WindowEventLoop.h (252606 => 252607)


--- trunk/Source/WebCore/dom/WindowEventLoop.h	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/dom/WindowEventLoop.h	2019-11-19 00:54:57 UTC (rev 252607)
@@ -41,29 +41,13 @@
 
     ~WindowEventLoop();
 
-    void queueTask(TaskSource, ScriptExecutionContext&, TaskFunction&&) override;
-
-    void suspend(Document&);
-    void resume(Document&);
-    void stop(Document&);
-
 private:
     WindowEventLoop(const RegistrableDomain&);
 
-    void scheduleToRunIfNeeded();
-    void run();
+    void scheduleToRun() final;
+    bool isContextThread() const final;
 
-    struct Task {
-        TaskSource source;
-        TaskFunction task;
-        DocumentIdentifier documentIdentifier;
-    };
-
-    // Use a global queue instead of multiple task queues since HTML5 spec allows UA to pick arbitrary queue.
-    Vector<Task> m_tasks;
-    HashSet<DocumentIdentifier> m_documentIdentifiersForSuspendedTasks;
     RegistrableDomain m_domain;
-    bool m_isScheduledToRun { false };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/fileapi/FileReader.cpp (252606 => 252607)


--- trunk/Source/WebCore/fileapi/FileReader.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/fileapi/FileReader.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -254,7 +254,7 @@
     static uint64_t taskIdentifierSeed = 0;
     uint64_t taskIdentifier = ++taskIdentifierSeed;
     m_pendingTasks.add(taskIdentifier, WTFMove(task));
-    context->eventLoop().queueTask(TaskSource::FileReading, *context, [this, protectedThis = makeRef(*this), pendingActivity = makePendingActivity(*this), taskIdentifier] {
+    context->eventLoop().queueTask(TaskSource::FileReading, [this, protectedThis = makeRef(*this), pendingActivity = makePendingActivity(*this), taskIdentifier] {
         auto task = m_pendingTasks.take(taskIdentifier);
         if (task)
             task();

Modified: trunk/Source/WebCore/testing/Internals.cpp (252606 => 252607)


--- trunk/Source/WebCore/testing/Internals.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/testing/Internals.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -4684,7 +4684,7 @@
     else
         return Exception { NotSupportedError };
 
-    context.eventLoop().queueTask(source, context, [callback = WTFMove(callback)]() {
+    context.eventLoop().queueTask(source, [callback = WTFMove(callback)]() {
         callback->handleEvent();
     });
 

Modified: trunk/Source/WebCore/workers/WorkerEventLoop.cpp (252606 => 252607)


--- trunk/Source/WebCore/workers/WorkerEventLoop.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/workers/WorkerEventLoop.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -44,63 +44,21 @@
 #endif
 
 WorkerEventLoop::WorkerEventLoop(ScriptExecutionContext& context)
-    : ActiveDOMObject(&context)
+    : ContextDestructionObserver(&context)
 {
-    suspendIfNeeded();
 }
 
-void WorkerEventLoop::queueTask(TaskSource source, ScriptExecutionContext& context, TaskFunction&& function)
+void WorkerEventLoop::scheduleToRun()
 {
-    if (!scriptExecutionContext())
-        return;
-    ASSERT(scriptExecutionContext()->isContextThread());
-    ASSERT_UNUSED(context, scriptExecutionContext() == &context);
-    m_tasks.append({ source, WTFMove(function) });
-    scheduleToRunIfNeeded();
-}
-
-const char* WorkerEventLoop::activeDOMObjectName() const
-{
-    return "WorkerEventLoop";
-}
-
-void WorkerEventLoop::suspend(ReasonForSuspension)
-{
-    ASSERT_NOT_REACHED();
-}
-
-void WorkerEventLoop::resume()
-{
-    ASSERT_NOT_REACHED();
-}
-
-void WorkerEventLoop::stop()
-{
-    m_tasks.clear();
-}
-
-void WorkerEventLoop::scheduleToRunIfNeeded()
-{
-    auto* context = scriptExecutionContext();
-    ASSERT(context);
-    if (m_isScheduledToRun || m_tasks.isEmpty())
-        return;
-
-    m_isScheduledToRun = true;
-    context->postTask([eventLoop = makeRef(*this)] (ScriptExecutionContext&) {
-        eventLoop->m_isScheduledToRun = false;
+    ASSERT(scriptExecutionContext());
+    scriptExecutionContext()->postTask([eventLoop = makeRef(*this)] (ScriptExecutionContext&) {
         eventLoop->run();
     });
 }
 
-void WorkerEventLoop::run()
+bool WorkerEventLoop::isContextThread() const
 {
-    auto* context = scriptExecutionContext();
-    if (!context || context->activeDOMObjectsAreStopped() || context->activeDOMObjectsAreSuspended())
-        return;
-    auto tasks = std::exchange(m_tasks, Vector<Task>());
-    for (auto& task : tasks)
-        task.task();
+    return scriptExecutionContext()->isContextThread();
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/WorkerEventLoop.h (252606 => 252607)


--- trunk/Source/WebCore/workers/WorkerEventLoop.h	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/workers/WorkerEventLoop.h	2019-11-19 00:54:57 UTC (rev 252607)
@@ -33,7 +33,7 @@
 class WorkerGlobalScope;
 class WorkletGlobalScope;
 
-class WorkerEventLoop final : public AbstractEventLoop, private ActiveDOMObject {
+class WorkerEventLoop final : public AbstractEventLoop, private ContextDestructionObserver {
 public:
     // Explicitly take WorkerGlobalScope and WorkletGlobalScope for documentation purposes.
     static Ref<WorkerEventLoop> create(WorkerGlobalScope&);
@@ -42,27 +42,11 @@
     static Ref<WorkerEventLoop> create(WorkletGlobalScope&);
 #endif
 
-    void queueTask(TaskSource, ScriptExecutionContext&, TaskFunction&&) override;
-
 private:
     explicit WorkerEventLoop(ScriptExecutionContext&);
 
-    void scheduleToRunIfNeeded();
-    void run();
-
-    // ActiveDOMObject;
-    const char* activeDOMObjectName() const override;
-    void suspend(ReasonForSuspension) override;
-    void resume() override;
-    void stop() override;
-
-    struct Task {
-        TaskSource source;
-        TaskFunction task;
-    };
-
-    Vector<Task> m_tasks;
-    bool m_isScheduledToRun { false };
+    void scheduleToRun() final;
+    bool isContextThread() const;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/WorkerGlobalScope.cpp (252606 => 252607)


--- trunk/Source/WebCore/workers/WorkerGlobalScope.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/workers/WorkerGlobalScope.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -105,12 +105,16 @@
     thread().workerReportingProxy().workerGlobalScopeDestroyed();
 }
 
-AbstractEventLoop& WorkerGlobalScope::eventLoop()
+EventLoopTaskGroup& WorkerGlobalScope::eventLoop()
 {
     ASSERT(isContextThread());
-    if (!m_eventLoop)
+    if (UNLIKELY(!m_defaultTaskGroup)) {
         m_eventLoop = WorkerEventLoop::create(*this);
-    return *m_eventLoop;
+        m_defaultTaskGroup = makeUnique<EventLoopTaskGroup>(*m_eventLoop);
+        if (activeDOMObjectsAreStopped())
+            m_defaultTaskGroup->stopAndDiscardAllTasks();
+    }
+    return *m_defaultTaskGroup;
 }
 
 String WorkerGlobalScope::origin() const
@@ -125,6 +129,8 @@
     stopIndexedDatabase();
 #endif
 
+    if (m_defaultTaskGroup)
+        m_defaultTaskGroup->stopAndDiscardAllTasks();
     stopActiveDOMObjects();
 
     if (m_cacheStorageConnection)

Modified: trunk/Source/WebCore/workers/WorkerGlobalScope.h (252606 => 252607)


--- trunk/Source/WebCore/workers/WorkerGlobalScope.h	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/workers/WorkerGlobalScope.h	2019-11-19 00:54:57 UTC (rev 252607)
@@ -42,9 +42,9 @@
 
 namespace WebCore {
 
-class AbstractEventLoop;
 class ContentSecurityPolicyResponseHeaders;
 class Crypto;
+class EventLoopTaskGroup;
 class MicrotaskQueue;
 class Performance;
 class ScheduledAction;
@@ -67,7 +67,7 @@
     virtual bool isDedicatedWorkerGlobalScope() const { return false; }
     virtual bool isServiceWorkerGlobalScope() const { return false; }
 
-    AbstractEventLoop& eventLoop() final;
+    EventLoopTaskGroup& eventLoop() final;
 
     const URL& url() const final { return m_url; }
     String origin() const final;
@@ -198,6 +198,7 @@
     bool m_shouldBypassMainWorldContentSecurityPolicy;
 
     RefPtr<WorkerEventLoop> m_eventLoop;
+    std::unique_ptr<EventLoopTaskGroup> m_defaultTaskGroup;
 
     mutable WorkerEventQueue m_eventQueue;
 

Modified: trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp (252606 => 252607)


--- trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp	2019-11-19 00:54:57 UTC (rev 252607)
@@ -77,6 +77,8 @@
 {
     if (!m_script)
         return;
+    if (m_defaultTaskGroup)
+        m_defaultTaskGroup->stopAndDiscardAllTasks();
     stopActiveDOMObjects();
     removeRejectedPromiseTracker();
     removeAllEventListeners();
@@ -90,11 +92,15 @@
     return scopes;
 }
 
-AbstractEventLoop& WorkletGlobalScope::eventLoop()
+EventLoopTaskGroup& WorkletGlobalScope::eventLoop()
 {
-    if (!m_eventLoop)
+    if (UNLIKELY(!m_defaultTaskGroup)) {
         m_eventLoop = WorkerEventLoop::create(*this);
-    return *m_eventLoop;
+        m_defaultTaskGroup = makeUnique<EventLoopTaskGroup>(*m_eventLoop);
+        if (activeDOMObjectsAreStopped())
+            m_defaultTaskGroup->stopAndDiscardAllTasks();
+    }
+    return *m_defaultTaskGroup;
 }
 
 String WorkletGlobalScope::origin() const

Modified: trunk/Source/WebCore/worklets/WorkletGlobalScope.h (252606 => 252607)


--- trunk/Source/WebCore/worklets/WorkletGlobalScope.h	2019-11-19 00:53:03 UTC (rev 252606)
+++ trunk/Source/WebCore/worklets/WorkletGlobalScope.h	2019-11-19 00:54:57 UTC (rev 252607)
@@ -43,7 +43,7 @@
 
 namespace WebCore {
 
-class AbstractEventLoop;
+class EventLoopTaskGroup;
 class WorkerEventLoop;
 class WorkletScriptController;
 
@@ -60,7 +60,7 @@
 
     virtual bool isPaintWorkletGlobalScope() const { return false; }
 
-    AbstractEventLoop& eventLoop() final;
+    EventLoopTaskGroup& eventLoop() final;
 
     const URL& url() const final { return m_code.url(); }
     String origin() const final;
@@ -135,6 +135,7 @@
     Ref<SecurityOrigin> m_topOrigin;
 
     RefPtr<WorkerEventLoop> m_eventLoop;
+    std::unique_ptr<EventLoopTaskGroup> m_defaultTaskGroup;
 
     // FIXME: This is not implemented properly, it just satisfies the compiler.
     // https://bugs.webkit.org/show_bug.cgi?id=191136
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to