Backed out changeset 4d07001e9afc (bug 673569) because it depends on bug 682048 which is being backed out.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 03 Dec 2013 22:43:52 -0500
changeset 173375 771052f15a6cbe186bf17055e8dcd08f20002964
parent 173374 ec574743984dc1d214c66a8e7f82d34a91bb418d
child 173376 874788e2239c90171780b64c577380d3a63996ed
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs673569, 682048
milestone28.0a1
backs out4d07001e9afc078a8d6b337ac746dce99b3de2a7
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
Backed out changeset 4d07001e9afc (bug 673569) because it depends on bug 682048 which is being backed out.
browser/modules/BrowserNewTabPreloader.jsm
content/base/public/nsIMessageManager.idl
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsFrameMessageManager.h
content/base/src/nsInProcessTabChildGlobal.cpp
content/base/src/nsInProcessTabChildGlobal.h
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
--- a/browser/modules/BrowserNewTabPreloader.jsm
+++ b/browser/modules/BrowserNewTabPreloader.jsm
@@ -327,17 +327,17 @@ HiddenBrowser.prototype = {
     }
 
     // Swap docShells.
     tabbrowser.swapNewTabWithBrowser(aTab, this._browser);
 
     // Load all default frame scripts attached to the target window.
     let mm = aTab.linkedBrowser.messageManager;
     let scripts = win.messageManager.getDelayedFrameScripts();
-    Array.forEach(scripts, ([script, runGlobal]) => mm.loadFrameScript(script, true, runGlobal));
+    Array.forEach(scripts, script => mm.loadFrameScript(script, true));
 
     // Remove the browser, it will be recreated by a timer.
     this._removeBrowser();
 
     // Start a timer that will kick off preloading the next newtab page.
     this._timer = createTimer(this, PRELOADER_INTERVAL_MS);
 
     // Signal that we swapped docShells.
--- a/content/base/public/nsIMessageManager.idl
+++ b/content/base/public/nsIMessageManager.idl
@@ -354,41 +354,38 @@ interface nsIContentFrameMessageManager 
 };
 
 [uuid(a2325927-9c0c-437d-9215-749c79235031)]
 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
 {
   [notxpcom] nsIContent getOwnerContent();
 };
 
-[scriptable, builtinclass, uuid(6fb78110-45ae-11e3-8f96-0800200c9a66)]
+[scriptable, builtinclass, uuid(ecebfb8c-ff51-11e2-9d65-7af553959281)]
 interface nsIFrameScriptLoader : nsISupports
 {
   /**
    * Load a script in the (remote) frame. aURL must be the absolute URL.
    * data: URLs are also supported. For example data:,dump("foo\n");
    * If aAllowDelayedLoad is true, script will be loaded when the
    * remote frame becomes available. Otherwise the script will be loaded
    * only if the frame is already available.
    */
-  void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad,
-                       [optional] in boolean aRunInGlobalScope);
+  void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad);
 
   /**
    * Removes aURL from the list of scripts which support delayed load.
    */
   void removeDelayedFrameScript(in AString aURL);
 
   /**
-   * Returns all delayed scripts that will be loaded once a (remote)
-   * frame becomes available. The return value is a list of pairs
-   * [<URL>, <WasLoadedInGlobalScope>].
+   * Returns a list of all delayed scripts that will be loaded once
+   * a (remote) frame becomes available.
    */
-  [implicit_jscontext]
-  jsval getDelayedFrameScripts();
+  nsIDOMDOMStringList getDelayedFrameScripts();
 };
 
 [scriptable, builtinclass, uuid(b37821ff-df79-44d4-821c-6d6ec4dfe1e9)]
 interface nsIProcessChecker : nsISupports
 {
 
   /**
    * Return true iff the "remote" process has |aPermission|.  This is
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -1682,18 +1682,17 @@ nsFrameLoader::MaybeCreateDocShell()
     if (os) {
       os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
                           "in-process-browser-or-app-frame-shown", nullptr);
     }
 
     if (mMessageManager) {
       mMessageManager->LoadFrameScript(
         NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js"),
-        /* allowDelayedLoad = */ true,
-        /* aRunInGlobalScope */ true);
+        /* allowDelayedLoad = */ true);
     }
   }
 
   return NS_OK;
 }
 
 void
 nsFrameLoader::GetURL(nsString& aURI)
