From db5d0c6b046edd8d0a924851f05a8bbe87b3db9f Mon Sep 17 00:00:00 2001 From: Ben Kelly Date: Fri, 21 Jul 2017 08:16:24 -0700 Subject: [PATCH] Bug 1379243 P4 Make worker EventTargetFor() return a "hybrid" WorkerEventTarget. r=baku --- dom/workers/WorkerPrivate.cpp | 22 +++++++++++++++++++++- dom/workers/WorkerPrivate.h | 6 ++++++ dom/workers/WorkerScope.cpp | 4 ++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index b9012f587b01..d58cf7f2e2a2 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -1672,7 +1672,7 @@ public: ForgetWorkerPrivate(WorkerPrivate* aWorkerPrivate) { MutexAutoLock lock(mMutex); - MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate == aWorkerPrivate); + MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate || mWorkerPrivate == aWorkerPrivate); mWorkerPrivate = nullptr; } @@ -4465,6 +4465,8 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent, , mMainThreadEventTarget(GetMainThreadEventTarget()) , mWorkerControlEventTarget(new WorkerEventTarget(this, WorkerEventTarget::Behavior::ControlOnly)) + , mWorkerHybridEventTarget(new WorkerEventTarget(this, + WorkerEventTarget::Behavior::Hybrid)) , mErrorHandlerRecursionCount(0) , mNextTimeoutId(1) , mStatus(Pending) @@ -4527,6 +4529,12 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent, WorkerPrivate::~WorkerPrivate() { mWorkerControlEventTarget->ForgetWorkerPrivate(this); + + // We force the hybrid event target to forget the thread when we + // enter the Killing state, but we do it again here to be safe. + // Its possible that we may be created and destroyed without progressing + // to Killing via some obscure code path. + mWorkerHybridEventTarget->ForgetWorkerPrivate(this); } // static @@ -5234,6 +5242,12 @@ WorkerPrivate::ControlEventTarget() return mWorkerControlEventTarget; } +nsISerialEventTarget* +WorkerPrivate::HybridEventTarget() +{ + return mWorkerHybridEventTarget; +} + void WorkerPrivate::InitializeGCTimers() { @@ -6197,6 +6211,12 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus) Close(); } + // Make sure the hybrid event target stops dispatching runnables + // once we reaching the killing state. + if (aStatus == Killing) { + mWorkerHybridEventTarget->ForgetWorkerPrivate(this); + } + eventTarget = mEventTarget; } diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 9ea9036acb22..d568b97f43ac 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -1005,6 +1005,7 @@ class WorkerPrivate : public WorkerPrivateParent RefPtr mMainThreadThrottledEventQueue; nsCOMPtr mMainThreadEventTarget; RefPtr mWorkerControlEventTarget; + RefPtr mWorkerHybridEventTarget; struct SyncLoopInfo { @@ -1464,6 +1465,11 @@ public: nsISerialEventTarget* ControlEventTarget(); + // Get an event target that will attempt to dispatch a normal WorkerRunnable, + // but if that fails will then fall back to a control runnable. + nsISerialEventTarget* + HybridEventTarget(); + private: WorkerPrivate(WorkerPrivate* aParent, const nsAString& aScriptURL, bool aIsChromeWorker, diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 2901817cd3db..dfc6c666df27 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -72,7 +72,7 @@ using mozilla::dom::cache::CacheStorage; using mozilla::ipc::PrincipalInfo; WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate) -: mSerialEventTarget(aWorkerPrivate->GetEventTarget()) +: mSerialEventTarget(aWorkerPrivate->HybridEventTarget()) , mWindowInteractionsAllowed(0) , mWorkerPrivate(aWorkerPrivate) { @@ -860,7 +860,7 @@ ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj) WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope( WorkerPrivate* aWorkerPrivate) : mWorkerPrivate(aWorkerPrivate) -, mSerialEventTarget(aWorkerPrivate->GetEventTarget()) +, mSerialEventTarget(aWorkerPrivate->HybridEventTarget()) { mWorkerPrivate->AssertIsOnWorkerThread();