Changeset 252607 in webkit
- Timestamp:
- Nov 18, 2019 4:54:57 PM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r252599 r252607 1 2019-11-15 Ryosuke Niwa <rniwa@webkit.org> 2 3 Share more code between WindowEventLoop and WorkerEventLoop by introducing EventLoopTaskGroup 4 https://bugs.webkit.org/show_bug.cgi?id=204263 5 6 Reviewed by Antti Koivisto. 7 8 This patch abstracts the logic in WindowEventLoop to deal with a set of tasks associated with 9 a particular documents all suspending, resuming, or stopping at the same time using a new abstraction 10 called EventLoopTaskGroup in order to group tasks for media code and elsewhere. 11 12 Each task is now represented as an instance of a concrete subclass of EventLoopTask, which has 13 a pure virtual execute() member function. Its primary purpose is to know EventLoopTaskGroup to which 14 each task belongs. One of subclasss, EventLoopFunctionDispatchTask, is used to store a callback function 15 and another subclass, ActiveDOMObjectEventDispatchTask, is used to dispatch an async event. 16 17 ScriptExecutionContext's eventLoop() method now returns EventLoopTaskGroup. Because this group is 18 specific to a given ScriptExecutionContext, we no longer have to pass the ScriptExecutionContext 19 in each call to queueTask everywhere in our codebase. 20 21 For now, I kept all the code in WindowEventLoop.cpp to make the patch reviewable. My plan is to create 22 a new cpp file (e.g. AbstractEventLoop.cpp) and move most of code there instead as a follow up. 23 24 No new tests since there should be no observable behavior change. 25 26 * Modules/encryptedmedia/MediaKeys.cpp: 27 (WebCore::MediaKeys::setServerCertificate): 28 * Modules/entriesapi/FileSystemDirectoryEntry.cpp: 29 (WebCore::FileSystemDirectoryEntry::getEntry): 30 * Modules/entriesapi/FileSystemDirectoryReader.cpp: 31 (WebCore::FileSystemDirectoryReader::readEntries): 32 * Modules/entriesapi/FileSystemEntry.cpp: 33 (WebCore::FileSystemEntry::getParent): 34 * Modules/entriesapi/FileSystemFileEntry.cpp: 35 (WebCore::FileSystemFileEntry::file): 36 * Modules/mediarecorder/MediaRecorder.cpp: 37 (WebCore::MediaRecorder::scheduleDeferredTask): 38 * Modules/notifications/Notification.cpp: 39 (WebCore::Notification::queueTask): 40 * Modules/webdatabase/Database.cpp: 41 (WebCore::Database::runTransaction): 42 * Modules/webdatabase/DatabaseManager.cpp: 43 (WebCore::DatabaseManager::openDatabase): 44 * Modules/webdatabase/SQLTransaction.cpp: 45 (WebCore::SQLTransaction::callErrorCallbackDueToInterruption): 46 (WebCore::SQLTransaction::deliverTransactionErrorCallback): 47 (WebCore::SQLTransaction::deliverSuccessCallback): 48 * bindings/js/JSDOMPromiseDeferred.cpp: 49 (WebCore::DeferredPromise::callFunction): 50 (WebCore::DeferredPromise::whenSettled): 51 * dom/AbstractEventLoop.h: 52 (WebCore::EventLoopTask): Added. 53 (WebCore::EventLoopTask::taskSource): Added. 54 (WebCore::EventLoopTask::group const): Added. 55 (WebCore::EventLoopTask::EventLoopTask): Added. 56 (WebCore::EventLoopTaskGroup): Added. This class represents a group of tasks. For now, each group is 57 a distinct ScriptExecutionContext. 58 (WebCore::EventLoopTaskGroup::matchesTask const): Added. 59 (WebCore::EventLoopTaskGroup::startRunning): Added. 60 (WebCore::EventLoopTaskGroup::stopAndDiscardAllTasks): Added. 61 (WebCore::EventLoopTaskGroup::suspend): Added. 62 (WebCore::EventLoopTaskGroup::resume): Added. 63 (WebCore::EventLoopTaskGroup::isStoppedPermanently): Added. 64 (WebCore::EventLoopTaskGroup::isSuspended): Added. 65 (WebCore::EventLoopTaskGroup::hasScheduledTasks const): Added. 66 (WebCore::EventLoopTaskGroup::queueTask): Added. 67 * dom/ActiveDOMObject.cpp: 68 (WebCore::ActiveDOMObject::queueTaskInEventLoop): 69 (WebCore::ActiveDOMObjectEventDispatchTask): Added; A subclass of EventLoopTask to dispatch an async event. 70 (WebCore::ActiveDOMObjectEventDispatchTask::ActiveDOMObjectEventDispatchTask): Added. 71 (WebCore::ActiveDOMObjectEventDispatchTask::~ActiveDOMObjectEventDispatchTask): Added. 72 (WebCore::ActiveDOMObject::queueTaskToDispatchEventInternal): Added. 73 * dom/ActiveDOMObject.h: 74 * dom/Document.cpp: 75 (WebCore::Document::suspendActiveDOMObjects): 76 (WebCore::Document::resumeActiveDOMObjects): 77 (WebCore::Document::stopActiveDOMObjects): 78 (WebCore::Document::eventLoop): Creates EventLoopTaskGroup for this document. 79 * dom/Document.h: 80 * dom/IdleCallbackController.cpp: 81 (WebCore::IdleCallbackController::queueTaskToStartIdlePeriod): 82 (WebCore::IdleCallbackController::queueTaskToInvokeIdleCallbacks): 83 * dom/ScriptExecutionContext.h: 84 * dom/WindowEventLoop.cpp: 85 (WebCore::AbstractEventLoop::queueTask): The implementation moved from WindowEventLoop to AbstractEventLoop. 86 (WebCore::AbstractEventLoop::suspend): Removed. 87 (WebCore::AbstractEventLoop::resumeGroup): Ditto. 88 (WebCore::AbstractEventLoop::stopGroup): Ditto. 89 (WebCore::WindowEventLoop::scheduleToRun): Renamed from WindowEventLoop::scheduleToRunIfNeeded. 90 (WebCore::AbstractEventLoop::scheduleToRunIfNeeded): Extracted from WindowEventLoop::scheduleToRunIfNeeded. 91 (WebCore::WindowEventLoop::isContextThread const): Added. 92 (WebCore::AbstractEventLoop::run): The implementation moved from WindowEventLoop to AbstractEventLoop. 93 (WebCore::AbstractEventLoop::clearAllTasks): Added. 94 (WebCore::EventLoopFunctionDispatchTask): Added; A subclass of EventLoopTask to call a function. 95 (WebCore::EventLoopFunctionDispatchTask::EventLoopFunctionDispatchTask): Added. 96 (WebCore::EventLoopTaskGroup::queueTask): Added. 97 * dom/WindowEventLoop.h: 98 * fileapi/FileReader.cpp: 99 (WebCore::FileReader::enqueueTask): 100 * testing/Internals.cpp: 101 (WebCore::Internals::queueTask): 102 * workers/WorkerEventLoop.cpp: 103 (WebCore::WorkerEventLoop::WorkerEventLoop): 104 (WebCore::WorkerEventLoop::queueTask): Deleted. 105 (WebCore::WorkerEventLoop::activeDOMObjectName const): Deleted. 106 (WebCore::WorkerEventLoop::suspend): Deleted. 107 (WebCore::WorkerEventLoop::resume): Deleted. 108 (WebCore::WorkerEventLoop::stop): Deleted. 109 (WebCore::WorkerEventLoop::scheduleToRun): Extracted from scheduleToRunIfNeeded. 110 (WebCore::WorkerEventLoop::scheduleToRunIfNeeded): Deleted. 111 (WebCore::WorkerEventLoop::run): Deleted. 112 (WebCore::WorkerEventLoop::isContextThread const): Added. 113 * workers/WorkerEventLoop.h: 114 (WebCore::WorkerEventLoop): This class is no longer an active DOM object. WorkerGlobalScope and WorkerGlobalScope 115 manually stop the task group associated with it. 116 * workers/WorkerGlobalScope.cpp: 117 (WebCore::WorkerGlobalScope::eventLoop): Create the default task group for this script execution context. 118 (WebCore::WorkerGlobalScope::prepareForTermination): Stop the default task group. 119 * workers/WorkerGlobalScope.h: 120 * worklets/WorkletGlobalScope.cpp: 121 (WebCore::WorkletGlobalScope::prepareForDestruction): Similar to WorkerGlobalScope::prepareForTermination. 122 (WebCore::WorkletGlobalScope::eventLoop): Similar to WorkerGlobalScope::eventLoop. 123 * worklets/WorkletGlobalScope.h: 124 1 125 2019-11-18 Antti Koivisto <antti@apple.com> 2 126 -
trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp
r252033 r252607 107 107 // 5. Run the following steps in parallel: 108 108 109 context.eventLoop().queueTask(TaskSource::Networking, context,[this, certificate = WTFMove(certificate), promise = WTFMove(promise)] () mutable {109 context.eventLoop().queueTask(TaskSource::Networking, [this, certificate = WTFMove(certificate), promise = WTFMove(promise)] () mutable { 110 110 // 5.1. Use this object's cdm instance to process certificate. 111 111 if (m_instance->setServerCertificate(WTFMove(certificate)) == CDMInstance::Failed) { -
trunk/Source/WebCore/Modules/entriesapi/FileSystemDirectoryEntry.cpp
r251524 r252607 58 58 if (result.hasException()) { 59 59 if (errorCallback && document) { 60 document->eventLoop().queueTask(TaskSource::Networking, *document,[errorCallback = WTFMove(errorCallback), exception = result.releaseException(), pendingActivity = WTFMove(pendingActivity)]() mutable {60 document->eventLoop().queueTask(TaskSource::Networking, [errorCallback = WTFMove(errorCallback), exception = result.releaseException(), pendingActivity = WTFMove(pendingActivity)]() mutable { 61 61 errorCallback->handleEvent(DOMException::create(WTFMove(exception))); 62 62 }); … … 67 67 if (!matches(entry)) { 68 68 if (errorCallback && document) { 69 document->eventLoop().queueTask(TaskSource::Networking, *document,[errorCallback = WTFMove(errorCallback), pendingActivity = WTFMove(pendingActivity)]() mutable {69 document->eventLoop().queueTask(TaskSource::Networking, [errorCallback = WTFMove(errorCallback), pendingActivity = WTFMove(pendingActivity)]() mutable { 70 70 errorCallback->handleEvent(DOMException::create(Exception { TypeMismatchError, "Entry at given path does not match expected type"_s })); 71 71 }); … … 74 74 } 75 75 if (successCallback && document) { 76 document->eventLoop().queueTask(TaskSource::Networking, *document,[successCallback = WTFMove(successCallback), entry = WTFMove(entry), pendingActivity = WTFMove(pendingActivity)]() mutable {76 document->eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback), entry = WTFMove(entry), pendingActivity = WTFMove(pendingActivity)]() mutable { 77 77 successCallback->handleEvent(WTFMove(entry)); 78 78 }); -
trunk/Source/WebCore/Modules/entriesapi/FileSystemDirectoryReader.cpp
r251509 r252607 90 90 m_error = result.releaseException(); 91 91 if (errorCallback && document) { 92 document->eventLoop().queueTask(TaskSource::Networking, *document,[this, errorCallback = WTFMove(errorCallback), pendingActivity = WTFMove(pendingActivity)]() mutable {92 document->eventLoop().queueTask(TaskSource::Networking, [this, errorCallback = WTFMove(errorCallback), pendingActivity = WTFMove(pendingActivity)]() mutable { 93 93 errorCallback->handleEvent(DOMException::create(*m_error)); 94 94 }); … … 98 98 m_isDone = true; 99 99 if (document) { 100 document->eventLoop().queueTask(TaskSource::Networking, *document,[successCallback = WTFMove(successCallback), pendingActivity = WTFMove(pendingActivity), result = result.releaseReturnValue()]() mutable {100 document->eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback), pendingActivity = WTFMove(pendingActivity), result = result.releaseReturnValue()]() mutable { 101 101 successCallback->handleEvent(WTFMove(result)); 102 102 }); -
trunk/Source/WebCore/Modules/entriesapi/FileSystemEntry.cpp
r251690 r252607 78 78 return; 79 79 80 document->eventLoop().queueTask(TaskSource::Networking, *document,[successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), result = WTFMove(result), pendingActivity = WTFMove(pendingActivity)]() mutable {80 document->eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), result = WTFMove(result), pendingActivity = WTFMove(pendingActivity)]() mutable { 81 81 if (result.hasException()) { 82 82 if (errorCallback) -
trunk/Source/WebCore/Modules/entriesapi/FileSystemFileEntry.cpp
r251690 r252607 49 49 return; 50 50 51 document->eventLoop().queueTask(TaskSource::Networking, *document,[successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), result = WTFMove(result), pendingActivity = WTFMove(pendingActivity)]() mutable {51 document->eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), result = WTFMove(result), pendingActivity = WTFMove(pendingActivity)]() mutable { 52 52 if (result.hasException()) { 53 53 if (errorCallback) -
trunk/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp
r252003 r252607 217 217 return; 218 218 219 document->eventLoop().queueTask(TaskSource::Networking, *document,[pendingActivity = makePendingActivity(*this), function = WTFMove(function)] {219 document->eventLoop().queueTask(TaskSource::Networking, [pendingActivity = makePendingActivity(*this), function = WTFMove(function)] { 220 220 function(); 221 221 }); -
trunk/Source/WebCore/Modules/notifications/Notification.cpp
r251528 r252607 153 153 return; 154 154 155 document->eventLoop().queueTask(TaskSource::UserInteraction, *document,WTFMove(task));155 document->eventLoop().queueTask(TaskSource::UserInteraction, WTFMove(task)); 156 156 } 157 157 -
trunk/Source/WebCore/Modules/webdatabase/Database.cpp
r252064 r252607 690 690 if (!m_isTransactionQueueEnabled) { 691 691 if (errorCallback) { 692 m_document->eventLoop().queueTask(TaskSource::Networking, m_document,[errorCallback = makeRef(*errorCallback)]() {692 m_document->eventLoop().queueTask(TaskSource::Networking, [errorCallback = makeRef(*errorCallback)]() { 693 693 errorCallback->handleEvent(SQLError::create(SQLError::UNKNOWN_ERR, "database has been closed")); 694 694 }); -
trunk/Source/WebCore/Modules/webdatabase/DatabaseManager.cpp
r252064 r252607 211 211 LOG(StorageAPI, "Scheduling DatabaseCreationCallbackTask for database %p\n", database.get()); 212 212 database->setHasPendingCreationEvent(true); 213 database->m_document->eventLoop().queueTask(TaskSource::Networking, database->m_document,[creationCallback, database]() {213 database->m_document->eventLoop().queueTask(TaskSource::Networking, [creationCallback, database]() { 214 214 creationCallback->handleEvent(*database); 215 215 database->setHasPendingCreationEvent(false); -
trunk/Source/WebCore/Modules/webdatabase/SQLTransaction.cpp
r252064 r252607 142 142 return; 143 143 144 m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(),[errorCallback = WTFMove(errorCallback)]() mutable {144 m_database->document().eventLoop().queueTask(TaskSource::Networking, [errorCallback = WTFMove(errorCallback)]() mutable { 145 145 errorCallback->handleEvent(SQLError::create(SQLError::DATABASE_ERR, "the database was closed")); 146 146 }); … … 416 416 RefPtr<SQLTransactionErrorCallback> errorCallback = m_errorCallbackWrapper.unwrap(); 417 417 if (errorCallback) { 418 m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(),[errorCallback = WTFMove(errorCallback), transactionError = m_transactionError]() mutable {418 m_database->document().eventLoop().queueTask(TaskSource::Networking, [errorCallback = WTFMove(errorCallback), transactionError = m_transactionError]() mutable { 419 419 errorCallback->handleEvent(*transactionError); 420 420 }); … … 467 467 RefPtr<VoidCallback> successCallback = m_successCallbackWrapper.unwrap(); 468 468 if (successCallback) { 469 m_database->document().eventLoop().queueTask(TaskSource::Networking, m_database->document(),[successCallback = WTFMove(successCallback)]() mutable {469 m_database->document().eventLoop().queueTask(TaskSource::Networking, [successCallback = WTFMove(successCallback)]() mutable { 470 470 successCallback->handleEvent(); 471 471 }); -
trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp
r252338 r252607 52 52 if (activeDOMObjectsAreSuspended()) { 53 53 JSC::Strong<JSC::Unknown, ShouldStrongDestructorGrabLock::Yes> strongResolution(lexicalGlobalObject.vm(), resolution); 54 scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, *scriptExecutionContext(),[this, protectedThis = makeRef(*this), mode, strongResolution = WTFMove(strongResolution)]() mutable {54 scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = makeRef(*this), mode, strongResolution = WTFMove(strongResolution)]() mutable { 55 55 if (shouldIgnoreRequestToFulfill()) 56 56 return; … … 84 84 85 85 if (activeDOMObjectsAreSuspended()) { 86 scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, *scriptExecutionContext(),[this, protectedThis = makeRef(*this), callback = WTFMove(callback)]() mutable {86 scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, [this, protectedThis = makeRef(*this), callback = WTFMove(callback)]() mutable { 87 87 whenSettled(WTFMove(callback)); 88 88 }); -
trunk/Source/WebCore/dom/AbstractEventLoop.h
r251975 r252607 29 29 #include <wtf/Function.h> 30 30 #include <wtf/RefCounted.h> 31 #include <wtf/StdLibExtras.h> 32 #include <wtf/WeakHashSet.h> 33 #include <wtf/WeakPtr.h> 31 34 32 35 namespace WebCore { 33 36 37 class EventLoopTaskGroup; 38 class EventTarget; 34 39 class ScriptExecutionContext; 35 40 41 class EventLoopTask { 42 WTF_MAKE_NONCOPYABLE(EventLoopTask); 43 WTF_MAKE_FAST_ALLOCATED; 44 45 public: 46 virtual ~EventLoopTask() = default; 47 48 TaskSource taskSource() { return m_taskSource; } 49 virtual void execute() = 0; 50 51 EventLoopTaskGroup* group() const { return m_group.get(); } 52 53 protected: 54 EventLoopTask(TaskSource, EventLoopTaskGroup&); 55 56 private: 57 const TaskSource m_taskSource; 58 WeakPtr<EventLoopTaskGroup> m_group; 59 }; 60 36 61 // https://html.spec.whatwg.org/multipage/webappapis.html#event-loop 37 class AbstractEventLoop : public RefCounted<AbstractEventLoop> {62 class AbstractEventLoop : public RefCounted<AbstractEventLoop>, public CanMakeWeakPtr<AbstractEventLoop> { 38 63 public: 39 64 virtual ~AbstractEventLoop() = default; 40 65 41 typedef WTF::Function<void ()> TaskFunction; 42 virtual void queueTask(TaskSource, ScriptExecutionContext&, TaskFunction&&) = 0; 66 typedef Function<void ()> TaskFunction; 67 void queueTask(std::unique_ptr<EventLoopTask>&&); 68 69 void resumeGroup(EventLoopTaskGroup&); 70 void stopGroup(EventLoopTaskGroup&); 43 71 44 72 protected: 45 73 AbstractEventLoop() = default; 74 void run(); 75 void clearAllTasks(); 76 77 private: 78 void scheduleToRunIfNeeded(); 79 virtual void scheduleToRun() = 0; 80 virtual bool isContextThread() const = 0; 81 82 // Use a global queue instead of multiple task queues since HTML5 spec allows UA to pick arbitrary queue. 83 Vector<std::unique_ptr<EventLoopTask>> m_tasks; 84 WeakHashSet<EventLoopTaskGroup> m_groupsWithSuspenedTasks; 85 bool m_isScheduledToRun { false }; 46 86 }; 47 87 88 class EventLoopTaskGroup : public CanMakeWeakPtr<EventLoopTaskGroup> { 89 WTF_MAKE_NONCOPYABLE(EventLoopTaskGroup); 90 WTF_MAKE_FAST_ALLOCATED; 91 92 public: 93 EventLoopTaskGroup(AbstractEventLoop& eventLoop) 94 : m_eventLoop(makeWeakPtr(eventLoop)) 95 { 96 } 97 98 bool matchesTask(EventLoopTask& task) const 99 { 100 auto* group = task.group(); 101 return group == this; 102 } 103 104 void stopAndDiscardAllTasks() 105 { 106 m_state = State::Stopped; 107 if (auto* eventLoop = m_eventLoop.get()) 108 eventLoop->stopGroup(*this); 109 } 110 111 void suspend() 112 { 113 ASSERT(m_state != State::Stopped); 114 m_state = State::Suspended; 115 // We don't remove suspended tasks to preserve the ordering. 116 // AbstractEventLoop::run checks whether each task's group is suspended or not. 117 } 118 119 void resume() 120 { 121 ASSERT(m_state != State::Stopped); 122 m_state = State::Running; 123 if (auto* eventLoop = m_eventLoop.get()) 124 eventLoop->resumeGroup(*this); 125 } 126 127 bool isStoppedPermanently() { return m_state == State::Stopped; } 128 bool isSuspended() { return m_state == State::Suspended; } 129 130 void queueTask(std::unique_ptr<EventLoopTask>&& task) 131 { 132 if (m_state == State::Stopped || !m_eventLoop) 133 return; 134 ASSERT(task->group() == this); 135 m_eventLoop->queueTask(WTFMove(task)); 136 } 137 138 WEBCORE_EXPORT void queueTask(TaskSource, AbstractEventLoop::TaskFunction&&); 139 140 private: 141 enum class State : uint8_t { Running, Suspended, Stopped }; 142 143 WeakPtr<AbstractEventLoop> m_eventLoop; 144 State m_state { State::Running }; 145 }; 146 147 inline EventLoopTask::EventLoopTask(TaskSource source, EventLoopTaskGroup& group) 148 : m_taskSource(source) 149 , m_group(makeWeakPtr(group)) 150 { } 151 48 152 } // namespace WebCore -
trunk/Source/WebCore/dom/ActiveDOMObject.cpp
r252545 r252607 136 136 } 137 137 138 void ActiveDOMObject::queueTaskInEventLoop(TaskSource source, Function<void ()>&& task)138 void ActiveDOMObject::queueTaskInEventLoop(TaskSource source, Function<void ()>&& function) 139 139 { 140 140 auto* context = scriptExecutionContext(); 141 141 if (!context) 142 142 return; 143 context->eventLoop().queueTask(source, *context, WTFMove(task)); 143 context->eventLoop().queueTask(source, WTFMove(function)); 144 } 145 146 class ActiveDOMObjectEventDispatchTask : public EventLoopTask { 147 public: 148 ActiveDOMObjectEventDispatchTask(TaskSource source, EventLoopTaskGroup& group, ActiveDOMObject& object, EventTarget& target, Ref<Event>&& event) 149 : EventLoopTask(source, group) 150 , m_object(object) 151 , m_target(target) 152 , m_event(WTFMove(event)) 153 { 154 ++m_object.m_pendingActivityCount; 155 } 156 157 ~ActiveDOMObjectEventDispatchTask() 158 { 159 ASSERT(m_object.m_pendingActivityCount); 160 --m_object.m_pendingActivityCount; 161 } 162 163 void execute() final { m_target->dispatchEvent(m_event.get()); } 164 165 private: 166 ActiveDOMObject& m_object; 167 Ref<EventTarget> m_target; 168 Ref<Event> m_event; 169 }; 170 171 void ActiveDOMObject::queueTaskToDispatchEventInternal(EventTarget& target, TaskSource source, Ref<Event>&& event) 172 { 173 ASSERT(!event->target() || &target == event->target()); 174 auto* context = scriptExecutionContext(); 175 if (!context) 176 return; 177 auto& eventLoopTaskGroup = context->eventLoop(); 178 auto task = makeUnique<ActiveDOMObjectEventDispatchTask>(source, eventLoopTaskGroup, *this, target, WTFMove(event)); 179 eventLoopTaskGroup.queueTask(WTFMove(task)); 144 180 } 145 181 -
trunk/Source/WebCore/dom/ActiveDOMObject.h
r252212 r252607 38 38 39 39 class Document; 40 class Event; 41 class EventLoopTaskGroup; 42 class EventTarget; 40 43 41 44 enum class ReasonForSuspension { … … 117 120 static void queueTaskKeepingObjectAlive(T& object, TaskSource source, Function<void ()>&& task) 118 121 { 119 object.queueTaskInEventLoop(source, [protectedObject = makeRef(object), activity = object. makePendingActivity(object), task = WTFMove(task)] () {122 object.queueTaskInEventLoop(source, [protectedObject = makeRef(object), activity = object.ActiveDOMObject::makePendingActivity(object), task = WTFMove(task)] () { 120 123 task(); 121 124 }); … … 125 128 static void queueTaskToDispatchEvent(EventTargetType& target, TaskSource source, Ref<EventType>&& event) 126 129 { 127 ASSERT(!event->target() || &target == event->target()); 128 queueTaskKeepingObjectAlive(target, source, [&target, event = WTFMove(event)] () mutable { 129 target.dispatchEvent(event.get()); 130 }); 130 target.queueTaskToDispatchEventInternal(target, source, WTFMove(event)); 131 131 } 132 132 … … 142 142 143 143 void queueTaskInEventLoop(TaskSource, Function<void ()>&&); 144 void queueTaskToDispatchEventInternal(EventTarget&, TaskSource, Ref<Event>&&); 144 145 145 146 unsigned m_pendingActivityCount { 0 }; … … 148 149 Ref<Thread> m_creationThread { Thread::current() }; 149 150 #endif 151 152 friend class ActiveDOMObjectEventDispatchTask; 150 153 }; 151 154 -
trunk/Source/WebCore/dom/Document.cpp
r252546 r252607 2647 2647 void Document::suspendActiveDOMObjects(ReasonForSuspension why) 2648 2648 { 2649 if (m_ eventLoop)2650 m_ eventLoop->suspend(*this);2649 if (m_documentTaskGroup) 2650 m_documentTaskGroup->suspend(); 2651 2651 ScriptExecutionContext::suspendActiveDOMObjects(why); 2652 2652 suspendDeviceMotionAndOrientationUpdates(); … … 2656 2656 void Document::resumeActiveDOMObjects(ReasonForSuspension why) 2657 2657 { 2658 if (m_ eventLoop)2659 m_ eventLoop->resume(*this);2658 if (m_documentTaskGroup) 2659 m_documentTaskGroup->resume(); 2660 2660 ScriptExecutionContext::resumeActiveDOMObjects(why); 2661 2661 resumeDeviceMotionAndOrientationUpdates(); … … 2665 2665 void Document::stopActiveDOMObjects() 2666 2666 { 2667 if (m_ eventLoop)2668 m_ eventLoop->stop(*this);2667 if (m_documentTaskGroup) 2668 m_documentTaskGroup->stopAndDiscardAllTasks(); 2669 2669 ScriptExecutionContext::stopActiveDOMObjects(); 2670 2670 platformSuspendOrStopActiveDOMObjects(); … … 6244 6244 } 6245 6245 6246 AbstractEventLoop& Document::eventLoop()6246 EventLoopTaskGroup& Document::eventLoop() 6247 6247 { 6248 6248 ASSERT(isMainThread()); 6249 if (UNLIKELY(!m_ eventLoop))6249 if (UNLIKELY(!m_documentTaskGroup)) { 6250 6250 m_eventLoop = WindowEventLoop::ensureForRegistrableDomain(RegistrableDomain { securityOrigin().data() }); 6251 return *m_eventLoop; 6251 m_documentTaskGroup = makeUnique<EventLoopTaskGroup>(*m_eventLoop); 6252 if (activeDOMObjectsAreStopped()) 6253 m_documentTaskGroup->stopAndDiscardAllTasks(); 6254 else if (activeDOMObjectsAreSuspended()) 6255 m_documentTaskGroup->suspend(); 6256 } 6257 return *m_documentTaskGroup; 6252 6258 } 6253 6259 -
trunk/Source/WebCore/dom/Document.h
r252546 r252607 122 122 class DocumentType; 123 123 class EditingBehavior; 124 class EventLoopTaskGroup; 124 125 class ExtensionStyleSheets; 125 126 class FloatQuad; … … 1064 1065 WEBCORE_EXPORT void postTask(Task&&) final; // Executes the task on context's thread asynchronously. 1065 1066 1066 AbstractEventLoop& eventLoop() final;1067 EventLoopTaskGroup& eventLoop() final; 1067 1068 1068 1069 ScriptedAnimationController* scriptedAnimationController() { return m_scriptedAnimationController.get(); } … … 2065 2066 2066 2067 RefPtr<WindowEventLoop> m_eventLoop; 2068 std::unique_ptr<EventLoopTaskGroup> m_documentTaskGroup; 2067 2069 2068 2070 #if ENABLE(SERVICE_WORKER) -
trunk/Source/WebCore/dom/IdleCallbackController.cpp
r251050 r252607 72 72 void IdleCallbackController::queueTaskToStartIdlePeriod() 73 73 { 74 m_document->eventLoop().queueTask(TaskSource::IdleTask, *m_document, [protectedDocument = makeRef(*m_document), this](){74 m_document->eventLoop().queueTask(TaskSource::IdleTask, [protectedDocument = makeRef(*m_document), this] { 75 75 RELEASE_ASSERT(protectedDocument->idleCallbackController() == this); 76 76 startIdlePeriod(); … … 101 101 void IdleCallbackController::queueTaskToInvokeIdleCallbacks(MonotonicTime deadline) 102 102 { 103 m_document->eventLoop().queueTask(TaskSource::IdleTask, *m_document, [protectedDocument = makeRef(*m_document), deadline, this](){103 m_document->eventLoop().queueTask(TaskSource::IdleTask, [protectedDocument = makeRef(*m_document), deadline, this] { 104 104 RELEASE_ASSERT(protectedDocument->idleCallbackController() == this); 105 105 invokeIdleCallbacks(deadline); -
trunk/Source/WebCore/dom/ScriptExecutionContext.h
r252263 r252607 58 58 class DatabaseContext; 59 59 class EventQueue; 60 class EventLoopTaskGroup; 60 61 class EventTarget; 61 62 class MessagePort; … … 65 66 class SecurityOrigin; 66 67 class SocketProvider; 68 enum class TaskSource : uint8_t; 67 69 68 70 #if ENABLE(SERVICE_WORKER) … … 90 92 virtual bool isJSExecutionForbidden() const = 0; 91 93 92 virtual AbstractEventLoop& eventLoop() = 0;94 virtual EventLoopTaskGroup& eventLoop() = 0; 93 95 94 96 virtual const URL& url() const = 0; -
trunk/Source/WebCore/dom/WindowEventLoop.cpp
r252221 r252607 60 60 } 61 61 62 void WindowEventLoop::queueTask(TaskSource source, ScriptExecutionContext& context, TaskFunction&& task)62 void AbstractEventLoop::queueTask(std::unique_ptr<EventLoopTask>&& task) 63 63 { 64 ASSERT( isMainThread());65 ASSERT(is <Document>(context));64 ASSERT(task->group()); 65 ASSERT(isContextThread()); 66 66 scheduleToRunIfNeeded(); 67 m_tasks.append( Task { source, WTFMove(task), downcast<Document>(context).identifier() });67 m_tasks.append(WTFMove(task)); 68 68 } 69 69 70 void WindowEventLoop::suspend(Document&)70 void AbstractEventLoop::resumeGroup(EventLoopTaskGroup& group) 71 71 { 72 ASSERT(isMainThread()); 73 } 74 75 void WindowEventLoop::resume(Document& document) 76 { 77 ASSERT(isMainThread()); 78 if (!m_documentIdentifiersForSuspendedTasks.contains(document.identifier())) 72 ASSERT(isContextThread()); 73 if (!m_groupsWithSuspenedTasks.contains(group)) 79 74 return; 80 75 scheduleToRunIfNeeded(); 81 76 } 82 77 83 void WindowEventLoop::stop(Document& document)78 void AbstractEventLoop::stopGroup(EventLoopTaskGroup& group) 84 79 { 85 m_tasks.removeAllMatching([identifier = document.identifier()] (auto& task) { 86 return task.documentIdentifier == identifier; 80 ASSERT(isContextThread()); 81 m_tasks.removeAllMatching([&group] (auto& task) { 82 return group.matchesTask(*task); 87 83 }); 88 84 } 89 85 90 void WindowEventLoop::scheduleToRunIfNeeded()86 void AbstractEventLoop::scheduleToRunIfNeeded() 91 87 { 92 88 if (m_isScheduledToRun) 93 89 return; 90 m_isScheduledToRun = true; 91 scheduleToRun(); 92 } 94 93 95 m_isScheduledToRun = true; 94 void WindowEventLoop::scheduleToRun() 95 { 96 96 callOnMainThread([eventLoop = makeRef(*this)] () { 97 eventLoop->m_isScheduledToRun = false;98 97 eventLoop->run(); 99 98 }); 100 99 } 101 100 102 void WindowEventLoop::run() 101 bool WindowEventLoop::isContextThread() const 103 102 { 103 return isMainThread(); 104 } 105 106 void AbstractEventLoop::run() 107 { 108 m_isScheduledToRun = false; 104 109 if (m_tasks.isEmpty()) 105 110 return; 106 111 107 Vector<Task> tasks = WTFMove(m_tasks);108 m_ documentIdentifiersForSuspendedTasks.clear();109 Vector< Task> remainingTasks;112 auto tasks = std::exchange(m_tasks, { }); 113 m_groupsWithSuspenedTasks.clear(); 114 Vector<std::unique_ptr<EventLoopTask>> remainingTasks; 110 115 for (auto& task : tasks) { 111 auto* document = Document::allDocumentsMap().get(task.documentIdentifier);112 if (! document || document->activeDOMObjectsAreStopped())116 auto* group = task->group(); 117 if (!group || group->isStoppedPermanently()) 113 118 continue; 114 if (document->activeDOMObjectsAreSuspended()) { 115 m_documentIdentifiersForSuspendedTasks.add(task.documentIdentifier); 119 120 if (group->isSuspended()) { 121 m_groupsWithSuspenedTasks.add(group); 116 122 remainingTasks.append(WTFMove(task)); 117 123 continue; 118 124 } 119 task.task(); 125 126 task->execute(); 120 127 } 121 128 for (auto& task : m_tasks) … … 124 131 } 125 132 133 void AbstractEventLoop::clearAllTasks() 134 { 135 m_tasks.clear(); 136 m_groupsWithSuspenedTasks.clear(); 137 } 138 139 class EventLoopFunctionDispatchTask : public EventLoopTask { 140 public: 141 EventLoopFunctionDispatchTask(TaskSource source, EventLoopTaskGroup& group, AbstractEventLoop::TaskFunction&& function) 142 : EventLoopTask(source, group) 143 , m_function(WTFMove(function)) 144 { 145 } 146 147 void execute() final { m_function(); } 148 149 private: 150 AbstractEventLoop::TaskFunction m_function; 151 }; 152 153 void EventLoopTaskGroup::queueTask(TaskSource source, AbstractEventLoop::TaskFunction&& function) 154 { 155 return queueTask(makeUnique<EventLoopFunctionDispatchTask>(source, *this, WTFMove(function))); 156 } 157 126 158 } // namespace WebCore -
trunk/Source/WebCore/dom/WindowEventLoop.h
r252221 r252607 42 42 ~WindowEventLoop(); 43 43 44 void queueTask(TaskSource, ScriptExecutionContext&, TaskFunction&&) override;45 46 void suspend(Document&);47 void resume(Document&);48 void stop(Document&);49 50 44 private: 51 45 WindowEventLoop(const RegistrableDomain&); 52 46 53 void scheduleToRun IfNeeded();54 void run();47 void scheduleToRun() final; 48 bool isContextThread() const final; 55 49 56 struct Task {57 TaskSource source;58 TaskFunction task;59 DocumentIdentifier documentIdentifier;60 };61 62 // Use a global queue instead of multiple task queues since HTML5 spec allows UA to pick arbitrary queue.63 Vector<Task> m_tasks;64 HashSet<DocumentIdentifier> m_documentIdentifiersForSuspendedTasks;65 50 RegistrableDomain m_domain; 66 bool m_isScheduledToRun { false };67 51 }; 68 52 -
trunk/Source/WebCore/fileapi/FileReader.cpp
r251953 r252607 255 255 uint64_t taskIdentifier = ++taskIdentifierSeed; 256 256 m_pendingTasks.add(taskIdentifier, WTFMove(task)); 257 context->eventLoop().queueTask(TaskSource::FileReading, *context,[this, protectedThis = makeRef(*this), pendingActivity = makePendingActivity(*this), taskIdentifier] {257 context->eventLoop().queueTask(TaskSource::FileReading, [this, protectedThis = makeRef(*this), pendingActivity = makePendingActivity(*this), taskIdentifier] { 258 258 auto task = m_pendingTasks.take(taskIdentifier); 259 259 if (task) -
trunk/Source/WebCore/testing/Internals.cpp
r252221 r252607 4685 4685 return Exception { NotSupportedError }; 4686 4686 4687 context.eventLoop().queueTask(source, context,[callback = WTFMove(callback)]() {4687 context.eventLoop().queueTask(source, [callback = WTFMove(callback)]() { 4688 4688 callback->handleEvent(); 4689 4689 }); -
trunk/Source/WebCore/workers/WorkerEventLoop.cpp
r251968 r252607 45 45 46 46 WorkerEventLoop::WorkerEventLoop(ScriptExecutionContext& context) 47 : ActiveDOMObject(&context)47 : ContextDestructionObserver(&context) 48 48 { 49 suspendIfNeeded();50 49 } 51 50 52 void WorkerEventLoop:: queueTask(TaskSource source, ScriptExecutionContext& context, TaskFunction&& function)51 void WorkerEventLoop::scheduleToRun() 53 52 { 54 if (!scriptExecutionContext()) 55 return; 56 ASSERT(scriptExecutionContext()->isContextThread()); 57 ASSERT_UNUSED(context, scriptExecutionContext() == &context); 58 m_tasks.append({ source, WTFMove(function) }); 59 scheduleToRunIfNeeded(); 60 } 61 62 const char* WorkerEventLoop::activeDOMObjectName() const 63 { 64 return "WorkerEventLoop"; 65 } 66 67 void WorkerEventLoop::suspend(ReasonForSuspension) 68 { 69 ASSERT_NOT_REACHED(); 70 } 71 72 void WorkerEventLoop::resume() 73 { 74 ASSERT_NOT_REACHED(); 75 } 76 77 void WorkerEventLoop::stop() 78 { 79 m_tasks.clear(); 80 } 81 82 void WorkerEventLoop::scheduleToRunIfNeeded() 83 { 84 auto* context = scriptExecutionContext(); 85 ASSERT(context); 86 if (m_isScheduledToRun || m_tasks.isEmpty()) 87 return; 88 89 m_isScheduledToRun = true; 90 context->postTask([eventLoop = makeRef(*this)] (ScriptExecutionContext&) { 91 eventLoop->m_isScheduledToRun = false; 53 ASSERT(scriptExecutionContext()); 54 scriptExecutionContext()->postTask([eventLoop = makeRef(*this)] (ScriptExecutionContext&) { 92 55 eventLoop->run(); 93 56 }); 94 57 } 95 58 96 void WorkerEventLoop::run() 59 bool WorkerEventLoop::isContextThread() const 97 60 { 98 auto* context = scriptExecutionContext(); 99 if (!context || context->activeDOMObjectsAreStopped() || context->activeDOMObjectsAreSuspended()) 100 return; 101 auto tasks = std::exchange(m_tasks, Vector<Task>()); 102 for (auto& task : tasks) 103 task.task(); 61 return scriptExecutionContext()->isContextThread(); 104 62 } 105 63 -
trunk/Source/WebCore/workers/WorkerEventLoop.h
r251792 r252607 34 34 class WorkletGlobalScope; 35 35 36 class WorkerEventLoop final : public AbstractEventLoop, private ActiveDOMObject{36 class WorkerEventLoop final : public AbstractEventLoop, private ContextDestructionObserver { 37 37 public: 38 38 // Explicitly take WorkerGlobalScope and WorkletGlobalScope for documentation purposes. … … 43 43 #endif 44 44 45 void queueTask(TaskSource, ScriptExecutionContext&, TaskFunction&&) override;46 47 45 private: 48 46 explicit WorkerEventLoop(ScriptExecutionContext&); 49 47 50 void scheduleToRunIfNeeded(); 51 void run(); 52 53 // ActiveDOMObject; 54 const char* activeDOMObjectName() const override; 55 void suspend(ReasonForSuspension) override; 56 void resume() override; 57 void stop() override; 58 59 struct Task { 60 TaskSource source; 61 TaskFunction task; 62 }; 63 64 Vector<Task> m_tasks; 65 bool m_isScheduledToRun { false }; 48 void scheduleToRun() final; 49 bool isContextThread() const; 66 50 }; 67 51 -
trunk/Source/WebCore/workers/WorkerGlobalScope.cpp
r252060 r252607 106 106 } 107 107 108 AbstractEventLoop& WorkerGlobalScope::eventLoop()108 EventLoopTaskGroup& WorkerGlobalScope::eventLoop() 109 109 { 110 110 ASSERT(isContextThread()); 111 if ( !m_eventLoop)111 if (UNLIKELY(!m_defaultTaskGroup)) { 112 112 m_eventLoop = WorkerEventLoop::create(*this); 113 return *m_eventLoop; 113 m_defaultTaskGroup = makeUnique<EventLoopTaskGroup>(*m_eventLoop); 114 if (activeDOMObjectsAreStopped()) 115 m_defaultTaskGroup->stopAndDiscardAllTasks(); 116 } 117 return *m_defaultTaskGroup; 114 118 } 115 119 … … 126 130 #endif 127 131 132 if (m_defaultTaskGroup) 133 m_defaultTaskGroup->stopAndDiscardAllTasks(); 128 134 stopActiveDOMObjects(); 129 135 -
trunk/Source/WebCore/workers/WorkerGlobalScope.h
r252060 r252607 43 43 namespace WebCore { 44 44 45 class AbstractEventLoop;46 45 class ContentSecurityPolicyResponseHeaders; 47 46 class Crypto; 47 class EventLoopTaskGroup; 48 48 class MicrotaskQueue; 49 49 class Performance; … … 68 68 virtual bool isServiceWorkerGlobalScope() const { return false; } 69 69 70 AbstractEventLoop& eventLoop() final;70 EventLoopTaskGroup& eventLoop() final; 71 71 72 72 const URL& url() const final { return m_url; } … … 199 199 200 200 RefPtr<WorkerEventLoop> m_eventLoop; 201 std::unique_ptr<EventLoopTaskGroup> m_defaultTaskGroup; 201 202 202 203 mutable WorkerEventQueue m_eventQueue; -
trunk/Source/WebCore/worklets/WorkletGlobalScope.cpp
r251792 r252607 78 78 if (!m_script) 79 79 return; 80 if (m_defaultTaskGroup) 81 m_defaultTaskGroup->stopAndDiscardAllTasks(); 80 82 stopActiveDOMObjects(); 81 83 removeRejectedPromiseTracker(); … … 91 93 } 92 94 93 AbstractEventLoop& WorkletGlobalScope::eventLoop()95 EventLoopTaskGroup& WorkletGlobalScope::eventLoop() 94 96 { 95 if ( !m_eventLoop)97 if (UNLIKELY(!m_defaultTaskGroup)) { 96 98 m_eventLoop = WorkerEventLoop::create(*this); 97 return *m_eventLoop; 99 m_defaultTaskGroup = makeUnique<EventLoopTaskGroup>(*m_eventLoop); 100 if (activeDOMObjectsAreStopped()) 101 m_defaultTaskGroup->stopAndDiscardAllTasks(); 102 } 103 return *m_defaultTaskGroup; 98 104 } 99 105 -
trunk/Source/WebCore/worklets/WorkletGlobalScope.h
r252030 r252607 44 44 namespace WebCore { 45 45 46 class AbstractEventLoop;46 class EventLoopTaskGroup; 47 47 class WorkerEventLoop; 48 48 class WorkletScriptController; … … 61 61 virtual bool isPaintWorkletGlobalScope() const { return false; } 62 62 63 AbstractEventLoop& eventLoop() final;63 EventLoopTaskGroup& eventLoop() final; 64 64 65 65 const URL& url() const final { return m_code.url(); } … … 136 136 137 137 RefPtr<WorkerEventLoop> m_eventLoop; 138 std::unique_ptr<EventLoopTaskGroup> m_defaultTaskGroup; 138 139 139 140 // FIXME: This is not implemented properly, it just satisfies the compiler.
Note: See TracChangeset
for help on using the changeset viewer.