Bug 1050795 Part 1: Replace nsCxPusher in WorkerRunnable::Run. r=bholley
authorBob Owen <bobowencode@gmail.com>
Fri, 08 Aug 2014 16:06:33 +0100
changeset 198861 9ea1fc4f59e0a4a465c3f1623316ddfba0d8c607
parent 198860 f2a2559265feb50ea9b4e15489cfc205c220c5da
child 198862 17fd16e2f47be49c9acffa48037b614dd53d7252
push id47514
push userbobbyholley@gmail.com
push dateMon, 11 Aug 2014 16:29:24 +0000
treeherdermozilla-inbound@17fd16e2f47b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1050795
milestone34.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 1050795 Part 1: Replace nsCxPusher in WorkerRunnable::Run. r=bholley
dom/workers/WorkerRunnable.cpp
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -1,25 +1,29 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WorkerRunnable.h"
 
+#include "nsGlobalWindow.h"
 #include "nsIEventTarget.h"
+#include "nsIGlobalObject.h"
 #include "nsIRunnable.h"
 #include "nsThreadUtils.h"
 
 #include "mozilla/DebugOnly.h"
+#include "mozilla/dom/ScriptSettings.h"
 
 #include "js/RootingAPI.h"
 #include "js/Value.h"
 
 #include "WorkerPrivate.h"
+#include "WorkerScope.h"
 
 USING_WORKERS_NAMESPACE
 
 namespace {
 
 const nsIID kWorkerRunnableIID = {
   0x320cc0b5, 0xef12, 0x4084, { 0x88, 0x6e, 0xca, 0x6a, 0x81, 0xe4, 0x1d, 0x68 }
 };
@@ -253,19 +257,20 @@ WorkerRunnable::Run()
     mWorkerPrivate->AssertIsOnParentThread();
   }
 #endif
 
   if (IsCanceled() && !mCallingCancelWithinRun) {
     return NS_OK;
   }
 
-  JSContext* cx;
+  nsCOMPtr<nsIGlobalObject> globalObject;
+  bool isMainThread = !targetIsWorkerThread && !mWorkerPrivate->GetParent();
+  MOZ_ASSERT(isMainThread == NS_IsMainThread());
   nsRefPtr<WorkerPrivate> kungFuDeathGrip;
-  nsCxPusher pusher;
 
   if (targetIsWorkerThread) {
     if (mWorkerPrivate->AllPendingRunnablesShouldBeCanceled() &&
         !IsCanceled() &&
         !mCallingCancelWithinRun) {
 
       // Prevent recursion.
       mCallingCancelWithinRun = true;
@@ -275,54 +280,61 @@ WorkerRunnable::Run()
       MOZ_ASSERT(mCallingCancelWithinRun);
       mCallingCancelWithinRun = false;
 
       MOZ_ASSERT(IsCanceled(), "Subclass Cancel() didn't set IsCanceled()!");
 
       return NS_OK;
     }
 
-    cx = mWorkerPrivate->GetJSContext();
-    MOZ_ASSERT(cx);
+    globalObject = mWorkerPrivate->GlobalScope();
   }
   else {
-    cx = mWorkerPrivate->ParentJSContext();
-    MOZ_ASSERT(cx);
-
     kungFuDeathGrip = mWorkerPrivate;
-
-    if (!mWorkerPrivate->GetParent()) {
-      AssertIsOnMainThread();
-      pusher.Push(cx);
+    if (isMainThread) {
+      globalObject = static_cast<nsGlobalWindow*>(mWorkerPrivate->GetWindow());
+    } else {
+      globalObject = mWorkerPrivate->GetParent()->GlobalScope();
     }
   }
 
-  JSAutoRequest ar(cx);
-
-  JS::Rooted<JSObject*> targetCompartmentObject(cx);
-  if (targetIsWorkerThread) {
-    targetCompartmentObject = JS::CurrentGlobalOrNull(cx);
+  // We might run script as part of WorkerRun, so we need an AutoEntryScript.
+  // This is part of the HTML spec for workers at:
+  // http://www.whatwg.org/specs/web-apps/current-work/#run-a-worker
+  // If we don't have a globalObject we have to use an AutoJSAPI instead, but
+  // this is OK as we won't be running script in these circumstances.
+  // It's important that aes is declared after jsapi, because if WorkerRun
+  // creates a global then we construct aes before PostRun and we need them to
+  // be destroyed in the correct order.
+  mozilla::dom::AutoJSAPI jsapi;
+  Maybe<mozilla::dom::AutoEntryScript> aes;
+  JSContext* cx;
+  if (globalObject) {
+    aes.construct(globalObject, isMainThread, isMainThread ? nullptr :
+                                              GetCurrentThreadJSContext());
+    cx = aes.ref().cx();
   } else {
-    targetCompartmentObject = mWorkerPrivate->GetWrapper();
+    jsapi.Init();
+    cx = jsapi.cx();
   }
 
+  // If we're not on the worker thread we'll either be in our parent's
+  // compartment or the null compartment, so we need to enter our own.
   Maybe<JSAutoCompartment> ac;
-  if (targetCompartmentObject) {
-    ac.construct(cx, targetCompartmentObject);
+  if (!targetIsWorkerThread && mWorkerPrivate->GetWrapper()) {
+    ac.construct(cx, mWorkerPrivate->GetWrapper());
   }
 
   bool result = WorkerRun(cx, mWorkerPrivate);
 
   // In the case of CompileScriptRunnnable, WorkerRun above can cause us to
-  // lazily create a global, in which case we need to be in its compartment
-  // when calling PostRun() below. Maybe<> this time...
-  if (targetIsWorkerThread &&
-      ac.empty() &&
-      js::DefaultObjectForContextOrNull(cx)) {
-    ac.construct(cx, js::DefaultObjectForContextOrNull(cx));
+  // lazily create a global, so we construct aes here before calling PostRun.
+  if (targetIsWorkerThread && aes.empty() && mWorkerPrivate->GlobalScope()) {
+    aes.construct(mWorkerPrivate->GlobalScope(), false, GetCurrentThreadJSContext());
+    cx = aes.ref().cx();
   }
 
   PostRun(cx, mWorkerPrivate, result);
 
   return result ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP