Refactor AbstractEventLoop out of WindowEventLoop
https://bugs.webkit.org/show_bug.cgi?id=203136
<rdar://problem/56396749>

Reviewed by Antti Koivisto.

Extract AbstractEventLoop out of WindowEventLoop as a preparation for adding WorkerEventLoop.

Also replaced m_activeTaskCount with a boolean m_isScheduledToRun since it doesn't need to count.

* WebCore.xcodeproj/project.pbxproj:
* dom/AbstractEventLoop.cpp: Added.
* dom/AbstractEventLoop.h: Added.
(WebCore::AbstractEventLoop): Added.
* dom/WindowEventLoop.cpp:
(WebCore::WindowEventLoop::WindowEventLoop): Deleted. Use the default constructor in the header instead.
(WebCore::WindowEventLoop::queueTask):
(WebCore::WindowEventLoop::suspend):
(WebCore::WindowEventLoop::resume):
(WebCore::WindowEventLoop::scheduleToRunIfNeeded): Extracted out of queueTask.
(WebCore::WindowEventLoop::run):
* dom/WindowEventLoop.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251308 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index c8d1ac9..9069ab6 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,28 @@
+2019-10-18  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Refactor AbstractEventLoop out of WindowEventLoop
+        https://bugs.webkit.org/show_bug.cgi?id=203136
+        <rdar://problem/56396749>
+
+        Reviewed by Antti Koivisto.
+
+        Extract AbstractEventLoop out of WindowEventLoop as a preparation for adding WorkerEventLoop.
+
+        Also replaced m_activeTaskCount with a boolean m_isScheduledToRun since it doesn't need to count.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/AbstractEventLoop.cpp: Added.
+        * dom/AbstractEventLoop.h: Added.
+        (WebCore::AbstractEventLoop): Added.
+        * dom/WindowEventLoop.cpp:
+        (WebCore::WindowEventLoop::WindowEventLoop): Deleted. Use the default constructor in the header instead.
+        (WebCore::WindowEventLoop::queueTask):
+        (WebCore::WindowEventLoop::suspend):
+        (WebCore::WindowEventLoop::resume):
+        (WebCore::WindowEventLoop::scheduleToRunIfNeeded): Extracted out of queueTask.
+        (WebCore::WindowEventLoop::run):
+        * dom/WindowEventLoop.h:
+
 2019-10-18  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Elements: allow WebKit engineers to edit UserAgent shadow trees
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 0439398..e9b5eaf0c 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -11116,6 +11116,7 @@
 		9B742608234BEA6E00DB52E9 /* IdleDeadline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IdleDeadline.h; sourceTree = "<group>"; };
 		9B742609234BEA6E00DB52E9 /* IdleDeadline.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IdleDeadline.cpp; sourceTree = "<group>"; };
 		9B74260A234BEA6E00DB52E9 /* IdleDeadline.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = IdleDeadline.idl; sourceTree = "<group>"; };
+		9B8205A5235929B100C3BF40 /* AbstractEventLoop.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractEventLoop.cpp; sourceTree = "<group>"; };
 		9B85530520E733B5009EEF4F /* EventTargetFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EventTargetFactory.cpp; path = DerivedSources/WebCore/EventTargetFactory.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		9B864F00234C028A006D10EB /* IdleRequestOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IdleRequestOptions.h; sourceTree = "<group>"; };
 		9B864F01234C028A006D10EB /* IdleRequestOptions.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = IdleRequestOptions.idl; sourceTree = "<group>"; };
@@ -27637,6 +27638,7 @@
 				7CD0E2BD1F80A56E0016A4CE /* AbortSignal.cpp */,
 				7CD0E2BC1F80A56E0016A4CE /* AbortSignal.h */,
 				7CD0E2BE1F80A56E0016A4CE /* AbortSignal.idl */,
+				9B8205A5235929B100C3BF40 /* AbstractEventLoop.cpp */,
 				7C5222971E1DAE16002CB8F7 /* ActiveDOMCallback.cpp */,
 				7C5222981E1DAE16002CB8F7 /* ActiveDOMCallback.h */,
 				7CD0BA021B8F79C9005CEBBE /* ActiveDOMCallbackMicrotask.cpp */,
