Bug 1083648 part 3. Change nsJSUtils::CompileFunction to take an explicit scope chain vector, not just a single scope object, and pass in the right objects in CompileEventHandlerInternal. r=bholley

This commit is contained in:
Boris Zbarsky 2014-10-25 00:50:29 -04:00
parent e5c5edfce2
commit ac67e4fb9f
6 changed files with 37 additions and 11 deletions

View File

@ -124,7 +124,7 @@ nsJSUtils::ReportPendingException(JSContext *aContext)
nsresult
nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
JS::Handle<JSObject*> aTarget,
JS::AutoObjectVector& aScopeChain,
JS::CompileOptions& aOptions,
const nsACString& aName,
uint32_t aArgCount,
@ -135,19 +135,20 @@ nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
MOZ_ASSERT(jsapi.OwnsErrorReporting());
JSContext* cx = jsapi.cx();
MOZ_ASSERT(js::GetEnterCompartmentDepth(cx) > 0);
MOZ_ASSERT_IF(aTarget, js::IsObjectInContextCompartment(aTarget, cx));
MOZ_ASSERT_IF(aScopeChain.length() != 0,
js::IsObjectInContextCompartment(aScopeChain[0], cx));
MOZ_ASSERT_IF(aOptions.versionSet, aOptions.version != JSVERSION_UNKNOWN);
mozilla::DebugOnly<nsIScriptContext*> ctx = GetScriptContextFromJSContext(cx);
MOZ_ASSERT_IF(ctx, ctx->IsContextInitialized());
// Do the junk Gecko is supposed to do before calling into JSAPI.
if (aTarget) {
JS::ExposeObjectToActiveJS(aTarget);
for (size_t i = 0; i < aScopeChain.length(); ++i) {
JS::ExposeObjectToActiveJS(aScopeChain[i]);
}
// Compile.
JS::Rooted<JSFunction*> fun(cx);
if (!JS::CompileFunction(cx, aTarget, aOptions,
if (!JS::CompileFunction(cx, aScopeChain, aOptions,
PromiseFlatCString(aName).get(),
aArgCount, aArgArray,
PromiseFlatString(aBody).get(),

View File

@ -56,7 +56,7 @@ public:
static void ReportPendingException(JSContext *aContext);
static nsresult CompileFunction(mozilla::dom::AutoJSAPI& jsapi,
JS::Handle<JSObject*> aTarget,
JS::AutoObjectVector& aScopeChain,
JS::CompileOptions& aOptions,
const nsACString& aName,
uint32_t aArgCount,

View File

@ -860,6 +860,19 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
return rv;
}
}
JS::AutoObjectVector scopeChain(cx);
{ // scope for curScope
// We append all the non-globals on our desired scope chain.
JS::Rooted<JSObject*> curScope(cx, &v.toObject());
while (curScope && !JS_IsGlobalObject(curScope)) {
if (!scopeChain.append(curScope)) {
return NS_ERROR_OUT_OF_MEMORY;
}
curScope = JS_GetParent(curScope);
}
}
if (addonId) {
JS::Rooted<JSObject*> vObj(cx, &v.toObject());
JS::Rooted<JSObject*> addonScope(cx, xpc::GetAddonScope(cx, vObj, addonId));
@ -867,6 +880,14 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
return NS_ERROR_FAILURE;
}
JSAutoCompartment ac(cx, addonScope);
for (size_t i = 0; i < scopeChain.length(); ++i) {
if (!JS_WrapObject(cx, scopeChain[i])) {
return NS_ERROR_FAILURE;
}
}
// And wrap v as well, since scopeChain might be empty so we can't
// reliably use it to enter a compartment.
if (!JS_WrapValue(cx, &v)) {
return NS_ERROR_FAILURE;
}
@ -896,7 +917,7 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
.setDefineOnScope(false);
JS::Rooted<JSObject*> handler(cx);
result = nsJSUtils::CompileFunction(jsapi, target, options,
result = nsJSUtils::CompileFunction(jsapi, scopeChain, options,
nsAtomCString(typeAtom),
argCount, argNames, *body, handler.address());
NS_ENSURE_SUCCESS(result, result);

View File

@ -196,7 +196,8 @@ nsXBLProtoImplMethod::CompileMember(AutoJSAPI& jsapi, const nsCString& aClassStr
uncompiledMethod->mBodyText.GetLineNumber())
.setVersion(JSVERSION_LATEST);
JS::Rooted<JSObject*> methodObject(cx);
nsresult rv = nsJSUtils::CompileFunction(jsapi, JS::NullPtr(), options, cname,
JS::AutoObjectVector emptyVector(cx);
nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, cname,
paramCount,
const_cast<const char**>(args),
body, methodObject.address());

View File

@ -195,7 +195,8 @@ nsXBLProtoImplProperty::CompileMember(AutoJSAPI& jsapi, const nsCString& aClassS
.setVersion(JSVERSION_LATEST);
nsCString name = NS_LITERAL_CSTRING("get_") + NS_ConvertUTF16toUTF8(mName);
JS::Rooted<JSObject*> getterObject(cx);
rv = nsJSUtils::CompileFunction(jsapi, JS::NullPtr(), options, name, 0,
JS::AutoObjectVector emptyVector(cx);
rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, name, 0,
nullptr, getter, getterObject.address());
delete getterText;
@ -240,7 +241,8 @@ nsXBLProtoImplProperty::CompileMember(AutoJSAPI& jsapi, const nsCString& aClassS
.setVersion(JSVERSION_LATEST);
nsCString name = NS_LITERAL_CSTRING("set_") + NS_ConvertUTF16toUTF8(mName);
JS::Rooted<JSObject*> setterObject(cx);
rv = nsJSUtils::CompileFunction(jsapi, JS::NullPtr(), options, name, 1,
JS::AutoObjectVector emptyVector(cx);
rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, name, 1,
gPropertyArgs, setter,
setterObject.address());

View File

@ -373,7 +373,8 @@ nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName,
.setVersion(JSVERSION_LATEST);
JS::Rooted<JSObject*> handlerFun(cx);
nsresult rv = nsJSUtils::CompileFunction(jsapi, JS::NullPtr(), options,
JS::AutoObjectVector emptyVector(cx);
nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options,
nsAtomCString(aName), argCount,
argNames, handlerText,
handlerFun.address());