Bug 1398601 - Fix subscript loader when using JSM global sharing
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
--- 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;
}