@@ -2184,26 +2183,26 @@ nsFrameLoader::CreateStaticClone(nsIFram
   nsCOMPtr<nsIDocument> clonedDoc = doc->CreateStaticClone(dest->mDocShell);
   nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
 
   viewer->SetDOMDocument(clonedDOMDoc);
   return NS_OK;
 }
 
 bool
-nsFrameLoader::DoLoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope)
+nsFrameLoader::DoLoadFrameScript(const nsAString& aURL)
 {
   mozilla::dom::PBrowserParent* tabParent = GetRemoteBrowser();
   if (tabParent) {
-    return tabParent->SendLoadRemoteScript(nsString(aURL), aRunInGlobalScope);
+    return tabParent->SendLoadRemoteScript(nsString(aURL));
   }
   nsRefPtr<nsInProcessTabChildGlobal> tabChild =
     static_cast<nsInProcessTabChildGlobal*>(GetTabChildGlobalAsEventTarget());
   if (tabChild) {
-    tabChild->LoadFrameScript(aURL, aRunInGlobalScope);
+    tabChild->LoadFrameScript(aURL);
   }
   return true;
 }
 
 class nsAsyncMessageToChild : public nsRunnable
 {
 public:
   nsAsyncMessageToChild(JSContext* aCx,
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -180,18 +180,17 @@ public:
   void Finalize();
   nsIDocShell* GetExistingDocShell() { return mDocShell; }
   mozilla::dom::EventTarget* GetTabChildGlobalAsEventTarget();
   nsresult CreateStaticClone(nsIFrameLoader* aDest);
 
   /**
    * MessageManagerCallback methods that we override.
    */
-  virtual bool DoLoadFrameScript(const nsAString& aURL,
-                                 bool aRunInGlobalScope) MOZ_OVERRIDE;
+  virtual bool DoLoadFrameScript(const nsAString& aURL) MOZ_OVERRIDE;
   virtual bool DoSendAsyncMessage(JSContext* aCx,
                                   const nsAString& aMessage,
                                   const mozilla::dom::StructuredCloneData& aData,
                                   JS::Handle<JSObject *> aCpows,
                                   nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
   virtual bool CheckPermission(const nsAString& aPermission) MOZ_OVERRIDE;
   virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE;
   virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE;
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -389,98 +389,73 @@ nsFrameMessageManager::RemoveWeakMessage
 
   return NS_OK;
 }
 
 // nsIFrameScriptLoader
 
 NS_IMETHODIMP
 nsFrameMessageManager::LoadFrameScript(const nsAString& aURL,
-                                       bool aAllowDelayedLoad,
-                                       bool aRunInGlobalScope)
+                                       bool aAllowDelayedLoad)
 {
   if (aAllowDelayedLoad) {
     if (IsGlobal() || IsWindowLevel()) {
       // Cache for future windows or frames
       mPendingScripts.AppendElement(aURL);
-      mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope);
     } else if (!mCallback) {
       // We're frame message manager, which isn't connected yet.
       mPendingScripts.AppendElement(aURL);
-      mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope);
       return NS_OK;
     }
   }
 
   if (mCallback) {
 #ifdef DEBUG_smaug
     printf("Will load %s \n", NS_ConvertUTF16toUTF8(aURL).get());
 #endif
-    NS_ENSURE_TRUE(mCallback->DoLoadFrameScript(aURL, aRunInGlobalScope),
-                   NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(mCallback->DoLoadFrameScript(aURL), NS_ERROR_FAILURE);
   }
 
   for (int32_t i = 0; i < mChildManagers.Count(); ++i) {
     nsRefPtr<nsFrameMessageManager> mm =
       static_cast<nsFrameMessageManager*>(mChildManagers[i]);
     if (mm) {
       // Use false here, so that child managers don't cache the script, which
       // is already cached in the parent.
-      mm->LoadFrameScript(aURL, false, aRunInGlobalScope);
+      mm->LoadFrameScript(aURL, false);
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::RemoveDelayedFrameScript(const nsAString& aURL)
 {
-  for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
-    if (mPendingScripts[i] == aURL) {
-      mPendingScripts.RemoveElementAt(i);
-      mPendingScriptsGlobalStates.RemoveElementAt(i);
-      break;
-    }
-  }
+  mPendingScripts.RemoveElement(aURL);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::Value* aList)
+nsFrameMessageManager::GetDelayedFrameScripts(nsIDOMDOMStringList** aList)
 {
   // Frame message managers may return an incomplete list because scripts
   // that were loaded after it was connected are not added to the list.
   if (!IsGlobal() && !IsWindowLevel()) {
     NS_WARNING("Cannot retrieve list of pending frame scripts for frame"
                "message managers as it may be incomplete");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, mPendingScripts.Length(), nullptr));
-  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
-
-  JS::Rooted<JSString*> url(aCx);
-  JS::Rooted<JSObject*> pair(aCx);
-  JS::Rooted<JS::Value> pairVal(aCx);
-  for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
-    url = JS_NewUCStringCopyN(aCx, mPendingScripts[i].get(), mPendingScripts[i].Length());
-    NS_ENSURE_TRUE(url, NS_ERROR_OUT_OF_MEMORY);
+  nsRefPtr<nsDOMStringList> scripts = new nsDOMStringList();
 
-    JS::Value pairElts[] = { JS::StringValue(url),
-                             JS::BooleanValue(mPendingScriptsGlobalStates[i]) };
-
-    pair = JS_NewArrayObject(aCx, 2, pairElts);
-    NS_ENSURE_TRUE(pair, NS_ERROR_OUT_OF_MEMORY);
-
-    pairVal = JS::ObjectValue(*pair);
-    NS_ENSURE_TRUE(JS_SetElement(aCx, array, i, &pairVal),
-                   NS_ERROR_OUT_OF_MEMORY);
+  for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
+    scripts->Add(mPendingScripts[i]);
   }
 
-  *aList = JS::ObjectValue(*array);
+  scripts.forget(aList);
 
   return NS_OK;
 }
 
 static bool
 JSONCreator(const jschar* aBuf, uint32_t aLen, void* aData)
 {
   nsAString* result = static_cast<nsAString*>(aData);
@@ -1069,23 +1044,21 @@ nsFrameMessageManager::AddChildManager(n
     nsRefPtr<nsFrameMessageManager> kungfuDeathGrip = this;
     nsRefPtr<nsFrameMessageManager> kungfuDeathGrip2 = aManager;
     // We have parent manager if we're a window message manager.
     // In that case we want to load the pending scripts from global
     // message manager.
     if (mParentManager) {
       nsRefPtr<nsFrameMessageManager> globalMM = mParentManager;
       for (uint32_t i = 0; i < globalMM->mPendingScripts.Length(); ++i) {
-        aManager->LoadFrameScript(globalMM->mPendingScripts[i], false,
-                                  globalMM->mPendingScriptsGlobalStates[i]);
+        aManager->LoadFrameScript(globalMM->mPendingScripts[i], false);
       }
     }
     for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
-      aManager->LoadFrameScript(mPendingScripts[i], false,
-                                mPendingScriptsGlobalStates[i]);
+      aManager->LoadFrameScript(mPendingScripts[i], false);
     }
   }
 }
 
 void
 nsFrameMessageManager::SetCallback(MessageManagerCallback* aCallback, bool aLoadScripts)
 {
   NS_ASSERTION(!mIsBroadcaster || !mCallback,
@@ -1096,17 +1069,17 @@ nsFrameMessageManager::SetCallback(Messa
       mOwnedCallback = aCallback;
     }
     // First load global scripts by adding this to parent manager.
     if (mParentManager) {
       mParentManager->AddChildManager(this, aLoadScripts);
     }
     if (aLoadScripts) {
       for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
-        LoadFrameScript(mPendingScripts[i], false, mPendingScriptsGlobalStates[i]);
+        LoadFrameScript(mPendingScripts[i], false);
       }
     }
   }
 }
 
 void
 nsFrameMessageManager::RemoveFromParent()
 {
@@ -1326,46 +1299,41 @@ NS_NewGlobalMessageManager(nsIMessageBro
                  NS_ERROR_NOT_AVAILABLE);
   nsFrameMessageManager* mm = new nsFrameMessageManager(nullptr,
                                                         nullptr,
                                                         MM_CHROME | MM_GLOBAL | MM_BROADCASTER);
   RegisterStrongMemoryReporter(new MessageManagerReporter());
   return CallQueryInterface(mm, aResult);
 }
 
