diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 6b1cb307016a..81894e4fee91 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -446,9 +446,14 @@ mozJSComponentLoader::FindTargetObject(JSContext* aCx, { 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)); } } diff --git a/js/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/xpconnect/loader/mozJSSubScriptLoader.cpp index f925ec7c6cf2..aff43328ade3 100644 --- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp +++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp @@ -193,24 +193,40 @@ EvalScript(JSContext* cx, 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(); } }