Bug 1398601 - Fix subscript loader when using JSM global sharing r=kmag
authorTed Campbell <tcampbell@mozilla.com>
Sun, 10 Sep 2017 14:23:32 -0400
changeset 430220 675444347ccd1f4ceeefc4203851e8d2d9a984fe
parent 430219 354b9d0b210193cffbc146b037c598bc31fa9401
child 430221 51d0521b16aa83197e4c032da894484b00cda7c1
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1398601
milestone57.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 1398601 - Fix subscript loader when using JSM global sharing r=kmag When using the subscript loader with JSM global sharing, it was possible that subscript would pollute the global of all JSMs in the sharing. MozReview-Commit-ID: 1ah5JUAZwBA
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -441,19 +441,24 @@ mozJSComponentLoader::LoadModule(FileLoc
 }
 
 void
 mozJSComponentLoader::FindTargetObject(JSContext* aCx,
                                        MutableHandleObject aTargetObject)
 {
     aTargetObject.set(js::GetJSMEnvironmentOfScriptedCaller(aCx));
 
-    // The above could fail if the scripted caller is not a
-    // component/JSM (it could be a DOM scope, for instance).
-    if (!aTargetObject) {
+    // The above could fail if the scripted caller is not a component/JSM (it
+    // could be a DOM scope, for instance).
+    //
+    // If the target object was not in the JSM shared global, return the global
+    // instead. This is needed when calling the subscript loader within a frame
+    // script, since it the FrameScript NSVO will have been found.
+    if (!aTargetObject ||
+        !IsLoaderGlobal(js::GetGlobalForObjectCrossCompartment(aTargetObject))) {
         aTargetObject.set(CurrentGlobalOrNull(aCx));
     }
 }
 
 // This requires that the keys be strings and the values be pointers.
 template <class Key, class Data, class UserData>
 static size_t
 SizeOfTableExcludingThis(const nsBaseHashtable<Key, Data, UserData>& aTable,
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -188,34 +188,50 @@ EvalScript(JSContext* cx,
            bool startupCache,
            bool preloadCache,
            MutableHandleScript script)
 {
     if (JS_IsGlobalObject(targetObj)) {
         if (!JS::CloneAndExecuteScript(cx, script, retval)) {
             return false;
         }
+    } else if (js::IsJSMEnvironment(targetObj)) {
+        if (!ExecuteInJSMEnvironment(cx, script, targetObj)) {
+            return false;
+        }
+        retval.setUndefined();
     } else {
         JS::AutoObjectVector envChain(cx);
         if (!envChain.append(targetObj)) {
             return false;
         }
-        if (loadScope != targetObj &&
-            loadScope &&
-            !JS_IsGlobalObject(loadScope))
-        {
-            MOZ_DIAGNOSTIC_ASSERT(js::GetObjectCompartment(loadScope) ==
-                                  js::GetObjectCompartment(targetObj));
-
-            if (!envChain.append(loadScope)) {
+        if (!loadScope) {
+            // A null loadScope means we are cross-compartment. In this case, we
+            // should check the target isn't in the JSM loader shared-global or
+            // we will contaiminate all JSMs in the compartment.
+            //
+            // NOTE: If loadScope is already a shared-global JSM, we can't
+            // determine which JSM the target belongs to and have to assume it
+            // is in our JSM.
+            JSObject* targetGlobal = js::GetGlobalForObjectCrossCompartment(targetObj);
+            MOZ_DIAGNOSTIC_ASSERT(!mozJSComponentLoader::Get()->IsLoaderGlobal(targetGlobal),
+                                  "Don't load subscript into target in a shared-global JSM");
+            if (!JS::CloneAndExecuteScript(cx, envChain, script, retval)) {
                 return false;
             }
-        }
-        if (!JS::CloneAndExecuteScript(cx, envChain, script, retval)) {
-            return false;
+        } else if (JS_IsGlobalObject(loadScope)) {
+            if (!JS::CloneAndExecuteScript(cx, envChain, script, retval)) {
+                return false;
+            }
+        } else {
+            MOZ_ASSERT(js::IsJSMEnvironment(loadScope));
+            if (!js::ExecuteInJSMEnvironment(cx, script, loadScope, envChain)) {
+                return false;
+            }
+            retval.setUndefined();
         }
     }
 
     JSAutoCompartment rac(cx, targetObj);
     if (!JS_WrapValue(cx, retval)) {
         return false;
     }