diff --git a/dom/workers/WorkerRunnable.cpp b/dom/workers/WorkerRunnable.cpp index ba641ed38995..773c9ab5ceb1 100644 --- a/dom/workers/WorkerRunnable.cpp +++ b/dom/workers/WorkerRunnable.cpp @@ -677,13 +677,13 @@ WorkerProxyToMainThreadRunnable::Dispatch() { mWorkerPrivate->AssertIsOnWorkerThread(); - if (NS_WARN_IF(!mWorkerPrivate->ModifyBusyCountFromWorker(true))) { + if (NS_WARN_IF(!HoldWorker())) { RunBackOnWorkerThread(); return false; } if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(this)))) { - mWorkerPrivate->ModifyBusyCountFromWorker(false); + ReleaseWorker(); RunBackOnWorkerThread(); return false; } @@ -733,7 +733,7 @@ WorkerProxyToMainThreadRunnable::PostDispatchOnMainThread() mRunnable->RunBackOnWorkerThread(); // Let's release the worker thread. - aWorkerPrivate->ModifyBusyCountFromWorker(false); + mRunnable->ReleaseWorker(); return true; } @@ -746,3 +746,37 @@ WorkerProxyToMainThreadRunnable::PostDispatchOnMainThread() new ReleaseRunnable(mWorkerPrivate, this); NS_WARN_IF(!runnable->Dispatch()); } + +bool +WorkerProxyToMainThreadRunnable::HoldWorker() +{ + mWorkerPrivate->AssertIsOnWorkerThread(); + MOZ_ASSERT(!mWorkerHolder); + + class SimpleWorkerHolder final : public WorkerHolder + { + public: + bool Notify(Status aStatus) override + { + // We don't care about the notification. We just want to keep the + // mWorkerPrivate alive. + return true; + } + }; + + UniquePtr workerHolder(new SimpleWorkerHolder()); + if (NS_WARN_IF(!workerHolder->HoldWorker(mWorkerPrivate))) { + return false; + } + + mWorkerHolder = Move(workerHolder); + return true; +} + +void +WorkerProxyToMainThreadRunnable::ReleaseWorker() +{ + mWorkerPrivate->AssertIsOnWorkerThread(); + MOZ_ASSERT(mWorkerHolder); + mWorkerHolder = nullptr; +} diff --git a/dom/workers/WorkerRunnable.h b/dom/workers/WorkerRunnable.h index d35ebbf7c938..c65060f4485f 100644 --- a/dom/workers/WorkerRunnable.h +++ b/dom/workers/WorkerRunnable.h @@ -433,8 +433,12 @@ private: void PostDispatchOnMainThread(); + bool HoldWorker(); + void ReleaseWorker(); + protected: WorkerPrivate* mWorkerPrivate; + UniquePtr mWorkerHolder; }; // Class for checking API exposure. This totally violates the "MUST" in the