-nsDataHashtable<nsStringHashKey, nsFrameScriptObjectExecutorHolder*>*
+nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>*
   nsFrameScriptExecutor::sCachedScripts = nullptr;
 nsScriptCacheCleaner* nsFrameScriptExecutor::sScriptCacheCleaner = nullptr;
 
 void
 nsFrameScriptExecutor::DidCreateGlobal()
 {
   NS_ASSERTION(mGlobal, "Should have mGlobal!");
   if (!sCachedScripts) {
     sCachedScripts =
-      new nsDataHashtable<nsStringHashKey, nsFrameScriptObjectExecutorHolder*>;
+      new nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>;
 
     nsRefPtr<nsScriptCacheCleaner> scriptCacheCleaner =
       new nsScriptCacheCleaner();
     scriptCacheCleaner.forget(&sScriptCacheCleaner);
   }
 }
 
 static PLDHashOperator
 CachedScriptUnrooter(const nsAString& aKey,
-                     nsFrameScriptObjectExecutorHolder*& aData,
-                     void* aUserArg)
+                       nsFrameJSScriptExecutorHolder*& aData,
+                       void* aUserArg)
 {
   JSContext* cx = static_cast<JSContext*>(aUserArg);
-  if (aData->mScript) {
-    JS_RemoveScriptRoot(cx, &aData->mScript);
-  }
-  if (aData->mFunction) {
-    JS_RemoveObjectRoot(cx, &aData->mFunction);
-  }
+  JS_RemoveScriptRoot(cx, &(aData->mScript));
   delete aData;
   return PL_DHASH_REMOVE;
 }
 
 // static
 void
 nsFrameScriptExecutor::Shutdown()
 {
@@ -1378,63 +1346,41 @@ nsFrameScriptExecutor::Shutdown()
     sCachedScripts = nullptr;
 
     nsRefPtr<nsScriptCacheCleaner> scriptCacheCleaner;
     scriptCacheCleaner.swap(sScriptCacheCleaner);
   }
 }
 
 void
-nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL,
-                                               bool aRunInGlobalScope)
+nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
 {
   if (!mGlobal || !sCachedScripts) {
     return;
   }
 
-  AutoSafeJSContext cx;
-  JS::Rooted<JSScript*> script(cx);
-  JS::Rooted<JSObject*> funobj(cx);
-
-  nsFrameScriptObjectExecutorHolder* holder = sCachedScripts->Get(aURL);
-  if (holder && holder->WillRunInGlobalScope() == aRunInGlobalScope) {
-    script = holder->mScript;
-    funobj = holder->mFunction;
-  } else {
-    // Don't put anything in the cache if we already have an entry
-    // with a different WillRunInGlobalScope() value.
-    bool shouldCache = !holder;
-    TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope,
-                                 shouldCache, &script, &funobj);
+  nsFrameJSScriptExecutorHolder* holder = sCachedScripts->Get(aURL);
+  if (!holder) {
+    TryCacheLoadAndCompileScript(aURL, EXECUTE_IF_CANT_CACHE);
+    holder = sCachedScripts->Get(aURL);
   }
 
-  JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
-  if (global) {
-    JSAutoCompartment ac(cx, global);
-    if (funobj) {
-      JS::Rooted<JSObject*> method(cx, JS_CloneFunctionObject(cx, funobj, global));
-      if (!method) {
-        return;
-      }
-      JS::Rooted<JS::Value> rval(cx);
-      JS::Rooted<JS::Value> methodVal(cx, JS::ObjectValue(*method));
-      (void) JS_CallFunctionValue(cx, global, methodVal,
-                                  0, nullptr, rval.address());
-    } else if (script) {
-      (void) JS_ExecuteScript(cx, global, script, nullptr);
+  if (holder) {
+    AutoSafeJSContext cx;
+    JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
+    if (global) {
+      JSAutoCompartment ac(cx, global);
+      (void) JS_ExecuteScript(cx, global, holder->mScript, nullptr);
     }
   }
 }
 
 void
 nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
-                                                    bool aRunInGlobalScope,
-                                                    bool aShouldCache,
-                                                    JS::MutableHandle<JSScript*> aScriptp,
-                                                    JS::MutableHandle<JSObject*> aFunp)
+                                                    CacheFailedBehavior aBehavior)
 {
   nsCString url = NS_ConvertUTF16toUTF8(aURL);
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
   if (NS_FAILED(rv)) {
     return;
   }
 
@@ -1471,75 +1417,42 @@ nsFrameScriptExecutor::TryCacheLoadAndCo
   }
 
   if (!dataString.IsEmpty()) {
     AutoSafeJSContext cx;
     JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
     if (global) {
       JSAutoCompartment ac(cx, global);
       JS::CompileOptions options(cx);
-      options.setFileAndLine(url.get(), 1)
+      options.setNoScriptRval(true)
+             .setFileAndLine(url.get(), 1)
              .setPrincipals(nsJSPrincipals::get(mPrincipal));
-      JS::Rooted<JSScript*> script(cx);
-      JS::Rooted<JSObject*> funobj(cx);
-      if (aRunInGlobalScope) {
-        options.setNoScriptRval(true);
-        script = JS::Compile(cx, JS::NullPtr(), options, dataString.get(),
-                             dataString.Length());
-      } else {
-        JS::Rooted<JSFunction *> fun(cx);
-        fun = JS::CompileFunction(cx, JS::NullPtr(), options,
-                                  nullptr, 0, nullptr, /* name, nargs, args */
-                                  dataString.get(),
-                                  dataString.Length());
-        if (!fun) {
-          return;
-        }
-        funobj = JS_GetFunctionObject(fun);
-      }
+      JS::Rooted<JSScript*> script(cx,
+        JS::Compile(cx, JS::NullPtr(), options, dataString.get(),
+                    dataString.Length()));
 
-      if (!script && !funobj) {
-        return;
-      }
-
-      aScriptp.set(script);
-      aFunp.set(funobj);
-
-      nsAutoCString scheme;
-      uri->GetScheme(scheme);
-      // We don't cache data: scripts!
-      if (aShouldCache && !scheme.EqualsLiteral("data")) {
-        nsFrameScriptObjectExecutorHolder* holder;
-
-        // Root the object also for caching.
-        if (script) {
-          holder = new nsFrameScriptObjectExecutorHolder(script);
-          JS_AddNamedScriptRoot(cx, &holder->mScript,
+      if (script) {
+        nsAutoCString scheme;
+        uri->GetScheme(scheme);
+        // We don't cache data: scripts!
+        if (!scheme.EqualsLiteral("data")) {
+          nsFrameJSScriptExecutorHolder* holder =
+            new nsFrameJSScriptExecutorHolder(script);
+          // Root the object also for caching.
+          JS_AddNamedScriptRoot(cx, &(holder->mScript),
                                 "Cached message manager script");
-        } else {
-          holder = new nsFrameScriptObjectExecutorHolder(funobj);
-          JS_AddNamedObjectRoot(cx, &holder->mFunction,
-                                "Cached message manager function");
+          sCachedScripts->Put(aURL, holder);
+        } else if (aBehavior == EXECUTE_IF_CANT_CACHE) {
+          (void) JS_ExecuteScript(cx, global, script, nullptr);
         }
-        sCachedScripts->Put(aURL, holder);
       }
     }
   }
 }
 
-void
-nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
-                                                    bool aRunInGlobalScope)
-{
-  AutoSafeJSContext cx;
-  JS::Rooted<JSScript*> script(cx);
-  JS::Rooted<JSObject*> funobj(cx);
-  TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope, true, &script, &funobj);
-}
-
 bool
 nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope,
                                                   const nsACString& aID)
 {
 
   nsCOMPtr<nsIJSRuntimeService> runtimeSvc =
     do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
   NS_ENSURE_TRUE(runtimeSvc, false);
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -48,17 +48,17 @@ enum MessageManagerFlags {
   MM_OWNSCALLBACK = 16
 };
 
 class MessageManagerCallback
 {
 public:
   virtual ~MessageManagerCallback() {}
 
-  virtual bool DoLoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope)
+  virtual bool DoLoadFrameScript(const nsAString& aURL)
   {
     return true;
   }
 
   virtual bool DoSendBlockingMessage(JSContext* aCx,
                                      const nsAString& aMessage,
                                      const StructuredCloneData& aData,
                                      JS::Handle<JSObject*> aCpows,
@@ -291,17 +291,16 @@ protected:
   bool mIsBroadcaster; // true if the message manager is a broadcaster
   bool mOwnsCallback;
   bool mHandlingMessage;
   bool mDisconnected;
   mozilla::dom::ipc::MessageManagerCallback* mCallback;
   nsAutoPtr<mozilla::dom::ipc::MessageManagerCallback> mOwnedCallback;
   nsFrameMessageManager* mParentManager;
   nsTArray<nsString> mPendingScripts;
-  nsTArray<bool> mPendingScriptsGlobalStates;
 public:
   static nsFrameMessageManager* sParentProcessManager;
   static nsFrameMessageManager* sChildProcessManager;
   static nsFrameMessageManager* sSameProcessParentManager;
   static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages;
 private:
   enum ProcessCheckerType {
     PROCESS_CHECKER_PERMISSION,
@@ -310,63 +309,49 @@ private:
   };
   nsresult AssertProcessInternal(ProcessCheckerType aType,
                                  const nsAString& aCapability,
                                  bool* aValid);
 };
 
 class nsScriptCacheCleaner;
 
-struct nsFrameScriptObjectExecutorHolder
+struct nsFrameJSScriptExecutorHolder
 {
-  nsFrameScriptObjectExecutorHolder(JSScript* aScript) : mScript(aScript), mFunction(nullptr)
-  { MOZ_COUNT_CTOR(nsFrameScriptObjectExecutorHolder); }
-  nsFrameScriptObjectExecutorHolder(JSObject* aFunction) : mScript(nullptr), mFunction(aFunction)
-  { MOZ_COUNT_CTOR(nsFrameScriptObjectExecutorHolder); }
-  ~nsFrameScriptObjectExecutorHolder()
-  { MOZ_COUNT_DTOR(nsFrameScriptObjectExecutorHolder); }
-
-  bool WillRunInGlobalScope() { return mScript; }
-
-  // We use JS_AddNamed{Script,Object}Root to root these fields explicitly, so
-  // no need for Heap<T>.
+  nsFrameJSScriptExecutorHolder(JSScript* aScript) : mScript(aScript)
+  { MOZ_COUNT_CTOR(nsFrameJSScriptExecutorHolder); }
+  ~nsFrameJSScriptExecutorHolder()
+  { MOZ_COUNT_DTOR(nsFrameJSScriptExecutorHolder); }
   JSScript* mScript;
-  JSObject* mFunction;
 };
 
-class nsFrameScriptObjectExecutorStackHolder;
-
 class nsFrameScriptExecutor
 {
 public:
   static void Shutdown();
   already_AddRefed<nsIXPConnectJSObjectHolder> GetGlobal()
   {
     nsCOMPtr<nsIXPConnectJSObjectHolder> ref = mGlobal;
     return ref.forget();
   }
 protected:
   friend class nsFrameScriptCx;
   nsFrameScriptExecutor()
   { MOZ_COUNT_CTOR(nsFrameScriptExecutor); }
   ~nsFrameScriptExecutor()
   { MOZ_COUNT_DTOR(nsFrameScriptExecutor); }
   void DidCreateGlobal();
-  void LoadFrameScriptInternal(const nsAString& aURL, bool aRunInGlobalScope);
+  void LoadFrameScriptInternal(const nsAString& aURL);
+  enum CacheFailedBehavior { EXECUTE_IF_CANT_CACHE, DONT_EXECUTE };
   void TryCacheLoadAndCompileScript(const nsAString& aURL,
-                                    bool aRunInGlobalScope,
-                                    bool aShouldCache,
-                                    JS::MutableHandle<JSScript*> aScriptp,
-                                    JS::MutableHandle<JSObject*> aFunp);
-  void TryCacheLoadAndCompileScript(const nsAString& aURL,
-                                    bool aRunInGlobalScope);
+                                    CacheFailedBehavior aBehavior = DONT_EXECUTE);
   bool InitTabChildGlobalInternal(nsISupports* aScope, const nsACString& aID);
   nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
   nsCOMPtr<nsIPrincipal> mPrincipal;
-  static nsDataHashtable<nsStringHashKey, nsFrameScriptObjectExecutorHolder*>* sCachedScripts;
+  static nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>* sCachedScripts;
   static nsScriptCacheCleaner* sScriptCacheCleaner;
 };
 
 class nsScriptCacheCleaner MOZ_FINAL : public nsIObserver
 {
   NS_DECL_ISUPPORTS
 
   nsScriptCacheCleaner()
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
 /* vim: set sw=4 ts=8 et tw=80 : */
 /* 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 "nsInProcessTabChildGlobal.h"
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
@@ -330,42 +330,40 @@ nsInProcessTabChildGlobal::InitTabChildG
   nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
   NS_ENSURE_STATE(InitTabChildGlobalInternal(scopeSupports, id));
   return NS_OK;
 }
 
 class nsAsyncScriptLoad : public nsRunnable
 {
 public:
-    nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild, const nsAString& aURL,
-                      bool aRunInGlobalScope)
-      : mTabChild(aTabChild), mURL(aURL), mRunInGlobalScope(aRunInGlobalScope) {}
+  nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild, const nsAString& aURL)
+  : mTabChild(aTabChild), mURL(aURL) {}
 
   NS_IMETHOD Run()
   {
-    mTabChild->LoadFrameScript(mURL, mRunInGlobalScope);
+    mTabChild->LoadFrameScript(mURL);
     return NS_OK;
   }
   nsRefPtr<nsInProcessTabChildGlobal> mTabChild;
   nsString mURL;
-  bool mRunInGlobalScope;
 };
 
 void
-nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope)
+nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL)
 {
   if (!nsContentUtils::IsSafeToRunScript()) {
-    nsContentUtils::AddScriptRunner(new nsAsyncScriptLoad(this, aURL, aRunInGlobalScope));
+    nsContentUtils::AddScriptRunner(new nsAsyncScriptLoad(this, aURL));
     return;
   }
   if (!mInitialized) {
     mInitialized = true;
     Init();
   }
   bool tmp = mLoadingScript;
   mLoadingScript = true;
-  LoadFrameScriptInternal(aURL, aRunInGlobalScope);
+  LoadFrameScriptInternal(aURL);
   mLoadingScript = tmp;
   if (!mLoadingScript && mDelayedDisconnect) {
     mDelayedDisconnect = false;
     Disconnect();
   }
 }
--- a/content/base/src/nsInProcessTabChildGlobal.h
+++ b/content/base/src/nsInProcessTabChildGlobal.h
@@ -114,17 +114,17 @@ public:
                                                     aUseCapture,
                                                     aWantsUntrusted,
                                                     optional_argc);
   }
   using nsDOMEventTargetHelper::AddEventListener;
 
   virtual JSContext* GetJSContextForEventHandlers() MOZ_OVERRIDE { return nsContentUtils::GetSafeJSContext(); }
   virtual nsIPrincipal* GetPrincipal() MOZ_OVERRIDE { return mPrincipal; }
-  void LoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope);
+  void LoadFrameScript(const nsAString& aURL);
   void Disconnect();
   void SendMessageToParent(const nsString& aMessage, bool aSync,
                            const nsString& aJSON,
                            nsTArray<nsString>* aJSONRetVal);
   nsFrameMessageManager* GetInnerManager()
   {
     return static_cast<nsFrameMessageManager*>(mMessageManager.get());
   }
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -387,17 +387,17 @@ child:
 
     SelectionEvent(WidgetSelectionEvent event);
 
     /**
      * Activate event forwarding from client to parent.
      */
     ActivateFrameEvent(nsString aType, bool capture);
 
-    LoadRemoteScript(nsString aURL, bool aRunInGlobalScope);
+    LoadRemoteScript(nsString aURL);
 
     /**
      * Create a asynchronous request to render whatever document is
      * loaded in the child when this message arrives.  When the
      * request finishes, PDocumentRenderer:__delete__ is sent back to
      * this side to notify completion.
      *
      * |documentRect| is the area of the remote document to draw,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -217,21 +217,20 @@ TabChild::PreloadSlowThings()
 
     nsRefPtr<TabChild> tab(new TabChild(ContentChild::GetSingleton(),
                                         TabContext(), /* chromeFlags */ 0));
     if (!NS_SUCCEEDED(tab->Init()) ||
         !tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
         return;
     }
     // Just load and compile these scripts, but don't run them.
