Title: [250527] trunk
Revision
250527
Author
[email protected]
Date
2019-09-30 14:00:33 -0700 (Mon, 30 Sep 2019)

Log Message

Pages with Web Workers cannot enter the back / forward cache
https://bugs.webkit.org/show_bug.cgi?id=202296
<rdar://problem/55764073>

Reviewed by Jer Noble.

Source/WebCore:

Allow pages that use Web Workers to enter the back / forward cache.
This involves adding an EventQueue for all event firing on Woker
objects and suspending this EventQueue while in the page cache.

This was preventing some of the pages on weather.com to enter the
back / forward cache.

Test: fast/workers/worker-page-cache.html

* Modules/encryptedmedia/MediaKeySession.h:
* Modules/encryptedmedia/legacy/WebKitMediaKeySession.h:
* Modules/mediasource/MediaSource.h:
* Modules/mediasource/SourceBuffer.h:
* Modules/mediasource/SourceBufferList.h:
* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::AudioContext):
* Modules/webaudio/AudioContext.h:
* animation/DeclarativeAnimation.h:

* dom/GenericEventQueue.cpp:
(WebCore::TaskQueueConstructor::construct):
(WebCore::TaskQueueConstructor<Timer>::construct):
(WebCore::GenericEventQueueBase<T>::GenericEventQueueBase):
(WebCore::GenericEventQueueBase<T>::enqueueEvent):
(WebCore::GenericEventQueueBase<T>::dispatchOneEvent):
(WebCore::GenericEventQueueBase<T>::close):
(WebCore::GenericEventQueueBase<T>::cancelAllEvents):
(WebCore::GenericEventQueueBase<T>::hasPendingEvents const):
(WebCore::GenericEventQueueBase<T>::hasPendingEventsOfType const):
(WebCore::GenericEventQueueBase<T>::suspend):
(WebCore::GenericEventQueueBase<T>::resume):
* dom/GenericEventQueue.h:
(WebCore::GenericEventQueueBase::isSuspended const):
(WebCore::MainThreadGenericEventQueue::MainThreadGenericEventQueue):
(WebCore::GenericEventQueue::GenericEventQueue):
Rename GenericEventQueue to MainThreadGenericEventQueue since its implementation relies
on a global shared Timer to fire events. Introduce a new GenericEventQueue which can
actually be used from any thread. This is useful for MessagePort, which is used both
on the main thread and on worker threads.

* dom/MessagePort.cpp:
(WebCore::MessagePort::MessagePort):
(WebCore::MessagePort::close):
(WebCore::MessagePort::suspend):
(WebCore::MessagePort::resume):
(WebCore::MessagePort::dispatchMessages):
* dom/MessagePort.h:
Use an GenericEventQueue in MessagePort for consistency with Worker.
MessagePort is an ActiveDOMobject which returns true in canSuspend(),
we therefore need to make sure it suspends event firing while
suspended.

* html/HTMLMediaElement.h:
* html/track/TrackListBase.h:
* workers/Worker.cpp:
(WebCore::Worker::Worker):
(WebCore::Worker::terminate):
(WebCore::Worker::canSuspendForDocumentSuspension const):
(WebCore::Worker::suspend):
(WebCore::Worker::resume):
(WebCore::Worker::stop):
(WebCore::Worker::hasPendingActivity const):
(WebCore::Worker::notifyFinished):
(WebCore::Worker::enqueueEvent):
(WebCore::Worker::dispatchEvent):
* workers/Worker.h:
* workers/WorkerMessagingProxy.cpp:
(WebCore::WorkerMessagingProxy::postMessageToWorkerObject):
(WebCore::WorkerMessagingProxy::postExceptionToWorkerObject):

LayoutTests:

Add layout test coverage.

* fast/workers/worker-page-cache-expected.txt: Added.
* fast/workers/worker-page-cache.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (250526 => 250527)


