diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 6caea850dae7..477445bbe382 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -457,7 +457,7 @@ mozJSComponentLoader::FindTargetObject(JSContext* aCx, if (mReuseLoaderGlobal) { JSFunction *fun = js::GetOutermostEnclosingFunctionOfScriptedCaller(aCx); if (fun) { - JSObject *funParent = js::GetObjectParent(JS_GetFunctionObject(fun)); + JSObject *funParent = js::GetObjectEnvironmentObjectForFunction(fun); if (JS_GetClass(funParent) == &kFakeBackstagePassJSClass) targetObject = funParent; } @@ -783,9 +783,14 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo &aInfo, if (!mReuseLoaderGlobal) { Compile(cx, obj, options, buf, fileSize32, &script); } else { - CompileFunction(cx, obj, options, - nullptr, 0, nullptr, - buf, fileSize32, &function); + // Note: exceptions will get handled further down; + // don't early return for them here. + AutoObjectVector scopeChain(cx); + if (scopeChain.append(obj)) { + CompileFunction(cx, scopeChain, + options, nullptr, 0, nullptr, + buf, fileSize32, &function); + } } PR_MemUnmap(buf, fileSize32); @@ -829,9 +834,14 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo &aInfo, script = Compile(cx, obj, options, buf, fileSize32); } else { - function = CompileFunction(cx, obj, options, - nullptr, 0, nullptr, - buf, fileSize32); + // Note: exceptions will get handled further down; + // don't early return for them here. + AutoObjectVector scopeChain(cx); + if (scopeChain.append(obj)) { + CompileFunction(cx, scopeChain, + options, nullptr, 0, nullptr, + buf, fileSize32, &function); + } } free(buf); @@ -869,9 +879,14 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo &aInfo, if (!mReuseLoaderGlobal) { Compile(cx, obj, options, buf, bytesRead, &script); } else { - CompileFunction(cx, obj, options, - nullptr, 0, nullptr, - buf, bytesRead, &function); + // Note: exceptions will get handled further down; + // don't early return for them here. + AutoObjectVector scopeChain(cx); + if (scopeChain.append(obj)) { + CompileFunction(cx, scopeChain, + options, nullptr, 0, nullptr, + buf, bytesRead, &function); + } } } // Propagate the exception, if one exists. Also, don't leave the stale diff --git a/js/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/xpconnect/loader/mozJSSubScriptLoader.cpp index 2ec843d450ab..3b2d13b45f0c 100644 --- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp +++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp @@ -90,6 +90,22 @@ ReportError(JSContext *cx, const char *msg) return NS_OK; } +// There probably aren't actually any consumers that rely on having the full +// scope chain up the parent chain of "obj" (instead of just having obj and then +// the global), but we do this for now to preserve backwards compat. +static bool +BuildScopeChainForObject(JSContext *cx, HandleObject obj, + AutoObjectVector &scopeChain) +{ + RootedObject cur(cx, obj); + for ( ; cur && !JS_IsGlobalObject(cur); cur = JS_GetParent(cur)) { + if (!scopeChain.append(cur)) { + return false; + } + } + return true; +} + nsresult mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *targetObjArg, const nsAString &charset, const char *uriStr, @@ -161,10 +177,13 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *targetObj if (!reuseGlobal) { JS::Compile(cx, target_obj, options, srcBuf, script); } else { - JS::CompileFunction(cx, target_obj, options, - nullptr, 0, nullptr, - srcBuf, - function); + AutoObjectVector scopeChain(cx); + if (!BuildScopeChainForObject(cx, target_obj, scopeChain)) { + return NS_ERROR_OUT_OF_MEMORY; + } + // XXXbz do we really not care if the compile fails??? + JS::CompileFunction(cx, scopeChain, options, nullptr, 0, nullptr, + srcBuf, function); } } else { // We only use lazy source when no special encoding is specified because @@ -173,9 +192,13 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *targetObj options.setSourceIsLazy(true); JS::Compile(cx, target_obj, options, buf.get(), len, script); } else { - JS::CompileFunction(cx, target_obj, options, - nullptr, 0, nullptr, buf.get(), - len, function); + AutoObjectVector scopeChain(cx); + if (!BuildScopeChainForObject(cx, target_obj, scopeChain)) { + return NS_ERROR_OUT_OF_MEMORY; + } + // XXXbz do we really not care if the compile fails??? + JS::CompileFunction(cx, scopeChain, options, nullptr, 0, nullptr, + buf.get(), len, function); } }