Bug 1254848 part 1. Take ownership of error reporting on the AutoEntryScript in mozJSComponentLoader::ObjectForLocation. r=bholley

The code as it stood is a bit weird.  It sets up an AutoJSAPI that takes
ownership of error reporting.  Then later it also sets up an
AutoEntryScript... but keeps using the JSContext it got from the AutoJSAPI.
It's not obvious that there is any guarantee that this matches the JSContext
from the AutoEntryScript!

So we go ahead and change the things that are nominally using the
AutoEntryScript to use it JSContext and take ownership of error reporting on it
explicitly.  If the JSContext is the same as that of the AutoJSAPI, then we were
getting backstopped by its taking ownership of error reporting anyway.  If it's
not, we don't want to leave exceptions dangling on it.
This commit is contained in:
Boris Zbarsky 2016-03-09 15:28:33 -05:00
parent d0363ce0e6
commit 731f2ec68f

View File

@ -1,3 +1,4 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
@ -884,9 +885,9 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo& aInfo,
}
// Propagate the exception, if one exists. Also, don't leave the stale
// exception on this context.
if (!script && !function && aPropagateExceptions) {
JS_GetPendingException(cx, aException);
JS_ClearPendingException(cx);
if (!script && !function && aPropagateExceptions &&
jsapi.HasException()) {
jsapi.StealException(aException);
}
}
@ -931,33 +932,36 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo& aInfo,
aTableScript.set(tableScript);
bool ok = false;
{
{ // Scope for AutoEntryScript
// We're going to run script via JS_ExecuteScript or
// JS_CallFunction, so we need an AutoEntryScript.
// This is Gecko-specific and not in any spec.
dom::AutoEntryScript aes(NativeGlobal(CurrentGlobalOrNull(cx)),
dom::AutoEntryScript aes(CurrentGlobalOrNull(cx),
"component loader load module");
AutoSaveContextOptions asco(cx);
aes.TakeOwnershipOfErrorReporting();
JSContext* aescx = aes.cx();
AutoSaveContextOptions asco(aescx);
if (aPropagateExceptions)
ContextOptionsRef(cx).setDontReportUncaught(true);
ContextOptionsRef(aescx).setDontReportUncaught(true);
bool ok;
if (script) {
ok = JS_ExecuteScript(cx, script);
ok = JS_ExecuteScript(aescx, script);
} else {
RootedValue rval(cx);
ok = JS_CallFunction(cx, obj, function, JS::HandleValueArray::empty(), &rval);
ok = JS_CallFunction(aescx, obj, function,
JS::HandleValueArray::empty(), &rval);
}
}
if (!ok) {
if (aPropagateExceptions) {
JS_GetPendingException(cx, aException);
JS_ClearPendingException(cx);
if (!ok) {
if (aPropagateExceptions && aes.HasException()) {
aes.StealException(aException);
}
aObject.set(nullptr);
aTableScript.set(nullptr);
return NS_ERROR_FAILURE;
}
aObject.set(nullptr);
aTableScript.set(nullptr);
return NS_ERROR_FAILURE;
}
/* Freed when we remove from the table. */