From a807e3f1eae4029891e39c63c1d7067979cc6cec Mon Sep 17 00:00:00 2001
From: Jens Stutte <jstutte@mozilla.com>
Date: Tue, 30 Jan 2024 14:43:17 +0000
Subject: [PATCH] Bug 1867982 - Check if WorkerRunnable::Run runs on top of
 WorkerThreadPrimaryRunnable::Run in a worker thread.  a=RyanVM

Original Revision: https://phabricator.services.mozilla.com/D199247

Differential Revision: https://phabricator.services.mozilla.com/D199970
---
 dom/workers/WorkerPrivate.cpp  |  4 +++-
 dom/workers/WorkerRunnable.cpp | 28 ++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index fc349c16422da..6998d02308c6e 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3770,7 +3770,9 @@ void WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot) {
   if (WorkerRan == aRanOrNot) {
     nsIThread* currentThread = NS_GetCurrentThread();
     MOZ_ASSERT(currentThread);
-    MOZ_ASSERT(!NS_HasPendingEvents(currentThread));
+    // On the worker thread WorkerRunnable will refuse to run if not nested
+    // on top of a WorkerThreadPrimaryRunnable.
+    Unused << NS_WARN_IF(NS_HasPendingEvents(currentThread));
   }
 #endif
 
diff --git a/dom/workers/WorkerRunnable.cpp b/dom/workers/WorkerRunnable.cpp
index ec461d3cfb35c..f5aaa759efc88 100644
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -13,6 +13,7 @@
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/AppShutdown.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Maybe.h"
@@ -224,6 +225,33 @@ WorkerRunnable::Run() {
   bool targetIsWorkerThread = mBehavior == WorkerThreadModifyBusyCount ||
                               mBehavior == WorkerThreadUnchangedBusyCount;
 
+  if (targetIsWorkerThread) {
+    // On a worker thread, a WorkerRunnable should only run when there is an
+    // underlying WorkerThreadPrimaryRunnable active, which means we should
+    // find a CycleCollectedJSContext.
+    if (!CycleCollectedJSContext::Get()) {
+#if (defined(MOZ_COLLECTING_RUNNABLE_TELEMETRY) && defined(DEBUG))
+      // Temporarily set the LogLevel high enough to be certain the messages
+      // are visible.
+      LogModule* module = sWorkerRunnableLog;
+      LogLevel prevLevel = module->Level();
+      if (prevLevel < LogLevel::Error) {
+        module->SetLevel(LogLevel::Error);
+      }
+      MOZ_LOG(sWorkerRunnableLog, LogLevel::Error,
+              ("Runnable '%s' was executed after WorkerThreadPrimaryRunnable "
+               "ended.",
+               "WorkerRunnable"));
+      module->SetLevel(prevLevel);
+#endif
+      MOZ_DIAGNOSTIC_ASSERT(false,
+                            "A WorkerRunnable was executed after "
+                            "WorkerThreadPrimaryRunnable ended.");
+
+      return NS_OK;
+    }
+  }
+
 #ifdef DEBUG
   MOZ_ASSERT_IF(mCallingCancelWithinRun, targetIsWorkerThread);
   if (targetIsWorkerThread) {
-- 
GitLab