Bug 1251045 part 4. Remove the JSContext argument of WorkerRunnable::Dispatch. r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 26 Feb 2016 15:23:12 -0500
changeset 322202 a3ff598344f820ea79b85f27159b4bf5028db401
parent 322201 a482910c7d5b1aab69878c880efb93e2e3a98efd
child 322203 cb2a2fb571a1a182251f142530c7e109c8813c39
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1251045
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1251045 part 4. Remove the JSContext argument of WorkerRunnable::Dispatch. r=khuey
dom/base/Console.cpp
dom/base/WebSocket.cpp
dom/canvas/ImageBitmap.cpp
dom/fetch/Fetch.cpp
dom/indexedDB/ActorsChild.cpp
dom/notification/Notification.cpp
dom/promise/Promise.cpp
dom/promise/PromiseWorkerProxy.h
dom/push/PushManager.cpp
dom/workers/DataStore.cpp
dom/workers/RuntimeService.cpp
dom/workers/ScriptLoader.cpp
dom/workers/ServiceWorkerClients.cpp
dom/workers/ServiceWorkerPrivate.cpp
dom/workers/ServiceWorkerRegistration.cpp
dom/workers/ServiceWorkerWindowClient.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerRunnable.cpp
dom/workers/WorkerRunnable.h
dom/workers/WorkerScope.cpp
dom/workers/XMLHttpRequest.cpp
--- a/dom/base/Console.cpp
+++ b/dom/base/Console.cpp
@@ -366,17 +366,17 @@ private:
 
     private:
       ~ConsoleReleaseRunnable()
       {}
     };
 
     RefPtr<WorkerControlRunnable> runnable =
       new ConsoleReleaseRunnable(mWorkerPrivate, this);