--- trunk/LayoutTests/ChangeLog	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/LayoutTests/ChangeLog	2019-09-30 21:00:33 UTC (rev 250527)
@@ -1,3 +1,16 @@
+2019-09-30  Chris Dumez  <[email protected]>
+
+        Pages with Web Workers cannot enter the back / forward cache
+        https://bugs.webkit.org/show_bug.cgi?id=202296
+        <rdar://problem/55764073>
+
+        Reviewed by Jer Noble.
+
+        Add layout test coverage.
+
+        * fast/workers/worker-page-cache-expected.txt: Added.
+        * fast/workers/worker-page-cache.html: Added.
+
 2019-09-28  Said Abou-Hallawa  <[email protected]>
 
         Crash when removing the target element while animating its attributes

Added: trunk/LayoutTests/fast/workers/worker-page-cache-expected.txt (0 => 250527)


--- trunk/LayoutTests/fast/workers/worker-page-cache-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/workers/worker-page-cache-expected.txt	2019-09-30 21:00:33 UTC (rev 250527)
@@ -0,0 +1,15 @@
+Tests that pages with workers can go into the page cache.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+pageshow - not from page cache
+PASS Received message before restoring from page cache.
+pagehide - entering page cache
+pageshow - from page cache
+PASS Page entered page cache
+PASS Received message after restoring from page cache.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/workers/worker-page-cache.html (0 => 250527)


--- trunk/LayoutTests/fast/workers/worker-page-cache.html	                        (rev 0)
+++ trunk/LayoutTests/fast/workers/worker-page-cache.html	2019-09-30 21:00:33 UTC (rev 250527)
@@ -0,0 +1,51 @@
+<!-- webkit-test-runner [ enablePageCache=true ] -->
+<head>
+<script src=""
+</head>
+<body>
+<script>
+description("Tests that pages with workers can go into the page cache.");
+jsTestIsAsync = true;
+
+let restoredFromPageCache = false;
+
+window.addEventListener("pageshow", function(event) {
+  debug("pageshow - " + (event.persisted ? "" : "not ") + "from page cache");
+  if (event.persisted) {
+      testPassed("Page entered page cache");
+      restoredFromPageCache = true;
+  }
+});
+
+window.addEventListener("pagehide", function(event) {
+    debug("pagehide - " + (event.persisted ? "" : "not ") + "entering page cache");
+    if (!event.persisted) {
+        testFailed("Page failed to enter page cache");
+        finishJSTest();
+    }
+});
+
+let firstMessage = true;
+_onload_ = () => {
+    worker = new Worker('resources/worker-event-listener.js');
+    setInterval(() => {
+        worker.postMessage("");
+    }, 1);
+
+    worker._onmessage_ = function(evt) {
+        if (firstMessage) {
+            firstMessage = false;
+            testPassed("Received message before restoring from page cache.");
+            window.location = "../history/resources/page-cache-helper.html";
+            return;
+        }
+        if (restoredFromPageCache) {
+            restoredFromPageCache = false;
+            testPassed("Received message after restoring from page cache.");
+            finishJSTest();
+        }
+    };
+}
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (250526 => 250527)