-    tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
+    tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT);
     // Load, compile, and run these scripts.
     tab->RecvLoadRemoteScript(
-        NS_LITERAL_STRING("chrome://global/content/preload.js"),
-        true);
+        NS_LITERAL_STRING("chrome://global/content/preload.js"));
 
     nsCOMPtr<nsIDocShell> docShell = do_GetInterface(tab->mWebNav);
     if (nsIPresShell* presShell = docShell->GetPresShell()) {
         // Initialize and do an initial reflow of the about:blank
         // PresShell to let it preload some things for us.
         presShell->Initialize(0, 0);
         nsIDocument* doc = presShell->GetDocument();
         doc->FlushPendingNotifications(Flush_Layout);
@@ -2054,24 +2053,24 @@ bool
 TabChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor)
 {
   OfflineCacheUpdateChild* offlineCacheUpdate = static_cast<OfflineCacheUpdateChild*>(actor);
   delete offlineCacheUpdate;
   return true;
 }
 
 bool
-TabChild::RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope)
+TabChild::RecvLoadRemoteScript(const nsString& aURL)
 {
   if (!mGlobal && !InitTabChildGlobal())
     // This can happen if we're half-destroyed.  It's not a fatal
     // error.
     return true;
 
-  LoadFrameScriptInternal(aURL, aRunInGlobalScope);
+  LoadFrameScriptInternal(aURL);
   return true;
 }
 
 bool
 TabChild::RecvAsyncMessage(const nsString& aMessage,
                            const ClonedMessageData& aData,
                            const InfallibleTArray<CpowEntry>& aCpows,
                            const IPC::Principal& aPrincipal)