-    runnable->Dispatch(nullptr);
+    runnable->Dispatch();
   }
 
   void
   RunWithWindow(nsPIDOMWindowInner* aWindow)
   {
     AssertIsOnMainThread();
 
     AutoJSAPI jsapi;
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -2541,17 +2541,17 @@ NS_IMETHODIMP
 WebSocketImpl::Cancel(nsresult aStatus)
 {
   AssertIsOnMainThread();
 
   if (!mIsMainThread) {
     MOZ_ASSERT(mWorkerPrivate);
     RefPtr<CancelRunnable> runnable =
       new CancelRunnable(mWorkerPrivate, this);
-    if (!runnable->Dispatch(nullptr)) {
+    if (!runnable->Dispatch()) {
       return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
   }
 
   return CancelInternal();
 }
@@ -2744,17 +2744,17 @@ WebSocketImpl::Dispatch(already_AddRefed
   MOZ_ASSERT(HasFeatureRegistered());
 #endif
 
   // If the target is a worker, we have to use a custom WorkerRunnableDispatcher
   // runnable.
   RefPtr<WorkerRunnableDispatcher> event =
     new WorkerRunnableDispatcher(this, mWorkerPrivate, event_ref.forget());
 
-  if (!event->Dispatch(nullptr)) {
+  if (!event->Dispatch()) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 WebSocketImpl::IsOnCurrentThread(bool* aResult)
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -889,17 +889,17 @@ AsyncFulfillImageBitmapPromise(Promise* 
 {
   if (NS_IsMainThread()) {
     nsCOMPtr<nsIRunnable> task =
       new FulfillImageBitmapPromiseTask(aPromise, aImageBitmap);
     NS_DispatchToCurrentThread(task); // Actually, to the main-thread.
   } else {
     RefPtr<FulfillImageBitmapPromiseWorkerTask> task =
       new FulfillImageBitmapPromiseWorkerTask(aPromise, aImageBitmap);
-    task->Dispatch(GetCurrentThreadWorkerPrivate()->GetJSContext()); // Actually, to the current worker-thread.
+    task->Dispatch(); // Actually, to the current worker-thread.
   }
 }
 
 static already_AddRefed<SourceSurface>
 DecodeBlob(Blob& aBlob)
 {
   // Get the internal stream of the blob.
   nsCOMPtr<nsIInputStream> stream;
@@ -1162,17 +1162,17 @@ AsyncCreateImageBitmapFromBlob(Promise* 
 {
   if (NS_IsMainThread()) {
     nsCOMPtr<nsIRunnable> task =
       new CreateImageBitmapFromBlobTask(aPromise, aGlobal, aBlob, aCropRect);
     NS_DispatchToCurrentThread(task); // Actually, to the main-thread.
   } else {
     RefPtr<CreateImageBitmapFromBlobWorkerTask> task =
       new CreateImageBitmapFromBlobWorkerTask(aPromise, aGlobal, aBlob, aCropRect);
-    task->Dispatch(GetCurrentThreadWorkerPrivate()->GetJSContext()); // Actually, to the current worker-thread.
+    task->Dispatch(); // Actually, to the current worker-thread.
   }
 }
 
 /* static */ already_AddRefed<Promise>
 ImageBitmap::Create(nsIGlobalObject* aGlobal, const ImageBitmapSource& aSrc,
                     const Maybe<gfx::IntRect>& aCropRect, ErrorResult& aRv)
 {
   MOZ_ASSERT(aGlobal);
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -321,38 +321,34 @@ WorkerFetchResolver::OnResponseAvailable
   if (mPromiseProxy->CleanedUp()) {
     return;
   }
 
   RefPtr<WorkerFetchResponseRunnable> r =
     new WorkerFetchResponseRunnable(mPromiseProxy->GetWorkerPrivate(), this,
                                     aResponse);
 
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  if (!r->Dispatch(jsapi.cx())) {
+  if (!r->Dispatch()) {
     NS_WARNING("Could not dispatch fetch response");
   }
 }
 
 void
 WorkerFetchResolver::OnResponseEnd()
 {
   AssertIsOnMainThread();
   MutexAutoLock lock(mPromiseProxy->Lock());
   if (mPromiseProxy->CleanedUp()) {
     return;
   }
 
   RefPtr<WorkerFetchResponseEndRunnable> r =
     new WorkerFetchResponseEndRunnable(mPromiseProxy->GetWorkerPrivate(), this);
 
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  if (!r->Dispatch(jsapi.cx())) {
+  if (!r->Dispatch()) {
     NS_WARNING("Could not dispatch fetch response end");
   }
 }
 
 namespace {
 nsresult
 ExtractFromArrayBuffer(const ArrayBuffer& aBuffer,
                        nsIInputStream** aStream)
@@ -606,18 +602,17 @@ public:
 
   ~AutoFailConsumeBody()
   {
     AssertIsOnMainThread();
     if (mBody) {
       if (mBody->mWorkerPrivate) {
         RefPtr<FailConsumeBodyWorkerRunnable<Derived>> r =
           new FailConsumeBodyWorkerRunnable<Derived>(mBody);
-        AutoSafeJSContext cx;
-        if (!r->Dispatch(cx)) {
+        if (!r->Dispatch()) {
           MOZ_CRASH("We are going to leak");
         }
       } else {
         mBody->ContinueConsumeBody(NS_ERROR_FAILURE, 0, nullptr);
       }
     }
   }
 
@@ -657,18 +652,17 @@ public:
 
     uint8_t* nonconstResult = const_cast<uint8_t*>(aResult);
     if (mFetchBody->mWorkerPrivate) {
       RefPtr<ContinueConsumeBodyRunnable<Derived>> r =
         new ContinueConsumeBodyRunnable<Derived>(mFetchBody,
                                         aStatus,
                                         aResultLength,
                                         nonconstResult);
-      AutoSafeJSContext cx;
-      if (!r->Dispatch(cx)) {
+      if (!r->Dispatch()) {
         // XXXcatalinb: The worker is shutting down, the pump will be canceled
         // by FetchBodyFeature::Notify.
         NS_WARNING("Could not dispatch ConsumeBodyRunnable");
         // Return failure so that aResult is freed.
         return NS_ERROR_FAILURE;
       }
     } else {
       mFetchBody->ContinueConsumeBody(aStatus, aResultLength, nonconstResult);
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -938,17 +938,17 @@ public:
 
   void
   OperationCompleted()
   {
     if (NS_IsMainThread()) {
       RefPtr<WorkerPermissionOperationCompleted> runnable =
         new WorkerPermissionOperationCompleted(mWorkerPrivate, this);
 
-      MOZ_ALWAYS_TRUE(runnable->Dispatch(nullptr));
+      MOZ_ALWAYS_TRUE(runnable->Dispatch());
       return;
     }
 
     MOZ_ASSERT(mActor);
     mActor->AssertIsOnOwningThread();
 
     MaybeCollectGarbageOnIPCMessage();
 
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -498,22 +498,20 @@ public:
         // Notification.
         //
         // If the dispatch fails, the worker isn't running anymore and the event
         // runnables have already run or been canceled. We can use a control
         // runnable to release the reference.
         RefPtr<ReleaseNotificationRunnable> r =
           new ReleaseNotificationRunnable(notification);
 
-        AutoJSAPI jsapi;
-        jsapi.Init();
-        if (!r->Dispatch(jsapi.cx())) {
+        if (!r->Dispatch()) {
           RefPtr<ReleaseNotificationControlRunnable> r =
             new ReleaseNotificationControlRunnable(notification);
-          MOZ_ALWAYS_TRUE(r->Dispatch(jsapi.cx()));
+          MOZ_ALWAYS_TRUE(r->Dispatch());
         }
       } else {
         notification->AssertIsOnTargetThread();
         notification->ReleaseObject();
       }
     }
   }
 
@@ -1549,18 +1547,17 @@ WorkerNotificationObserver::Observe(nsIS
     r = new NotificationEventWorkerRunnable(notification,
                                             NS_LITERAL_STRING("close"));
   } else if (!strcmp("alertshow", aTopic)) {
     r = new NotificationEventWorkerRunnable(notification,
                                             NS_LITERAL_STRING("show"));
   }
 
   MOZ_ASSERT(r);
-  AutoSafeJSContext cx;
-  if (!r->Dispatch(cx)) {
+  if (!r->Dispatch()) {
     NS_WARNING("Could not dispatch event to worker notification");
   }
   return NS_OK;
 }
 
 class NotificationClickEventCallback final : public nsINotificationStorageCallback
 {
 public:
@@ -1721,18 +1718,17 @@ Notification::ShowInternal()
   // We rely on GetPermissionInternal returning Denied on all failure codepaths.
   MOZ_ASSERT_IF(result.Failed(), permission == NotificationPermission::Denied);
   result.SuppressException();
   if (permission != NotificationPermission::Granted || !alertService) {
     if (mWorkerPrivate) {
       RefPtr<NotificationEventWorkerRunnable> r =
         new NotificationEventWorkerRunnable(this,
                                             NS_LITERAL_STRING("error"));
-      AutoSafeJSContext cx;
-      if (!r->Dispatch(cx)) {
+      if (!r->Dispatch()) {
         NS_WARNING("Could not dispatch event to worker notification");
       }
     } else {
       DispatchTrustedEvent(NS_LITERAL_STRING("error"));
     }
     return;
   }
 
@@ -2148,17 +2144,17 @@ public:
       return NS_OK;
     }
 
     RefPtr<WorkerGetResultRunnable> r =
       new WorkerGetResultRunnable(proxy->GetWorkerPrivate(),
                                   proxy,
                                   Move(mStrings));
 
-    r->Dispatch(aCx);
+    r->Dispatch();
     return NS_OK;
   }
 
 private:
   ~WorkerGetCallback()
   {}
 };
 
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -2900,17 +2900,17 @@ PromiseWorkerProxy::RunCallback(JSContex
   if (!Write(aCx, aValue)) {
     JS_ClearPendingException(aCx);
     MOZ_ASSERT(false, "cannot serialize the value with the StructuredCloneAlgorithm!");
   }
 
   RefPtr<PromiseWorkerProxyRunnable> runnable =
     new PromiseWorkerProxyRunnable(this, aFunc);
 
-  runnable->Dispatch(aCx);
+  runnable->Dispatch();
 }
 
 void
 PromiseWorkerProxy::ResolvedCallback(JSContext* aCx,
                                      JS::Handle<JS::Value> aValue)
 {
   RunCallback(aCx, aValue, &Promise::MaybeResolve);
 }
--- a/dom/promise/PromiseWorkerProxy.h
+++ b/dom/promise/PromiseWorkerProxy.h
@@ -79,19 +79,17 @@ class WorkerPrivate;
 //          return;
 //        }
 //
 //   2. Dispatch a runnable to the worker. Use GetWorkerPrivate() to acquire the
 //      worker.
 //
 //        RefPtr<FinishTaskWorkerRunnable> runnable =
 //          new FinishTaskWorkerRunnable(proxy->GetWorkerPrivate(), proxy, result);
-//        AutoJSAPI jsapi;
-//        jsapi.Init();
-//        if (!r->Dispatch(jsapi.cx())) {
+//        if (!r->Dispatch()) {
 //          // Worker is alive but not Running any more, so the Promise can't
 //          // be resolved, give up. The proxy will get Release()d at some
 //          // point.
 //
 //          // Usually do nothing, but you may want to log the fact.
 //        }
 //
 //   3. In the WorkerRunnable's WorkerRun() use WorkerPromise() to access the
--- a/dom/push/PushManager.cpp
+++ b/dom/push/PushManager.cpp
@@ -437,22 +437,19 @@ public:
 
     RefPtr<PromiseWorkerProxy> proxy = mProxy.forget();
 
     MutexAutoLock lock(proxy->Lock());
     if (proxy->CleanedUp()) {
       return NS_OK;
     }
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-
     RefPtr<UnsubscribeResultRunnable> r =
       new UnsubscribeResultRunnable(proxy, aStatus, aSuccess);
-    r->Dispatch(jsapi.cx());
+    r->Dispatch();
     return NS_OK;
   }
 
 private:
   ~WorkerUnsubscribeResultCallback()
   {
   }
 
@@ -639,34 +636,31 @@ public:
 
     RefPtr<PromiseWorkerProxy> proxy = mProxy.forget();
 
     MutexAutoLock lock(proxy->Lock());
     if (proxy->CleanedUp()) {
       return NS_OK;
     }
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-
     nsAutoString endpoint;
     nsTArray<uint8_t> rawP256dhKey, authSecret;
     if (NS_SUCCEEDED(aStatus)) {
       aStatus = GetSubscriptionParams(aSubscription, endpoint, rawP256dhKey,
                                       authSecret);
     }
 
     RefPtr<GetSubscriptionResultRunnable> r =
       new GetSubscriptionResultRunnable(proxy,
                                         aStatus,
                                         endpoint,
                                         mScope,
                                         rawP256dhKey,
                                         authSecret);
-    r->Dispatch(jsapi.cx());
+    r->Dispatch();
     return NS_OK;
   }
 
   // Convenience method for use in this file.
   void
   OnPushSubscriptionError(nsresult aStatus)
   {
     Unused << NS_WARN_IF(NS_FAILED(
@@ -908,21 +902,19 @@ public:
     }
 
     PushPermissionState state;
     nsresult rv = GetPermissionState(
       mProxy->GetWorkerPrivate()->GetPrincipal(),
       state
     );
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
     RefPtr<PermissionResultRunnable> r =
       new PermissionResultRunnable(mProxy, rv, state);
-    r->Dispatch(jsapi.cx());
+    r->Dispatch();
     return NS_OK;
   }
 
 private:
   ~PermissionStateRunnable()
   {}
 
   RefPtr<PromiseWorkerProxy> mProxy;
--- a/dom/workers/DataStore.cpp
+++ b/dom/workers/DataStore.cpp
@@ -949,21 +949,17 @@ DataStoreChangeEventProxy::HandleEvent(n
   }
 
   RefPtr<DataStoreChangeEvent> event =
     static_cast<DataStoreChangeEvent*>(aEvent);
 
   RefPtr<DispatchDataStoreChangeEventRunnable> runnable =
     new DispatchDataStoreChangeEventRunnable(this, event);
 
-  {
-    AutoSafeJSContext cx;
-    JSAutoRequest ar(cx);
-    runnable->Dispatch(cx);
-  }
+  runnable->Dispatch();
 
   return NS_OK;
 }
 
 // WorkerFeature implementation.
 
 bool
 DataStoreChangeEventProxy::Notify(JSContext* aCx, Status aStatus)
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -596,25 +596,24 @@ public:
   : mWorkerPrivate(aWorker), mFileName(aFileName), mLineNum(aLineNum)
   {
     MOZ_ASSERT(aWorker);
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   bool
-  Dispatch(JSContext* aCx)
+  Dispatch()
   {
     AutoSyncLoopHolder syncLoop(mWorkerPrivate);
 
     mSyncLoopTarget = syncLoop.EventTarget();
     MOZ_ASSERT(mSyncLoopTarget);
 
     if (NS_FAILED(NS_DispatchToMainThread(this))) {
-      JS_ReportError(aCx, "Failed to dispatch to main thread!");
       return false;
     }
 
     return syncLoop.Run();
   }
 
 private:
   ~LogViolationDetailsRunnable() {}
@@ -637,19 +636,17 @@ ContentSecurityPolicyAllows(JSContext* a
       fileName = NS_ConvertUTF8toUTF16(file.get());
     } else {
       JS_ReportPendingException(aCx);
     }
 
     RefPtr<LogViolationDetailsRunnable> runnable =
         new LogViolationDetailsRunnable(worker, fileName, lineNum);
 
-    if (!runnable->Dispatch(aCx)) {
-      JS_ReportPendingException(aCx);
-    }
+    runnable->Dispatch();
   }
 
   return worker->IsEvalAllowed();
 }
 
 void
 CTypesActivityCallback(JSContext* aCx,
                        js::CTypesActivityType aType)
@@ -1250,17 +1247,17 @@ WorkerCrossThreadDispatcher::PostTask(Wo
   if (!mWorkerPrivate) {
     NS_WARNING("Posted a task to a WorkerCrossThreadDispatcher that is no "
                "longer accepting tasks!");
     return false;
   }
 
   RefPtr<WorkerTaskRunnable> runnable =
     new WorkerTaskRunnable(mWorkerPrivate, aTask);
-  return runnable->Dispatch(nullptr);
+  return runnable->Dispatch();
 }
 
 WorkerPrivate*
 GetWorkerPrivateFromContext(JSContext* aCx)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aCx);
 
@@ -2582,17 +2579,17 @@ LogViolationDetailsRunnable::Run()
                                mFileName, scriptSample, mLineNum,
                                EmptyString(), EmptyString());
     }
   }
 
   RefPtr<MainThreadStopSyncLoopRunnable> response =
     new MainThreadStopSyncLoopRunnable(mWorkerPrivate, mSyncLoopTarget.forget(),
                                        true);
-  MOZ_ALWAYS_TRUE(response->Dispatch(nullptr));
+  MOZ_ALWAYS_TRUE(response->Dispatch());
 
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(WorkerBackgroundChildCallback, nsIIPCBackgroundChildCreateCallback)
 
 NS_IMPL_ISUPPORTS_INHERITED0(WorkerThreadPrimaryRunnable, nsRunnable)
 
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -1247,17 +1247,17 @@ private:
     if (lastIndex == mLoadInfos.Length() - 1) {
       mCacheCreator = nullptr;
     }
 
     if (firstIndex != UINT32_MAX && lastIndex != UINT32_MAX) {
       RefPtr<ScriptExecutorRunnable> runnable =
         new ScriptExecutorRunnable(*this, mSyncLoopTarget, IsMainWorkerScript(),
                                    firstIndex, lastIndex);
-      if (!runnable->Dispatch(nullptr)) {
+      if (!runnable->Dispatch()) {
         MOZ_ASSERT(false, "This should never fail!");
       }
     }
   }
 };
 
 NS_IMPL_ISUPPORTS(ScriptLoaderRunnable, nsIRunnable)
 
@@ -1677,17 +1677,17 @@ public:
                                                    getter_AddRefs(channel));
     if (NS_SUCCEEDED(mResult)) {
       channel.forget(mChannel);
     }
 
     RefPtr<MainThreadStopSyncLoopRunnable> runnable =
       new MainThreadStopSyncLoopRunnable(mParentWorker,
                                          mSyncLoopTarget.forget(), true);
-    if (!runnable->Dispatch(nullptr)) {
+    if (!runnable->Dispatch()) {
       NS_ERROR("This should never fail!");
     }
 
     return NS_OK;
   }
 
   nsresult
   GetResult() const
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -127,19 +127,17 @@ public:
     UniquePtr<ServiceWorkerClientInfo> result = swm->GetClient(workerPrivate->GetPrincipal(),
                                                                mClientId, rv);
     RefPtr<ResolvePromiseWorkerRunnable> r =
       new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
                                        mPromiseProxy, Move(result),
                                        rv.StealNSResult());
     rv.SuppressException();
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    r->Dispatch(jsapi.cx());
+    r->Dispatch();
     return NS_OK;
   }
 };
 
 class MatchAllRunnable final : public nsRunnable
 {
   class ResolvePromiseWorkerRunnable final : public WorkerRunnable
   {
@@ -207,19 +205,17 @@ public:
     nsTArray<ServiceWorkerClientInfo> result;
 
     swm->GetAllClients(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(), mScope,
                        mIncludeUncontrolled, result);
     RefPtr<ResolvePromiseWorkerRunnable> r =
       new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
                                        mPromiseProxy, result);
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    r->Dispatch(jsapi.cx());
+    r->Dispatch();
     return NS_OK;
   }
 };
 
 class ResolveClaimRunnable final : public WorkerRunnable
 {
   RefPtr<PromiseWorkerProxy> mPromiseProxy;
   nsresult mResult;
@@ -287,19 +283,17 @@ public:
     MOZ_ASSERT(swm);
 
     nsresult rv = swm->ClaimClients(workerPrivate->GetPrincipal(),
                                     mScope, mServiceWorkerID);
 
     RefPtr<ResolveClaimRunnable> r =
       new ResolveClaimRunnable(workerPrivate, mPromiseProxy, rv);
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    r->Dispatch(jsapi.cx());
+    r->Dispatch();
     return NS_OK;
   }
 };
 
 class ResolveOpenWindowRunnable final : public WorkerRunnable
 {
 public:
   ResolveOpenWindowRunnable(PromiseWorkerProxy* aPromiseProxy,
@@ -400,20 +394,17 @@ public:
         clientInfo.reset(new ServiceWorkerClientInfo(doc));
       }
     }
 
     RefPtr<ResolveOpenWindowRunnable> r =
       new ResolveOpenWindowRunnable(mPromiseProxy,
                                     Move(clientInfo),
                                     NS_OK);
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    JSContext* cx = jsapi.cx();
-    r->Dispatch(cx);
+    r->Dispatch();
 
     return NS_OK;
   }
 
   NS_IMETHOD
   OnProgressChange(nsIWebProgress* aWebProgress,
                    nsIRequest* aRequest,
                    int32_t aCurSelfProgress,
@@ -548,19 +539,17 @@ public:
                                             nsIWebProgress::NOTIFY_STATE_DOCUMENT);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
       return NS_OK;
     }
 
     RefPtr<ResolveOpenWindowRunnable> resolveRunnable =
       new ResolveOpenWindowRunnable(mPromiseProxy, nullptr, rv);
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    NS_WARN_IF(!resolveRunnable->Dispatch(jsapi.cx()));
+    NS_WARN_IF(!resolveRunnable->Dispatch());
 
     return NS_OK;
   }
 
 private:
   nsresult
   OpenWindow(nsPIDOMWindowOuter** aWindow)
   {
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -158,19 +158,17 @@ ServiceWorkerPrivate::CheckScriptEvaluat
 {
   nsresult rv = SpawnWorkerIfNeeded(LifeCycleEvent, nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_ASSERT(mKeepAliveToken);
   RefPtr<WorkerRunnable> r = new CheckScriptEvaluationWithCallback(mWorkerPrivate,
                                                                    mKeepAliveToken,
                                                                    aCallback);
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
+  if (NS_WARN_IF(!r->Dispatch())) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 namespace {
 
@@ -543,19 +541,17 @@ ServiceWorkerPrivate::SendLifeCycleEvent
   nsresult rv = SpawnWorkerIfNeeded(LifeCycleEvent, aLoadFailure);
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_ASSERT(mKeepAliveToken);
   RefPtr<WorkerRunnable> r = new LifecycleEventWorkerRunnable(mWorkerPrivate,
                                                                 mKeepAliveToken,
                                                                 aEventType,
                                                                 aCallback);
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
+  if (NS_WARN_IF(!r->Dispatch())) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 #ifndef MOZ_SIMPLEPUSH
 namespace {
@@ -675,19 +671,17 @@ ServiceWorkerPrivate::SendPushEvent(cons
 
   if (mInfo->State() == ServiceWorkerState::Activating) {
     mPendingFunctionalEvents.AppendElement(r.forget());
     return NS_OK;
   }
 
   MOZ_ASSERT(mInfo->State() == ServiceWorkerState::Activated);
 
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
+  if (NS_WARN_IF(!r->Dispatch())) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 #endif // MOZ_SIMPLEPUSH
 }
 
 nsresult
@@ -697,19 +691,17 @@ ServiceWorkerPrivate::SendPushSubscripti
   return NS_ERROR_NOT_AVAILABLE;
 #else
   nsresult rv = SpawnWorkerIfNeeded(PushSubscriptionChangeEvent, nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_ASSERT(mKeepAliveToken);
   RefPtr<WorkerRunnable> r =
     new SendPushSubscriptionChangeEventRunnable(mWorkerPrivate, mKeepAliveToken);
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
+  if (NS_WARN_IF(!r->Dispatch())) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 #endif // MOZ_SIMPLEPUSH
 }
 
 namespace {
@@ -971,19 +963,17 @@ ServiceWorkerPrivate::SendNotificationCl
 
   gDOMDisableOpenClickDelay = Preferences::GetInt("dom.disable_open_click_delay");
 
   RefPtr<WorkerRunnable> r =
     new SendNotificationClickEventRunnable(mWorkerPrivate, mKeepAliveToken,
                                            aID, aTitle, aDir, aLang,
                                            aBody, aTag, aIcon, aData,
                                            aBehavior, aScope);
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
+  if (NS_WARN_IF(!r->Dispatch())) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 namespace {
 
@@ -1346,19 +1336,17 @@ ServiceWorkerPrivate::SendFetchEvent(nsI
 
   if (mInfo->State() == ServiceWorkerState::Activating) {
     mPendingFunctionalEvents.AppendElement(r.forget());
     return NS_OK;
   }
 
   MOZ_ASSERT(mInfo->State() == ServiceWorkerState::Activated);
 
-  AutoJSAPI jsapi;
-  jsapi.Init();
-  if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
+  if (NS_WARN_IF(!r->Dispatch())) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
 ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
@@ -1538,19 +1526,17 @@ ServiceWorkerPrivate::Activated()
   // when the worker becomes activated.
   MOZ_ASSERT_IF(!mPendingFunctionalEvents.IsEmpty(), mWorkerPrivate);
 
   nsTArray<RefPtr<WorkerRunnable>> pendingEvents;
   mPendingFunctionalEvents.SwapElements(pendingEvents);
 
   for (uint32_t i = 0; i < pendingEvents.Length(); ++i) {
     RefPtr<WorkerRunnable> r = pendingEvents[i].forget();
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
+    if (NS_WARN_IF(!r->Dispatch())) {
       NS_WARNING("Failed to dispatch pending functional event!");
     }
   }
 }
 
 nsresult
 ServiceWorkerPrivate::GetDebugger(nsIWorkerDebugger** aResult)
 {
--- a/dom/workers/ServiceWorkerRegistration.cpp
+++ b/dom/workers/ServiceWorkerRegistration.cpp
@@ -383,22 +383,19 @@ public:
 
     RefPtr<PromiseWorkerProxy> proxy = mPromiseProxy.forget();
 
     MutexAutoLock lock(proxy->Lock());
     if (proxy->CleanedUp()) {
       return;
     }
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-
     RefPtr<UpdateResultRunnable> r =
       new UpdateResultRunnable(proxy, aStatus);
-    r->Dispatch(jsapi.cx());
+    r->Dispatch();
   }
 };
 
 class UpdateRunnable final : public nsRunnable
 {
 public:
   UpdateRunnable(PromiseWorkerProxy* aPromiseProxy,
                  const nsAString& aScope)
@@ -550,19 +547,17 @@ private:
     MutexAutoLock lock(proxy->Lock());
     if (proxy->CleanedUp()) {
       return;
     }
 
     RefPtr<WorkerRunnable> r =
       new FulfillUnregisterPromiseRunnable(proxy, aState);
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    r->Dispatch(jsapi.cx());
+    r->Dispatch();
   }
 };
 
 NS_IMPL_ISUPPORTS(WorkerUnregisterCallback, nsIServiceWorkerUnregisterCallback);
 
 /*
  * If the worker goes away, we still continue to unregister, but we don't try to
  * resolve the worker Promise (which doesn't exist by that point).
@@ -1196,20 +1191,17 @@ public:
 
 void
 WorkerListener::UpdateFound()
 {
   AssertIsOnMainThread();
   if (mWorkerPrivate) {
     RefPtr<FireUpdateFoundRunnable> r =
       new FireUpdateFoundRunnable(mWorkerPrivate, this);
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
-    }
+    NS_WARN_IF(!r->Dispatch());
   }
 }
 
 // Notification API extension.
 already_AddRefed<Promise>
 ServiceWorkerRegistrationWorkerThread::ShowNotification(JSContext* aCx,
                                                         const nsAString& aTitle,
                                                         const NotificationOptions& aOptions,
--- a/dom/workers/ServiceWorkerWindowClient.cpp
+++ b/dom/workers/ServiceWorkerWindowClient.cpp
@@ -113,19 +113,17 @@ private:
     if (mPromiseProxy->CleanedUp()) {
       return;
     }
 
     RefPtr<ResolveOrRejectPromiseRunnable> resolveRunnable =
       new ResolveOrRejectPromiseRunnable(mPromiseProxy->GetWorkerPrivate(),
                                          mPromiseProxy, Move(aClientInfo));
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    resolveRunnable->Dispatch(jsapi.cx());
+    resolveRunnable->Dispatch();
   }
 };
 
 } // namespace
 
 already_AddRefed<Promise>
 ServiceWorkerWindowClient::Focus(ErrorResult& aRv) const
 {
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -461,24 +461,16 @@ class ModifyBusyCountRunnable final : pu
   bool mIncrease;
 
 public:
   ModifyBusyCountRunnable(WorkerPrivate* aWorkerPrivate, bool aIncrease)
   : WorkerControlRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount),
     mIncrease(aIncrease)
   { }
 
-  // We don't need a JSContext to dispatch, since we know our PreDispatch and
-  // DispatchInternal don't throw any exceptions.
-  bool
-  Dispatch()
-  {
-    return WorkerControlRunnable::Dispatch(nullptr);
-  }
-
 private:
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
     return aWorkerPrivate->ModifyBusyCount(mIncrease);
   }
 
   virtual void
@@ -848,24 +840,16 @@ public:
   NotifyRunnable(WorkerPrivate* aWorkerPrivate, Status aStatus)
   : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
     mStatus(aStatus)
   {
     MOZ_ASSERT(aStatus == Closing || aStatus == Terminating ||
                aStatus == Canceling || aStatus == Killing);
   }
 
-  // We can be dispatched without a JSContext, because all we do with the
-  // JSContext passed to Dispatch() normally for worker runnables is call
-  // ModifyBusyCount... but that doesn't actually use its JSContext argument.
-  bool Dispatch()
-  {
-    return WorkerControlRunnable::Dispatch(nullptr);
-  }
-
 private:
   virtual bool
   PreDispatch(WorkerPrivate* aWorkerPrivate) override
   {
     aWorkerPrivate->AssertIsOnParentThread();
     // Modify here, but not in PostRun! This busy count addition will be matched
     // by the CloseEventRunnable.
     return aWorkerPrivate->ModifyBusyCount(true);
@@ -1065,17 +1049,17 @@ public:
     }
 
     // Now fire a runnable to do the same on the parent's thread if we can.
     if (aWorkerPrivate) {
       RefPtr<ReportErrorRunnable> runnable =
         new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
                                 aLineNumber, aColumnNumber, aFlags,
                                 aErrorNumber, aExnType, aMutedError);
-      return runnable->Dispatch(aCx);
+      return runnable->Dispatch();
     }
 
     // Otherwise log an error to the error console.
     LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
                       aFlags, aInnerWindowId);
     return true;
   }
 
@@ -1750,17 +1734,17 @@ TimerThreadEventTarget::Dispatch(already
   // Run the runnable we're given now (should just call DummyCallback()),
   // otherwise the timer thread will leak it...  If we run this after
   // dispatch running the event can race against resetting the timer.
   nsCOMPtr<nsIRunnable> runnable(aRunnable);
   runnable->Run();
 
   // This can fail if we're racing to terminate or cancel, should be handled
   // by the terminate or cancel code.
-  mWorkerRunnable->Dispatch(nullptr);
+  mWorkerRunnable->Dispatch();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TimerThreadEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
 {
   MOZ_ASSERT(aIsOnCurrentThread);
@@ -2628,17 +2612,17 @@ WorkerPrivateParent<Derived>::Freeze(JSC
       return true;
     }
   }
 
   DisableDebugger();
 
   RefPtr<FreezeRunnable> runnable =
     new FreezeRunnable(ParentAsWorkerPrivate());
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     return false;
   }
 
   return true;
 }
 
 template <class Derived>
 bool
@@ -2710,17 +2694,17 @@ WorkerPrivateParent<Derived>::Thaw(JSCon
 
     for (uint32_t index = 0; index < runnables.Length(); index++) {
       runnables[index]->Run();
     }
   }
 
   RefPtr<ThawRunnable> runnable =
     new ThawRunnable(ParentAsWorkerPrivate());
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     return false;
   }
 
   return true;
 }
 
 template <class Derived>
 void
@@ -2922,17 +2906,17 @@ WorkerPrivateParent<Derived>::PostMessag
   }
 
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   runnable->SetMessageSource(Move(aClientInfo));
 
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::PostMessage(
                              JSContext* aCx, JS::Handle<JS::Value> aMessage,
@@ -2964,49 +2948,46 @@ WorkerPrivateParent<Derived>::UpdateRunt
 
   {
     MutexAutoLock lock(mMutex);
     mJSSettings.runtimeOptions = aRuntimeOptions;
   }
 
   RefPtr<UpdateRuntimeOptionsRunnable> runnable =
     new UpdateRuntimeOptionsRunnable(ParentAsWorkerPrivate(), aRuntimeOptions);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     NS_WARNING("Failed to update worker context options!");
-    JS_ClearPendingException(aCx);
   }
 }
 
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::UpdatePreference(JSContext* aCx, WorkerPreference aPref, bool aValue)
 {
   AssertIsOnParentThread();
   MOZ_ASSERT(aPref >= 0 && aPref < WORKERPREF_COUNT);
 
   RefPtr<UpdatePreferenceRunnable> runnable =
     new UpdatePreferenceRunnable(ParentAsWorkerPrivate(), aPref, aValue);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     NS_WARNING("Failed to update worker preferences!");
-    JS_ClearPendingException(aCx);
   }
 }
 
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::UpdateLanguages(JSContext* aCx,
                                               const nsTArray<nsString>& aLanguages)
 {
   AssertIsOnParentThread();
 
   RefPtr<UpdateLanguagesRunnable> runnable =
     new UpdateLanguagesRunnable(ParentAsWorkerPrivate(), aLanguages);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     NS_WARNING("Failed to update worker languages!");
-    JS_ClearPendingException(aCx);
   }
 }
 
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::UpdateJSWorkerMemoryParameter(JSContext* aCx,
                                                             JSGCParamKey aKey,
                                                             uint32_t aValue)
@@ -3019,19 +3000,18 @@ WorkerPrivateParent<Derived>::UpdateJSWo
     MutexAutoLock lock(mMutex);
     found = mJSSettings.ApplyGCSetting(aKey, aValue);
   }
 
   if (found) {
     RefPtr<UpdateJSWorkerMemoryParameterRunnable> runnable =
       new UpdateJSWorkerMemoryParameterRunnable(ParentAsWorkerPrivate(), aKey,
                                                 aValue);
-    if (!runnable->Dispatch(aCx)) {
+    if (!runnable->Dispatch()) {
       NS_WARNING("Failed to update memory parameter!");
-      JS_ClearPendingException(aCx);
     }
   }
 }
 
 #ifdef JS_GC_ZEAL
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::UpdateGCZeal(JSContext* aCx, uint8_t aGCZeal,
@@ -3042,64 +3022,60 @@ WorkerPrivateParent<Derived>::UpdateGCZe
   {
     MutexAutoLock lock(mMutex);
     mJSSettings.gcZeal = aGCZeal;
     mJSSettings.gcZealFrequency = aFrequency;
   }
 
   RefPtr<UpdateGCZealRunnable> runnable =
     new UpdateGCZealRunnable(ParentAsWorkerPrivate(), aGCZeal, aFrequency);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     NS_WARNING("Failed to update worker gczeal!");
-    JS_ClearPendingException(aCx);
   }
 }
 #endif
 
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::GarbageCollect(JSContext* aCx, bool aShrinking)
 {
   AssertIsOnParentThread();
 
   RefPtr<GarbageCollectRunnable> runnable =
     new GarbageCollectRunnable(ParentAsWorkerPrivate(), aShrinking,
                                /* collectChildren = */ true);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     NS_WARNING("Failed to GC worker!");
-    JS_ClearPendingException(aCx);
   }
 }
 
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::CycleCollect(JSContext* aCx, bool aDummy)
 {
   AssertIsOnParentThread();
 
   RefPtr<CycleCollectRunnable> runnable =
     new CycleCollectRunnable(ParentAsWorkerPrivate(),
                              /* collectChildren = */ true);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     NS_WARNING("Failed to CC worker!");
-    JS_ClearPendingException(aCx);
   }
 }
 
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::OfflineStatusChangeEvent(JSContext* aCx, bool aIsOffline)
 {
   AssertIsOnParentThread();
 
   RefPtr<OfflineStatusChangeRunnable> runnable =
     new OfflineStatusChangeRunnable(ParentAsWorkerPrivate(), aIsOffline);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     NS_WARNING("Failed to dispatch offline status change event!");
-    JS_ClearPendingException(aCx);
   }
 }
 
 void
 WorkerPrivate::OfflineStatusChangeEventInternal(JSContext* aCx, bool aIsOffline)
 {
   AssertIsOnWorkerThread();
 
@@ -3143,17 +3119,17 @@ WorkerPrivateParent<Derived>::RegisterSh
   AssertIsOnMainThread();
   MOZ_ASSERT(aSharedWorker);
   MOZ_ASSERT(IsSharedWorker());
   MOZ_ASSERT(!mSharedWorkers.Contains(aSharedWorker));
 
   if (IsSharedWorker()) {
     RefPtr<MessagePortRunnable> runnable =
       new MessagePortRunnable(ParentAsWorkerPrivate(), aPort);
-    if (!runnable->Dispatch(aCx)) {
+    if (!runnable->Dispatch()) {
       return false;
     }
   }
 
   mSharedWorkers.AppendElement(aSharedWorker);
 
   // If there were other SharedWorker objects attached to this worker then they
   // may all have been frozen and this worker would need to be thawed.
@@ -3805,17 +3781,17 @@ WorkerDebugger::Initialize(const nsAStri
 
   if (!mWorkerPrivate) {
     return NS_ERROR_UNEXPECTED;
   }
 
   if (!mIsInitialized) {
     RefPtr<CompileDebuggerScriptRunnable> runnable =
       new CompileDebuggerScriptRunnable(mWorkerPrivate, aURL);
-    if (!runnable->Dispatch(aCx)) {
+    if (!runnable->Dispatch()) {
       return NS_ERROR_FAILURE;
     }
 
     mIsInitialized = true;
   }
 
   return NS_OK;
 }
@@ -3826,17 +3802,17 @@ WorkerDebugger::PostMessageMoz(const nsA
   AssertIsOnMainThread();
 
   if (!mWorkerPrivate || !mIsInitialized) {
     return NS_ERROR_UNEXPECTED;
   }
 
   RefPtr<DebuggerMessageEventRunnable> runnable =
     new DebuggerMessageEventRunnable(mWorkerPrivate, aMessage);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 WorkerDebugger::AddListener(nsIWorkerDebuggerListener* aListener)
@@ -4113,17 +4089,17 @@ WorkerPrivate::Constructor(JSContext* aC
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   worker->EnableDebugger();
 
   RefPtr<CompileScriptRunnable> compiler =
     new CompileScriptRunnable(worker, aScriptURL);
-  if (!compiler->Dispatch(aCx)) {
+  if (!compiler->Dispatch()) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   worker->mSelfRef = worker;
 
   return worker.forget();
 }
@@ -4773,17 +4749,17 @@ WorkerPrivate::ScheduleDeletion(WorkerRa
     MOZ_ASSERT(currentThread);
     MOZ_ASSERT(!NS_HasPendingEvents(currentThread));
   }
 #endif
 
   if (WorkerPrivate* parent = GetParent()) {
     RefPtr<WorkerFinishedRunnable> runnable =
       new WorkerFinishedRunnable(parent, this);
-    if (!runnable->Dispatch(nullptr)) {
+    if (!runnable->Dispatch()) {
       NS_WARNING("Failed to dispatch runnable!");
     }
   }
   else {
     RefPtr<TopLevelWorkerFinishedRunnable> runnable =
       new TopLevelWorkerFinishedRunnable(this);
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       NS_WARNING("Failed to dispatch runnable!");
@@ -5499,17 +5475,17 @@ WorkerPrivate::PostMessageToParentIntern
     timelines->AddMarkerForAllObservedDocShells(start);
     timelines->AddMarkerForAllObservedDocShells(end);
   }
 
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     aRv = NS_ERROR_FAILURE;
   }
 }
 
 void
 WorkerPrivate::EnterDebuggerEventLoop()
 {
   AssertIsOnWorkerThread();
@@ -5590,17 +5566,17 @@ WorkerPrivate::PostMessageToDebugger(con
 void
 WorkerPrivate::SetDebuggerImmediate(JSContext* aCx, dom::Function& aHandler,
                                     ErrorResult& aRv)
 {
   AssertIsOnWorkerThread();
 
   RefPtr<DebuggerImmediateRunnable> runnable =
     new DebuggerImmediateRunnable(this, aHandler);
-  if (!runnable->Dispatch(aCx)) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 void
 WorkerPrivate::ReportErrorToDebugger(const nsAString& aFilename,
                                      uint32_t aLineno,
                                      const nsAString& aMessage)
@@ -5692,17 +5668,17 @@ WorkerPrivate::NotifyInternal(JSContext*
 
     RefPtr<CloseEventRunnable> closeRunnable = new CloseEventRunnable(this);
     MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(closeRunnable)));
   }
 
   if (aStatus == Closing) {
     // Notify parent to stop sending us messages and balance our busy count.
     RefPtr<CloseRunnable> runnable = new CloseRunnable(this);
-    if (!runnable->Dispatch(aCx)) {
+    if (!runnable->Dispatch()) {
       return false;
     }
 
     // Don't abort the script.
     return true;
   }
 
   if (aStatus == Terminating) {
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -82,51 +82,23 @@ WorkerRunnable::PreDispatch(WorkerPrivat
   if (mBehavior == WorkerThreadModifyBusyCount) {
     return aWorkerPrivate->ModifyBusyCount(true);
   }
 
   return true;
 }
 
 bool
-WorkerRunnable::Dispatch(JSContext* aCx)
+WorkerRunnable::Dispatch()
 {
-  bool ok;
-
-  if (!aCx) {
-    ok = PreDispatch(mWorkerPrivate);
-    if (ok) {
-      ok = DispatchInternal();
-    }
-    PostDispatch(mWorkerPrivate, ok);
-    return ok;
+  bool ok = PreDispatch(mWorkerPrivate);
+  if (ok) {
+    ok = DispatchInternal();
   }
-
-  JSAutoRequest ar(aCx);
-
-  JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
-
-  Maybe<JSAutoCompartment> ac;
-  if (global) {
-    ac.emplace(aCx, global);
-  }
-
-  MOZ_ASSERT(!JS_IsExceptionPending(aCx));
-
-  ok = PreDispatch(mWorkerPrivate);
-  MOZ_ASSERT(!JS_IsExceptionPending(aCx));
-
-  if (ok && !DispatchInternal()) {
-    ok = false;
-  }
-  MOZ_ASSERT(!JS_IsExceptionPending(aCx));
-
   PostDispatch(mWorkerPrivate, ok);
-  MOZ_ASSERT(!JS_IsExceptionPending(aCx));
-
   return ok;
 }
 
 bool
 WorkerRunnable::DispatchInternal()
 {
   RefPtr<WorkerRunnable> runnable(this);
 
@@ -594,17 +566,17 @@ WorkerMainThreadRunnable::Run()
 
   bool runResult = MainThreadRun();
 
   RefPtr<MainThreadStopSyncLoopRunnable> response =
     new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
                                        mSyncLoopTarget.forget(),
                                        runResult);
 
-  MOZ_ALWAYS_TRUE(response->Dispatch(nullptr));
+  MOZ_ALWAYS_TRUE(response->Dispatch());
 
   return NS_OK;
 }
 
 bool
 WorkerCheckAPIExposureOnMainThreadRunnable::Dispatch()
 {
   ErrorResult rv;
--- a/dom/workers/WorkerRunnable.h
+++ b/dom/workers/WorkerRunnable.h
@@ -68,22 +68,20 @@ private:
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // If you override Cancel() then you'll need to either call the base class
   // Cancel() method or override IsCanceled() so that the Run() method bails out
   // appropriately.
   NS_DECL_NSICANCELABLERUNNABLE
 
-  // Passing a JSContext here is required for the WorkerThreadModifyBusyCount
-  // behavior. It also guarantees that any failure (false return) will throw an
-  // exception on the given context. If a context is not passed then failures
-  // must be dealt with by the caller.
+  // The return value is true if and only if both PreDispatch and
+  // DispatchInternal return true.
   bool
-  Dispatch(JSContext* aCx);
+  Dispatch();
 
   // See above note about Cancel().
   virtual bool
   IsCanceled() const
   {
     return mCanceled != 0;
   }
 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -594,19 +594,17 @@ public:
 
     WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
     swm->SetSkipWaitingFlag(workerPrivate->GetPrincipal(), mScope,
                             workerPrivate->ServiceWorkerID());
 
     RefPtr<SkipWaitingResultRunnable> runnable =
       new SkipWaitingResultRunnable(workerPrivate, mPromiseProxy);
 
-    AutoJSAPI jsapi;
-    jsapi.Init();
-    if (!runnable->Dispatch(jsapi.cx())) {
+    if (!runnable->Dispatch()) {
       NS_WARNING("Failed to dispatch SkipWaitingResultRunnable to the worker.");
     }
     return NS_OK;
   }
 };
 
 } // namespace
 
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -218,25 +218,24 @@ public:
     MOZ_ASSERT(aWorkerPrivate);
     MOZ_ASSERT(aProxy);
     aWorkerPrivate->AssertIsOnWorkerThread();
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   bool
-  Dispatch(JSContext* aCx)
+  Dispatch()
   {
     mWorkerPrivate->AssertIsOnWorkerThread();
 
     AutoSyncLoopHolder syncLoop(mWorkerPrivate);
     mSyncLoopTarget = syncLoop.EventTarget();
 
     if (NS_FAILED(NS_DispatchToMainThread(this))) {
-      JS_ReportError(aCx, "Failed to dispatch to main thread!");
       return false;
     }
 
     return syncLoop.Run();
   }
 
 protected:
   virtual ~WorkerThreadProxySyncRunnable()
@@ -590,20 +589,16 @@ public:
     mType(aType), mResponse(JS::UndefinedValue()), mLoaded(0), mTotal(0),
     mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0),
     mUploadEvent(aUploadEvent), mProgressEvent(false), mLengthComputable(0),
     mUseCachedArrayBufferResponse(false), mResponseTextResult(NS_OK),
     mStatusResult(NS_OK), mResponseResult(NS_OK),
     mScopeObj(nsContentUtils::RootingCxForThread(), aScopeObj)
   { }
 
-  void Dispatch()
-  {
-    MainThreadProxyRunnable::Dispatch(nullptr);
-  }
 private:
   ~EventRunnable()
   { }
 
   virtual bool
   PreDispatch(WorkerPrivate* /* unused */) override final;
 
   virtual bool
@@ -969,28 +964,28 @@ Proxy::Teardown(bool aSendUnpin)
     // floor.
     AddRemoveEventListeners(false, false);
     mXHR->Abort();
 
     if (mOutstandingSendCount) {
       if (aSendUnpin) {
         RefPtr<XHRUnpinRunnable> runnable =
           new XHRUnpinRunnable(mWorkerPrivate, mXMLHttpRequestPrivate);
-        if (!runnable->Dispatch(nullptr)) {
+        if (!runnable->Dispatch()) {
           NS_RUNTIMEABORT("We're going to hang at shutdown anyways.");
         }
       }
 
       if (mSyncLoopTarget) {
         // We have an unclosed sync loop.  Fix that now.
         RefPtr<MainThreadStopSyncLoopRunnable> runnable =
           new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
                                              mSyncLoopTarget.forget(),
                                              false);
-        if (!runnable->Dispatch(nullptr)) {
+        if (!runnable->Dispatch()) {
           NS_RUNTIMEABORT("We're going to hang at shutdown anyways.");
         }
       }
 
       mOutstandingSendCount = 0;
     }
 
     mWorkerPrivate = nullptr;
@@ -1141,17 +1136,17 @@ LoadStartDetectionRunnable::Run()
     if (mProxy->mOutstandingSendCount > 1) {
       mProxy->mOutstandingSendCount--;
     } else if (mProxy->mOutstandingSendCount == 1) {
       mProxy->Reset();
 
       RefPtr<ProxyCompleteRunnable> runnable =
         new ProxyCompleteRunnable(mWorkerPrivate, mProxy,
                                   mXMLHttpRequestPrivate, mChannelId);
-      if (runnable->Dispatch(nullptr)) {
+      if (runnable->Dispatch()) {
         mProxy->mWorkerPrivate = nullptr;
         mProxy->mSyncLoopTarget = nullptr;
         mProxy->mOutstandingSendCount--;
       }
     }
   }
 
   mProxy = nullptr;
@@ -1442,17 +1437,17 @@ WorkerThreadProxySyncRunnable::Run()
   mSyncLoopTarget.swap(tempTarget);
 
   mProxy->mSyncEventResponseTarget.swap(tempTarget);
 
   nsresult rv = MainThreadRun();
 
   RefPtr<ResponseRunnable> response =
     new ResponseRunnable(mWorkerPrivate, mProxy, rv);
-  if (!response->Dispatch(nullptr)) {
+  if (!response->Dispatch()) {
     MOZ_ASSERT(false, "Failed to dispatch response!");
   }
 
   mProxy->mSyncEventResponseTarget.swap(tempTarget);
 
   return NS_OK;
 }
 
@@ -1687,17 +1682,17 @@ XMLHttpRequest::ReleaseProxy(ReleaseType
         mProxy->mOuterEventStreamId++;
       }
 
       // We need to make a sync call here.
       RefPtr<SyncTeardownRunnable> runnable =
         new SyncTeardownRunnable(mWorkerPrivate, mProxy);
       mProxy = nullptr;
 
-      if (!runnable->Dispatch(nullptr)) {
+      if (!runnable->Dispatch()) {
         NS_ERROR("Failed to dispatch teardown runnable!");
       }
     }
   }
 }
 
 void
 XMLHttpRequest::MaybePin(ErrorResult& aRv)
@@ -1864,22 +1859,20 @@ XMLHttpRequest::SendInternal(SendRunnabl
   bool isSyncXHR = mProxy->mIsSyncXHR;
   if (isSyncXHR) {
     autoSyncLoop.emplace(mWorkerPrivate);
     syncLoopTarget = autoSyncLoop->EventTarget();
   }
 
   mProxy->mOuterChannelId++;
 
-  JSContext* cx = mWorkerPrivate->GetJSContext();
-
   aRunnable->SetSyncLoopTarget(syncLoopTarget);
   aRunnable->SetHaveUploadListeners(hasUploadListeners);
 
-  if (!aRunnable->Dispatch(cx)) {
+  if (!aRunnable->Dispatch()) {
     // Dispatch() may have spun the event loop and we may have already unrooted.
     // If so we don't want autoUnpin to try again.
     if (!mRooted) {
       autoUnpin.Clear();
     }
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
@@ -1936,17 +1929,17 @@ XMLHttpRequest::Open(const nsACString& a
   mProxy->mOuterEventStreamId++;
 
   RefPtr<OpenRunnable> runnable =
     new OpenRunnable(mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
                      mBackgroundRequest, mWithCredentials,
                      mTimeout);
 
   ++mProxy->mOpenCount;
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     if (!--mProxy->mOpenCount) {
       ReleaseProxy();
     }
 
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
@@ -1973,17 +1966,17 @@ XMLHttpRequest::SetRequestHeader(const n
 
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   RefPtr<SetRequestHeaderRunnable> runnable =
     new SetRequestHeaderRunnable(mWorkerPrivate, mProxy, aHeader, aValue);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 }
 
 void
 XMLHttpRequest::SetTimeout(uint32_t aTimeout, ErrorResult& aRv)
 {
@@ -1999,17 +1992,17 @@ XMLHttpRequest::SetTimeout(uint32_t aTim
   if (!mProxy) {
     // Open may not have been called yet, in which case we'll handle the
     // timeout in OpenRunnable.
     return;
   }
 
   RefPtr<SetTimeoutRunnable> runnable =
     new SetTimeoutRunnable(mWorkerPrivate, mProxy, aTimeout);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 }
 
 void
 XMLHttpRequest::SetWithCredentials(bool aWithCredentials, ErrorResult& aRv)
 {
@@ -2025,17 +2018,17 @@ XMLHttpRequest::SetWithCredentials(bool 
   if (!mProxy) {
     // Open may not have been called yet, in which case we'll handle the
     // credentials in OpenRunnable.
     return;
   }
 
   RefPtr<SetWithCredentialsRunnable> runnable =
     new SetWithCredentialsRunnable(mWorkerPrivate, mProxy, aWithCredentials);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 }
 
 void
 XMLHttpRequest::SetMozBackgroundRequest(bool aBackgroundRequest,
                                         ErrorResult& aRv)
@@ -2053,17 +2046,17 @@ XMLHttpRequest::SetMozBackgroundRequest(
     // Open may not have been called yet, in which case we'll handle the
     // background request in OpenRunnable.
     return;
   }
 
   RefPtr<SetBackgroundRequestRunnable> runnable =
     new SetBackgroundRequestRunnable(mWorkerPrivate, mProxy,
                                      aBackgroundRequest);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 }
 
 XMLHttpRequestUpload*
 XMLHttpRequest::GetUpload(ErrorResult& aRv)
 {
@@ -2285,17 +2278,17 @@ XMLHttpRequest::Abort(ErrorResult& aRv)
   MaybeDispatchPrematureAbortEvents(aRv);
   if (aRv.Failed()) {
     return;
   }
 
   mProxy->mOuterEventStreamId++;
 
   RefPtr<AbortRunnable> runnable = new AbortRunnable(mWorkerPrivate, mProxy);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 }
 
 void
 XMLHttpRequest::GetResponseHeader(const nsACString& aHeader,
                                   nsACString& aResponseHeader, ErrorResult& aRv)
@@ -2311,17 +2304,17 @@ XMLHttpRequest::GetResponseHeader(const 
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   nsCString responseHeader;
   RefPtr<GetResponseHeaderRunnable> runnable =
     new GetResponseHeaderRunnable(mWorkerPrivate, mProxy, aHeader,
                                   responseHeader);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
   aResponseHeader = responseHeader;
 }
 
 void
 XMLHttpRequest::GetAllResponseHeaders(nsACString& aResponseHeaders,
@@ -2337,17 +2330,17 @@ XMLHttpRequest::GetAllResponseHeaders(ns
   if (!mProxy) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   nsCString responseHeaders;
   RefPtr<GetAllResponseHeadersRunnable> runnable =
     new GetAllResponseHeadersRunnable(mWorkerPrivate, mProxy, responseHeaders);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   aResponseHeaders = responseHeaders;
 }
 
 void
@@ -2369,17 +2362,17 @@ XMLHttpRequest::OverrideMimeType(const n
                   (mProxy->mSeenLoadStart ||
                    mStateData.mReadyState > nsIXMLHttpRequest::OPENED))) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   RefPtr<OverrideMimeTypeRunnable> runnable =
     new OverrideMimeTypeRunnable(mWorkerPrivate, mProxy, aMimeType);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 }
 
 void
 XMLHttpRequest::SetResponseType(XMLHttpRequestResponseType aResponseType,
                                 ErrorResult& aRv)
@@ -2404,17 +2397,17 @@ XMLHttpRequest::SetResponseType(XMLHttpR
     return;
   }
 
   nsString responseType;
   ConvertResponseTypeToString(aResponseType, responseType);
 
   RefPtr<SetResponseTypeRunnable> runnable =
     new SetResponseTypeRunnable(mWorkerPrivate, mProxy, responseType);
-  if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
+  if (!runnable->Dispatch()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   nsString acceptedResponseTypeString;
   runnable->GetResponseType(acceptedResponseTypeString);
 
   mResponseType = ConvertStringToResponseType(acceptedResponseTypeString);