--- trunk/Source/WebCore/ChangeLog	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/ChangeLog	2019-09-30 21:00:33 UTC (rev 250527)
@@ -1,3 +1,81 @@
+2019-09-30  Chris Dumez  <[email protected]>
+
+        Pages with Web Workers cannot enter the back / forward cache
+        https://bugs.webkit.org/show_bug.cgi?id=202296
+        <rdar://problem/55764073>
+
+        Reviewed by Jer Noble.
+
+        Allow pages that use Web Workers to enter the back / forward cache.
+        This involves adding an EventQueue for all event firing on Woker
+        objects and suspending this EventQueue while in the page cache.
+
+        This was preventing some of the pages on weather.com to enter the
+        back / forward cache.
+
+        Test: fast/workers/worker-page-cache.html
+
+        * Modules/encryptedmedia/MediaKeySession.h:
+        * Modules/encryptedmedia/legacy/WebKitMediaKeySession.h:
+        * Modules/mediasource/MediaSource.h:
+        * Modules/mediasource/SourceBuffer.h:
+        * Modules/mediasource/SourceBufferList.h:
+        * Modules/webaudio/AudioContext.cpp:
+        (WebCore::AudioContext::AudioContext):
+        * Modules/webaudio/AudioContext.h:
+        * animation/DeclarativeAnimation.h:
+
+        * dom/GenericEventQueue.cpp:
+        (WebCore::TaskQueueConstructor::construct):
+        (WebCore::TaskQueueConstructor<Timer>::construct):
+        (WebCore::GenericEventQueueBase<T>::GenericEventQueueBase):
+        (WebCore::GenericEventQueueBase<T>::enqueueEvent):
+        (WebCore::GenericEventQueueBase<T>::dispatchOneEvent):
+        (WebCore::GenericEventQueueBase<T>::close):
+        (WebCore::GenericEventQueueBase<T>::cancelAllEvents):
+        (WebCore::GenericEventQueueBase<T>::hasPendingEvents const):
+        (WebCore::GenericEventQueueBase<T>::hasPendingEventsOfType const):
+        (WebCore::GenericEventQueueBase<T>::suspend):
+        (WebCore::GenericEventQueueBase<T>::resume):
+        * dom/GenericEventQueue.h:
+        (WebCore::GenericEventQueueBase::isSuspended const):
+        (WebCore::MainThreadGenericEventQueue::MainThreadGenericEventQueue):
+        (WebCore::GenericEventQueue::GenericEventQueue):
+        Rename GenericEventQueue to MainThreadGenericEventQueue since its implementation relies
+        on a global shared Timer to fire events. Introduce a new GenericEventQueue which can
+        actually be used from any thread. This is useful for MessagePort, which is used both
+        on the main thread and on worker threads.
+
+        * dom/MessagePort.cpp:
+        (WebCore::MessagePort::MessagePort):
+        (WebCore::MessagePort::close):
+        (WebCore::MessagePort::suspend):
+        (WebCore::MessagePort::resume):
+        (WebCore::MessagePort::dispatchMessages):
+        * dom/MessagePort.h:
+        Use an GenericEventQueue in MessagePort for consistency with Worker.
+        MessagePort is an ActiveDOMobject which returns true in canSuspend(),
+        we therefore need to make sure it suspends event firing while
+        suspended.
+
+        * html/HTMLMediaElement.h:
+        * html/track/TrackListBase.h:
+        * workers/Worker.cpp:
+        (WebCore::Worker::Worker):
+        (WebCore::Worker::terminate):
+        (WebCore::Worker::canSuspendForDocumentSuspension const):
+        (WebCore::Worker::suspend):
+        (WebCore::Worker::resume):
+        (WebCore::Worker::stop):
+        (WebCore::Worker::hasPendingActivity const):
+        (WebCore::Worker::notifyFinished):
+        (WebCore::Worker::enqueueEvent):
+        (WebCore::Worker::dispatchEvent):
+        * workers/Worker.h:
+        * workers/WorkerMessagingProxy.cpp:
+        (WebCore::WorkerMessagingProxy::postMessageToWorkerObject):
+        (WebCore::WorkerMessagingProxy::postExceptionToWorkerObject):
+
 2019-09-27  Keith Rollin  <[email protected]>
 
         Coalesce or remove PLATFORM(MAC) || PLATFORM(IOS_FAMILY)

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h (250526 => 250527)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -114,7 +114,7 @@
     MediaKeySessionType m_sessionType;
     Ref<CDM> m_implementation;
     Ref<CDMInstanceSession> m_instanceSession;
-    GenericEventQueue m_eventQueue;
+    MainThreadGenericEventQueue m_eventQueue;
     GenericTaskQueue<Timer> m_taskQueue;
     Vector<Ref<SharedBuffer>> m_recordOfKeyUsage;
     double m_firstDecryptTime { 0 };

Modified: trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h (250526 => 250527)


--- trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeySession.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -90,7 +90,7 @@
     String m_keySystem;
     String m_sessionId;
     RefPtr<WebKitMediaKeyError> m_error;
