Bug 839088 part 2. Add way to indicate to a CallSetup that it should propagate any exceptions thrown during the call out to the ErrorResult for the call. r=peterv

This commit is contained in:
Boris Zbarsky 2013-02-19 11:54:40 -05:00
parent fb92453c3a
commit c1a79f1556
3 changed files with 48 additions and 6 deletions

View File

@ -33,8 +33,12 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback) NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRACE_END
CallbackObject::CallSetup::CallSetup(JSObject* const aCallback) CallbackObject::CallSetup::CallSetup(JSObject* const aCallback,
ErrorResult& aRv,
ExceptionHandling aExceptionHandling)
: mCx(nullptr) : mCx(nullptr)
, mErrorResult(aRv)
, mExceptionHandling(aExceptionHandling)
{ {
xpc_UnmarkGrayObject(aCallback); xpc_UnmarkGrayObject(aCallback);
@ -123,14 +127,40 @@ CallbackObject::CallSetup::CallSetup(JSObject* const aCallback)
// And now we're ready to go. // And now we're ready to go.
mCx = cx; mCx = cx;
// Make sure the JS engine doesn't report exceptions we want to re-throw
if (mExceptionHandling == eRethrowExceptions) {
mSavedJSContextOptions = JS_GetOptions(cx);
JS_SetOptions(cx, mSavedJSContextOptions | JSOPTION_DONT_REPORT_UNCAUGHT);
}
} }
CallbackObject::CallSetup::~CallSetup() CallbackObject::CallSetup::~CallSetup()
{ {
// First things first: if we have a JSContext, report any pending // First things first: if we have a JSContext, report any pending
// errors on it. // errors on it, unless we were told to re-throw them.
if (mCx) { if (mCx) {
nsJSUtils::ReportPendingException(mCx); bool dealtWithPendingException = false;
if (mExceptionHandling == eRethrowExceptions) {
// Restore the old context options
JS_SetOptions(mCx, mSavedJSContextOptions);
mErrorResult.MightThrowJSException();
if (JS_IsExceptionPending(mCx)) {
JS::Value exn;
if (JS_GetPendingException(mCx, &exn)) {
mErrorResult.ThrowJSException(mCx, exn);
JS_ClearPendingException(mCx);
dealtWithPendingException = true;
}
}
}
if (!dealtWithPendingException) {
// Either we're supposed to report our exceptions, or we're supposed to
// re-throw them but we failed to JS_GetPendingException. Either way,
// just report the pending exception, if any.
nsJSUtils::ReportPendingException(mCx);
}
} }
// If we have an mCtx, we need to call ScriptEvaluated() on it. But we have // If we have an mCtx, we need to call ScriptEvaluated() on it. But we have

View File

@ -81,6 +81,11 @@ public:
return mCallback; return mCallback;
} }
enum ExceptionHandling {
eReportExceptions,
eRethrowExceptions
};
protected: protected:
explicit CallbackObject(CallbackObject* aCallbackFunction) explicit CallbackObject(CallbackObject* aCallbackFunction)
: mCallback(aCallbackFunction->mCallback) : mCallback(aCallbackFunction->mCallback)
@ -112,7 +117,8 @@ protected:
* non-null. * non-null.
*/ */
public: public:
CallSetup(JSObject* const aCallable); CallSetup(JSObject* const aCallable, ErrorResult& aRv,
ExceptionHandling aExceptionHandling);
~CallSetup(); ~CallSetup();
JSContext* GetContext() const JSContext* GetContext() const
@ -149,6 +155,12 @@ protected:
// JSContext. Though in practice we'll often manually order those two // JSContext. Though in practice we'll often manually order those two
// things. // things.
Maybe<JSAutoCompartment> mAc; Maybe<JSAutoCompartment> mAc;
// An ErrorResult to possibly re-throw exceptions on and whether
// we should re-throw them.
ErrorResult& mErrorResult;
const ExceptionHandling mExceptionHandling;
uint32_t mSavedJSContextOptions;
}; };
}; };

View File

@ -7707,7 +7707,7 @@ class CGCallback(CGClass):
argsWithoutThis = list(args) argsWithoutThis = list(args)
args.insert(0, Argument("const T&", "thisObj")) args.insert(0, Argument("const T&", "thisObj"))
setupCall = ("CallSetup s(mCallback);\n" setupCall = ("CallSetup s(mCallback, aRv, eReportExceptions);\n"
"if (!s.GetContext()) {\n" "if (!s.GetContext()) {\n"
" aRv.Throw(NS_ERROR_UNEXPECTED);\n" " aRv.Throw(NS_ERROR_UNEXPECTED);\n"
" return${errorReturn};\n" " return${errorReturn};\n"
@ -7970,7 +7970,7 @@ class CallbackMember(CGNativeMember):
# It's been done for us already # It's been done for us already
return "" return ""
return string.Template( return string.Template(
"CallSetup s(mCallback);\n" "CallSetup s(mCallback, aRv, eReportExceptions);\n"
"JSContext* cx = s.GetContext();\n" "JSContext* cx = s.GetContext();\n"
"if (!cx) {\n" "if (!cx) {\n"
" aRv.Throw(NS_ERROR_UNEXPECTED);\n" " aRv.Throw(NS_ERROR_UNEXPECTED);\n"