Bug 1295322 part 2. Stop propagating through xpconnect exceptions to consumers that won't be able to work with them. r=bholley

This commit is contained in:
Boris Zbarsky 2016-08-26 15:38:16 -04:00
parent 6a73ce5a82
commit 4821850eb8
2 changed files with 52 additions and 6 deletions

View File

@ -273,9 +273,11 @@ CallbackObject::CallSetup::~CallSetup()
// runs. Note that we've already run ~mAc, effectively, so we don't have
// to worry about ordering here.
if (mErrorResult.IsJSContextException()) {
// XXXkhuey bug 1117269.
// This won't be true anymore because we will report the exception on
// the JSContext ... so throw something else.
// XXXkhuey bug 1117269. When this is fixed, please consider fixing
// ThrowExceptionValueIfSafe over in Exceptions.cpp in the same way.
// IsJSContextException shouldn't be true anymore because we will report
// the exception on the JSContext ... so throw something else.
mErrorResult.Throw(NS_ERROR_UNEXPECTED);
}
}

View File

@ -25,6 +25,50 @@
namespace mozilla {
namespace dom {
// Throw the given exception value if it's safe. If it's not safe, then
// synthesize and throw a new exception value for NS_ERROR_UNEXPECTED. The
// incoming value must be in the compartment of aCx. This function guarantees
// that an exception is pending on aCx when it returns.
static void
ThrowExceptionValueIfSafe(JSContext* aCx, JS::Handle<JS::Value> exnVal,
nsIException* aOriginalException)
{
MOZ_ASSERT(aOriginalException);
if (!exnVal.isObject()) {
JS_SetPendingException(aCx, exnVal);
return;
}
JS::Rooted<JSObject*> exnObj(aCx, &exnVal.toObject());
MOZ_ASSERT(js::IsObjectInContextCompartment(exnObj, aCx),
"exnObj needs to be in the right compartment for the "
"CheckedUnwrap thing to make sense");
if (js::CheckedUnwrap(exnObj)) {
// This is an object we're allowed to work with, so just go ahead and throw
// it.
JS_SetPendingException(aCx, exnVal);
return;
}
// We could probably Throw(aCx, NS_ERROR_UNEXPECTED) here, and it would do the
// right thing due to there not being an existing exception on the runtime at
// this point, but it's clearer to explicitly do the thing we want done. This
// is also why we don't just call ThrowExceptionObject on the Exception we
// create: it would do the right thing, but that fact is not obvious.
RefPtr<Exception> syntheticException =
CreateException(aCx, NS_ERROR_UNEXPECTED);
JS::Rooted<JS::Value> syntheticVal(aCx);
if (!GetOrCreateDOMReflector(aCx, syntheticException, &syntheticVal)) {
return;
}
MOZ_ASSERT(syntheticVal.isObject() &&
!js::IsWrapper(&syntheticVal.toObject()),
"Must have a reflector here, not a wrapper");
JS_SetPendingException(aCx, syntheticVal);
}
void
ThrowExceptionObject(JSContext* aCx, nsIException* aException)
{
@ -44,7 +88,7 @@ ThrowExceptionObject(JSContext* aCx, nsIException* aException)
return;
}
JS_SetPendingException(aCx, val);
ThrowExceptionValueIfSafe(aCx, val, aException);
}
void
@ -76,7 +120,7 @@ ThrowExceptionObject(JSContext* aCx, Exception* aException)
if (!JS_WrapValue(aCx, &thrown)) {
return;
}
JS_SetPendingException(aCx, thrown);
ThrowExceptionValueIfSafe(aCx, thrown, aException);
return;
}
@ -84,7 +128,7 @@ ThrowExceptionObject(JSContext* aCx, Exception* aException)
return;
}
JS_SetPendingException(aCx, thrown);
ThrowExceptionValueIfSafe(aCx, thrown, aException);
}
bool