-    GenericEventQueue m_asyncEventQueue;
+    MainThreadGenericEventQueue m_asyncEventQueue;
     std::unique_ptr<LegacyCDMSession> m_session;
 
     struct PendingKeyRequest {

Modified: trunk/Source/WebCore/Modules/mediasource/MediaSource.h (250526 => 250527)


--- trunk/Source/WebCore/Modules/mediasource/MediaSource.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/Modules/mediasource/MediaSource.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -168,7 +168,7 @@
     MediaTime m_duration;
     MediaTime m_pendingSeekTime;
     ReadyState m_readyState { ReadyState::Closed };
-    GenericEventQueue m_asyncEventQueue;
+    MainThreadGenericEventQueue m_asyncEventQueue;
 #if !RELEASE_LOG_DISABLED
     Ref<const Logger> m_logger;
     const void* m_logIdentifier { nullptr };

Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h (250526 => 250527)


--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -217,7 +217,7 @@
 
     Ref<SourceBufferPrivate> m_private;
     MediaSource* m_source;
-    GenericEventQueue m_asyncEventQueue;
+    MainThreadGenericEventQueue m_asyncEventQueue;
     AppendMode m_mode { AppendMode::Segments };
 
     Vector<unsigned char> m_pendingAppendData;

Modified: trunk/Source/WebCore/Modules/mediasource/SourceBufferList.h (250526 => 250527)


--- trunk/Source/WebCore/Modules/mediasource/SourceBufferList.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBufferList.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -84,7 +84,7 @@
     void stop() final;
     const char* activeDOMObjectName() const final;
 
-    GenericEventQueue m_asyncEventQueue;
+    MainThreadGenericEventQueue m_asyncEventQueue;
 
     Vector<RefPtr<SourceBuffer>> m_list;
 };

Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp (250526 => 250527)


--- trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp	2019-09-30 21:00:33 UTC (rev 250527)
@@ -140,7 +140,7 @@
     , m_logIdentifier(uniqueLogIdentifier())
 #endif
     , m_mediaSession(PlatformMediaSession::create(*this))