@@ -2192,17 +2191,17 @@ TabChild::InitTabChildGlobal(FrameScript
     chromeHandler->AddEventListener(NS_LITERAL_STRING("scroll"), this, false);
   }
 
   if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) {
     mTriedBrowserInit = true;
     // Initialize the child side of the browser element machinery,
     // if appropriate.
     if (IsBrowserOrApp()) {
-      RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
+      RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT);
     }
   }
 
   return true;
 }
 
 bool
 TabChild::InitRenderingState()
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -237,17 +237,17 @@ public:
                               const int32_t&  aKeyCode,
                               const int32_t&  aCharCode,
                               const int32_t&  aModifiers,
                               const bool&     aPreventDefault);
     virtual bool RecvCompositionEvent(const mozilla::WidgetCompositionEvent& event);
     virtual bool RecvTextEvent(const mozilla::WidgetTextEvent& event);
     virtual bool RecvSelectionEvent(const mozilla::WidgetSelectionEvent& event);
     virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& capture);
-    virtual bool RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope);
+    virtual bool RecvLoadRemoteScript(const nsString& aURL);
     virtual bool RecvAsyncMessage(const nsString& aMessage,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
                                   const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
     virtual PDocumentRendererChild*
     AllocPDocumentRendererChild(const nsRect& documentRect, const gfxMatrix& transform,
                                 const nsString& bgcolor,