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, { }));
});
}