-    , m_eventQueue(makeUnique<GenericEventQueue>(*this))
+    , m_eventQueue(makeUnique<MainThreadGenericEventQueue>(*this))
 {
     // According to spec AudioContext must die only after page navigate.
     // Lets mark it as ActiveDOMObject with pending activity and unmark it in clear method.
@@ -166,7 +166,7 @@
 #endif
     , m_isOfflineContext(true)
     , m_mediaSession(PlatformMediaSession::create(*this))
-    , m_eventQueue(makeUnique<GenericEventQueue>(*this))
+    , m_eventQueue(makeUnique<MainThreadGenericEventQueue>(*this))
 {
     constructCommon();
 

Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.h (250526 => 250527)


--- trunk/Source/WebCore/Modules/webaudio/AudioContext.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -64,8 +64,8 @@
 class Document;
 class DynamicsCompressorNode;
 class GainNode;
-class GenericEventQueue;
 class HTMLMediaElement;
+class MainThreadGenericEventQueue;
 class MediaElementAudioSourceNode;
 class MediaStream;
 class MediaStreamAudioDestinationNode;
@@ -417,7 +417,7 @@
     Vector<Vector<DOMPromiseDeferred<void>>> m_stateReactions;
 
     std::unique_ptr<PlatformMediaSession> m_mediaSession;
-    std::unique_ptr<GenericEventQueue> m_eventQueue;
+    std::unique_ptr<MainThreadGenericEventQueue> m_eventQueue;
 
     RefPtr<AudioBuffer> m_renderTarget;
     RefPtr<AudioDestinationNode> m_destinationNode;

Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.h (250526 => 250527)


--- trunk/Source/WebCore/animation/DeclarativeAnimation.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -88,7 +88,7 @@
     bool m_wasPending { false };
     AnimationEffectPhase m_previousPhase { AnimationEffectPhase::Idle };
 
-    GenericEventQueue m_eventQueue;
+    MainThreadGenericEventQueue m_eventQueue;
 
     Element* m_owningElement;
     Ref<Animation> m_backingAnimation;

Modified: trunk/Source/WebCore/dom/GenericEventQueue.cpp (250526 => 250527)


--- trunk/Source/WebCore/dom/GenericEventQueue.cpp	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/dom/GenericEventQueue.cpp	2019-09-30 21:00:33 UTC (rev 250527)
@@ -36,15 +36,26 @@
 
 namespace WebCore {
 
-GenericEventQueue::GenericEventQueue(EventTarget& owner)
+template<typename T> struct TaskQueueConstructor {
+    static GenericTaskQueue<T> construct(ScriptExecutionContext* context) { return GenericTaskQueue<T>(context); }
+};
+
+template<> struct TaskQueueConstructor<Timer> {
+    static GenericTaskQueue<Timer> construct(ScriptExecutionContext*) { return GenericTaskQueue<Timer>(); }
+};
+
+template<typename T>
+GenericEventQueueBase<T>::GenericEventQueueBase(EventTarget& owner)
     : m_owner(owner)
-    , m_isClosed(false)
+    , m_taskQueue(TaskQueueConstructor<T>::construct(owner.scriptExecutionContext()))
 {
 }
 
-GenericEventQueue::~GenericEventQueue() = default;
+template<typename T>
+GenericEventQueueBase<T>::~GenericEventQueueBase() = default;
 
-void GenericEventQueue::enqueueEvent(RefPtr<Event>&& event)
+template<typename T>
+void GenericEventQueueBase<T>::enqueueEvent(RefPtr<Event>&& event)
 {
     if (m_isClosed)
         return;
@@ -57,10 +68,11 @@
     if (m_isSuspended)
         return;
 
-    m_taskQueue.enqueueTask(std::bind(&GenericEventQueue::dispatchOneEvent, this));
+    m_taskQueue.enqueueTask(std::bind(&GenericEventQueueBase::dispatchOneEvent, this));
 }
 
-void GenericEventQueue::dispatchOneEvent()
+template<typename T>
+void GenericEventQueueBase<T>::dispatchOneEvent()
 {
     ASSERT(!m_pendingEvents.isEmpty());
 
@@ -73,7 +85,8 @@
     target.dispatchEvent(*event);
 }
 
-void GenericEventQueue::close()
+template<typename T>
+void GenericEventQueueBase<T>::close()
 {
     m_isClosed = true;
 
@@ -81,18 +94,21 @@
     m_pendingEvents.clear();
 }
 
-void GenericEventQueue::cancelAllEvents()
+template<typename T>
+void GenericEventQueueBase<T>::cancelAllEvents()
 {
     m_taskQueue.cancelAllTasks();
     m_pendingEvents.clear();
 }
 
-bool GenericEventQueue::hasPendingEvents() const
+template<typename T>
+bool GenericEventQueueBase<T>::hasPendingEvents() const
 {
     return !m_pendingEvents.isEmpty();
 }
 
-bool GenericEventQueue::hasPendingEventsOfType(const AtomString& type) const
+template<typename T>
+bool GenericEventQueueBase<T>::hasPendingEventsOfType(const AtomString& type) const
 {
     for (auto& event : m_pendingEvents) {
         if (event->type() == type)
@@ -102,7 +118,8 @@
     return false;
 }
 
-void GenericEventQueue::suspend()
+template<typename T>
+void GenericEventQueueBase<T>::suspend()
 {
     ASSERT(!m_isSuspended);
     m_isSuspended = true;
@@ -109,7 +126,8 @@
     m_taskQueue.cancelAllTasks();
 }
 
-void GenericEventQueue::resume()
+template<typename T>
+void GenericEventQueueBase<T>::resume()
 {
     if (!m_isSuspended)
         return;
@@ -117,7 +135,10 @@
     m_isSuspended = false;
 
     for (unsigned i = 0; i < m_pendingEvents.size(); ++i)
-        m_taskQueue.enqueueTask(std::bind(&GenericEventQueue::dispatchOneEvent, this));
+        m_taskQueue.enqueueTask(std::bind(&GenericEventQueueBase::dispatchOneEvent, this));
 }
 
+template class GenericEventQueueBase<Timer>;
+template class GenericEventQueueBase<ScriptExecutionContext>;
+
 }

Modified: trunk/Source/WebCore/dom/GenericEventQueue.h (250526 => 250527)


--- trunk/Source/WebCore/dom/GenericEventQueue.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/dom/GenericEventQueue.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -35,12 +35,14 @@
 class Event;
 class EventTarget;
 class Timer;
+class ScriptExecutionContext;
 
-class GenericEventQueue {
+template<typename T>
+class GenericEventQueueBase {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    explicit GenericEventQueue(EventTarget&);
-    ~GenericEventQueue();
+    explicit GenericEventQueueBase(EventTarget&);
+    ~GenericEventQueueBase();
 
     void enqueueEvent(RefPtr<Event>&&);
     void close();
@@ -52,14 +54,34 @@
     void suspend();
     void resume();
 
+    bool isSuspended() const { return m_isSuspended; }
+
 private:
     void dispatchOneEvent();
 
     EventTarget& m_owner;
-    GenericTaskQueue<Timer> m_taskQueue;
+    GenericTaskQueue<T> m_taskQueue;
     Deque<RefPtr<Event>> m_pendingEvents;
-    bool m_isClosed;
+    bool m_isClosed { false };
     bool m_isSuspended { false };
 };
 
+// All instances of MainThreadGenericEventQueue use a shared Timer for dispatching events.
+class MainThreadGenericEventQueue : public GenericEventQueueBase<Timer> {
+public:
+    explicit MainThreadGenericEventQueue(EventTarget& eventTarget)
+        : GenericEventQueueBase<Timer>(eventTarget)
+    {
+    }
+};
+
+class GenericEventQueue : public GenericEventQueueBase<ScriptExecutionContext> {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit GenericEventQueue(EventTarget& eventTarget)
+        : GenericEventQueueBase<ScriptExecutionContext>(eventTarget)
+    {
+    }
+};
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/MessagePort.cpp (250526 => 250527)


--- trunk/Source/WebCore/dom/MessagePort.cpp	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/dom/MessagePort.cpp	2019-09-30 21:00:33 UTC (rev 250527)
@@ -98,6 +98,7 @@
     : ActiveDOMObject(&scriptExecutionContext)
     , m_identifier(local)
     , m_remoteIdentifier(remote)
+    , m_eventQueue(*this)
 {
     LOG(MessagePorts, "Created MessagePort %s (%p) in process %" PRIu64, m_identifier.logString().utf8().data(), this, Process::identifier().toUInt64());
 
@@ -227,8 +228,19 @@
 
     MessagePortChannelProvider::fromContext(*m_scriptExecutionContext).messagePortClosed(m_identifier);
     removeAllEventListeners();
+    m_eventQueue.close();
 }
 
+void MessagePort::suspend(ReasonForSuspension)
+{
+    m_eventQueue.suspend();
+}
+
+void MessagePort::resume()
+{
+    m_eventQueue.resume();
+}
+
 void MessagePort::contextDestroyed()
 {
     ASSERT(m_scriptExecutionContext);
@@ -268,7 +280,7 @@
             if (contextIsWorker && downcast<WorkerGlobalScope>(*m_scriptExecutionContext).isClosing())
                 return;
             auto ports = MessagePort::entanglePorts(*m_scriptExecutionContext, WTFMove(message.transferredPorts));
-            dispatchEvent(MessageEvent::create(WTFMove(ports), message.message.releaseNonNull()));
+            m_eventQueue.enqueueEvent(MessageEvent::create(WTFMove(ports), message.message.releaseNonNull()));
         }
     };
 

Modified: trunk/Source/WebCore/dom/MessagePort.h (250526 => 250527)


--- trunk/Source/WebCore/dom/MessagePort.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/dom/MessagePort.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -29,6 +29,7 @@
 #include "ActiveDOMObject.h"
 #include "EventTarget.h"
 #include "ExceptionOr.h"
+#include "GenericEventQueue.h"
 #include "MessagePortChannel.h"
 #include "MessagePortIdentifier.h"
 #include "MessageWithMessagePorts.h"
@@ -84,6 +85,8 @@
     // ActiveDOMObject
     const char* activeDOMObjectName() const final;
     bool canSuspendForDocumentSuspension() const final;
+    void suspend(ReasonForSuspension) final;
+    void resume() final;
     void contextDestroyed() final;
     void stop() final { close(); }
     bool hasPendingActivity() const final;
@@ -126,6 +129,7 @@
     MessagePortIdentifier m_remoteIdentifier;
 
     mutable std::atomic<unsigned> m_refCount { 1 };
+    GenericEventQueue m_eventQueue;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (250526 => 250527)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -972,7 +972,7 @@
     GenericTaskQueue<Timer> m_fullscreenTaskQueue;
     GenericTaskQueue<Timer> m_playbackTargetIsWirelessQueue;
     RefPtr<TimeRanges> m_playedTimeRanges;
-    GenericEventQueue m_asyncEventQueue;
+    MainThreadGenericEventQueue m_asyncEventQueue;
 #if PLATFORM(IOS_FAMILY)
     DeferrableTask<Timer> m_volumeRevertTaskQueue;
 #endif

Modified: trunk/Source/WebCore/html/track/TrackListBase.h (250526 => 250527)


--- trunk/Source/WebCore/html/track/TrackListBase.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/html/track/TrackListBase.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -86,7 +86,7 @@
 
     HTMLMediaElement* m_element;
 
-    GenericEventQueue m_asyncEventQueue;
+    MainThreadGenericEventQueue m_asyncEventQueue;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/Worker.cpp (250526 => 250527)


--- trunk/Source/WebCore/workers/Worker.cpp	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/workers/Worker.cpp	2019-09-30 21:00:33 UTC (rev 250527)
@@ -28,6 +28,7 @@
 #include "Worker.h"
 
 #include "ContentSecurityPolicy.h"
+#include "ErrorEvent.h"
 #include "Event.h"
 #include "EventNames.h"
 #include "InspectorInstrumentation.h"
@@ -67,6 +68,7 @@
     , m_identifier("worker:" + Inspector::IdentifiersFactory::createIdentifier())
     , m_contextProxy(WorkerGlobalScopeProxy::create(*this))
     , m_runtimeFlags(runtimeFlags)
+    , m_eventQueue(*this)
 {
     static bool addedListener;
     if (!addedListener) {
@@ -144,14 +146,24 @@
 void Worker::terminate()
 {
     m_contextProxy.terminateWorkerGlobalScope();
+    m_eventQueue.cancelAllEvents();
 }
 
 bool Worker::canSuspendForDocumentSuspension() const
 {
-    // FIXME: It is not currently possible to suspend a worker, so pages with workers can not go into page cache.
-    return false;
+    return true;
 }
 
+void Worker::suspend(ReasonForSuspension)
+{
+    m_eventQueue.suspend();
+}
+
+void Worker::resume()
+{
+    m_eventQueue.resume();
+}
+
 const char* Worker::activeDOMObjectName() const
 {
     return "Worker";
@@ -160,11 +172,12 @@
 void Worker::stop()
 {
     terminate();
+    m_eventQueue.close();
 }
 
 bool Worker::hasPendingActivity() const
 {
-    return m_contextProxy.hasPendingActivity() || ActiveDOMObject::hasPendingActivity();
+    return m_contextProxy.hasPendingActivity() || ActiveDOMObject::hasPendingActivity() || m_eventQueue.hasPendingEvents();
 }
 
 void Worker::notifyNetworkStateChange(bool isOnLine)
@@ -192,7 +205,7 @@
         return;
 
     if (m_scriptLoader->failed()) {
-        dispatchEvent(Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::Yes));
+        enqueueEvent(Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::Yes));
         return;
     }
 
@@ -202,4 +215,20 @@
     InspectorInstrumentation::scriptImported(*context, m_scriptLoader->identifier(), m_scriptLoader->script());
 }
 
+void Worker::enqueueEvent(Ref<Event>&& event)
+{
+    m_eventQueue.enqueueEvent(WTFMove(event));
+}
+
+void Worker::dispatchEvent(Event& event)
+{
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!m_eventQueue.isSuspended());
+
+    AbstractWorker::dispatchEvent(event);
+    if (is<ErrorEvent>(event) && !event.defaultPrevented() && event.isTrusted() && scriptExecutionContext()) {
+        auto& errorEvent = downcast<ErrorEvent>(event);
+        scriptExecutionContext()->reportException(errorEvent.message(), errorEvent.lineno(), errorEvent.colno(), errorEvent.filename(), nullptr, nullptr);
+    }
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/Worker.h (250526 => 250527)


--- trunk/Source/WebCore/workers/Worker.h	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/workers/Worker.h	2019-09-30 21:00:33 UTC (rev 250527)
@@ -29,6 +29,7 @@
 #include "ActiveDOMObject.h"
 #include "ContentSecurityPolicyResponseHeaders.h"
 #include "EventTarget.h"
+#include "GenericEventQueue.h"
 #include "MessagePort.h"
 #include "WorkerScriptLoaderClient.h"
 #include <_javascript_Core/RuntimeFlags.h>
@@ -67,9 +68,13 @@
 
     ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
 
+    void enqueueEvent(Ref<Event>&&);
+
 private:
     explicit Worker(ScriptExecutionContext&, JSC::RuntimeFlags, const Options&);
 
+    void dispatchEvent(Event&) final;
+
     EventTargetInterface eventTargetInterface() const final { return WorkerEventTargetInterfaceType; }
 
     void notifyNetworkStateChange(bool isOnline);
@@ -78,6 +83,8 @@
     void notifyFinished() final;
 
     bool canSuspendForDocumentSuspension() const final;
+    void suspend(ReasonForSuspension) final;
+    void resume() final;
     void stop() final;
     const char* activeDOMObjectName() const final;
 
@@ -91,6 +98,7 @@
     MonotonicTime m_workerCreationTime;
     bool m_shouldBypassMainWorldContentSecurityPolicy { false };
     JSC::RuntimeFlags m_runtimeFlags;
+    GenericEventQueue m_eventQueue;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp (250526 => 250527)


--- trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp	2019-09-30 20:27:13 UTC (rev 250526)
+++ trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp	2019-09-30 21:00:33 UTC (rev 250527)
@@ -104,7 +104,7 @@
             return;
 
         auto ports = MessagePort::entanglePorts(context, WTFMove(message.transferredPorts));
-        workerObject->dispatchEvent(MessageEvent::create(WTFMove(ports), message.message.releaseNonNull()));
+        workerObject->enqueueEvent(MessageEvent::create(WTFMove(ports), message.message.releaseNonNull()));
     });
 }
 