diff --git a/Source/WebCore/dom/AbstractEventLoop.h b/Source/WebCore/dom/AbstractEventLoop.h
new file mode 100644
index 0000000..9ec68f8
--- /dev/null
+++ b/Source/WebCore/dom/AbstractEventLoop.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Function.h>
+
+namespace WebCore {
+
+class ScriptExecutionContext;
+
+enum class TaskSource : uint8_t {
+    IdleTask,
+};
+
+// https://html.spec.whatwg.org/multipage/webappapis.html#event-loop
+class AbstractEventLoop : public RefCounted<AbstractEventLoop> {
+public:
+    virtual ~AbstractEventLoop() = default;
+
+    typedef WTF::Function<void ()> TaskFunction;
+    virtual void queueTask(TaskSource, ScriptExecutionContext&, TaskFunction&&) = 0;
+
+    virtual void suspend(ScriptExecutionContext&) = 0;
+    virtual void resume(ScriptExecutionContext&) = 0;
+
+protected:
+    AbstractEventLoop() = default;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/WindowEventLoop.cpp b/Source/WebCore/dom/WindowEventLoop.cpp
index 698d463..c67cfda 100644
--- a/Source/WebCore/dom/WindowEventLoop.cpp
+++ b/Source/WebCore/dom/WindowEventLoop.cpp
@@ -35,38 +35,43 @@
     return adoptRef(*new WindowEventLoop);
 }
 
-WindowEventLoop::WindowEventLoop()
+void WindowEventLoop::queueTask(TaskSource source, ScriptExecutionContext& context, TaskFunction&& task)
 {
+    ASSERT(isMainThread());
+    ASSERT(is<Document>(context));
+    scheduleToRunIfNeeded();
+    m_tasks.append(Task { source, WTFMove(task), downcast<Document>(context).identifier() });
 }
 
-void WindowEventLoop::queueTask(TaskSource source, Document& document, TaskFunction&& task)
+void WindowEventLoop::suspend(ScriptExecutionContext&)
 {
-    if (!m_activeTaskCount) {
-        callOnMainThread([eventLoop = makeRef(*this)] () {
-            eventLoop->run();
-        });
-    }
-    ++m_activeTaskCount;
-    m_tasks.append(Task { source, WTFMove(task), document.identifier() });
+    ASSERT(isMainThread());
 }
 
-void WindowEventLoop::suspend(Document&)
+void WindowEventLoop::resume(ScriptExecutionContext& context)
 {
-}
-
-void WindowEventLoop::resume(Document& document)
-{
+    ASSERT(isMainThread());
+    ASSERT(is<Document>(context));
+    auto& document = downcast<Document>(context);
     if (!m_documentIdentifiersForSuspendedTasks.contains(document.identifier()))
         return;
+    scheduleToRunIfNeeded();
+}
 
+void WindowEventLoop::scheduleToRunIfNeeded()
+{
+    if (m_isScheduledToRun)
+        return;
+
+    m_isScheduledToRun = true;
     callOnMainThread([eventLoop = makeRef(*this)] () {
+        eventLoop->m_isScheduledToRun = false;
         eventLoop->run();
     });
 }
 
 void WindowEventLoop::run()
 {
-    m_activeTaskCount = 0;
     Vector<Task> tasks = WTFMove(m_tasks);
     m_documentIdentifiersForSuspendedTasks.clear();
     Vector<Task> remainingTasks;
diff --git a/Source/WebCore/dom/WindowEventLoop.h b/Source/WebCore/dom/WindowEventLoop.h
index 5e38bf5..75ff43b 100644
--- a/Source/WebCore/dom/WindowEventLoop.h
+++ b/Source/WebCore/dom/WindowEventLoop.h
@@ -25,35 +25,27 @@
 
 #pragma once
 
-#include "DocumentIdentifier.h"
-#include <memory>
+#include "AbstractEventLoop.h"
 #include <wtf/HashSet.h>
-#include <wtf/Vector.h>
 
 namespace WebCore {
 
 class Document;
 
-enum class TaskSource : uint8_t {
-    IdleTask,
-};
-
 // https://html.spec.whatwg.org/multipage/webappapis.html#window-event-loop
-class WindowEventLoop : public RefCounted<WindowEventLoop> {
-    WTF_MAKE_FAST_ALLOCATED;
+class WindowEventLoop final : public AbstractEventLoop {
 public:
     static Ref<WindowEventLoop> create();
 
-    typedef WTF::Function<void ()> TaskFunction;
+    void queueTask(TaskSource, ScriptExecutionContext&, TaskFunction&&) override;
 
-    void queueTask(TaskSource, Document&, TaskFunction&&);
-
-    void suspend(Document&);
-    void resume(Document&);
+    void suspend(ScriptExecutionContext&) override;
+    void resume(ScriptExecutionContext&) override;
 
 private:
-    WindowEventLoop();
+    WindowEventLoop() = default;
 
+    void scheduleToRunIfNeeded();
     void run();
 
     struct Task {
@@ -64,7 +56,7 @@
 
     // Use a global queue instead of multiple task queues since HTML5 spec allows UA to pick arbitrary queue.
     Vector<Task> m_tasks;
-    size_t m_activeTaskCount { 0 };
+    bool m_isScheduledToRun { false };
     HashSet<DocumentIdentifier> m_documentIdentifiersForSuspendedTasks;
 };