@@ -154,7 +154,7 @@
 
 void WorkerMessagingProxy::postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL)
 {
-    m_scriptExecutionContext->postTask([this, errorMessage = errorMessage.isolatedCopy(), sourceURL = sourceURL.isolatedCopy(), lineNumber, columnNumber] (ScriptExecutionContext& context) {
+    m_scriptExecutionContext->postTask([this, errorMessage = errorMessage.isolatedCopy(), sourceURL = sourceURL.isolatedCopy(), lineNumber, columnNumber] (ScriptExecutionContext&) {
         Worker* workerObject = this->workerObject();
         if (!workerObject)
             return;
@@ -161,11 +161,7 @@
 
         // We don't bother checking the askedToTerminate() flag here, because exceptions should *always* be reported even if the thread is terminated.
         // This is intentionally different than the behavior in MessageWorkerTask, because terminated workers no longer deliver messages (section 4.6 of the WebWorker spec), but they do report exceptions.
-
-        auto event = ErrorEvent::create(errorMessage, sourceURL, lineNumber, columnNumber, { });
-        workerObject->dispatchEvent(event);
-        if (!event->defaultPrevented())
-            context.reportException(errorMessage, lineNumber, columnNumber, sourceURL, nullptr, nullptr);
+        workerObject->enqueueEvent(ErrorEvent::create(errorMessage, sourceURL, lineNumber, columnNumber, { }));
     });
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to