diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index c085f3ae74d0..82e51101dc87 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -312,7 +312,6 @@ AutoJSAPI::~AutoJSAPI() { if (mOwnErrorReporting) { MOZ_ASSERT(NS_IsMainThread(), "See corresponding assertion in TakeOwnershipOfErrorReporting()"); - JS::ContextOptionsRef(cx()).setAutoJSAPIOwnsErrorReporting(mOldAutoJSAPIOwnsErrorReporting); if (HasException()) { @@ -342,6 +341,13 @@ AutoJSAPI::~AutoJSAPI() NS_WARNING("OOMed while acquiring uncaught exception from JSAPI"); } } + + // We need to do this _after_ processing the existing exception, because the + // JS engine can throw while doing that, and uses this bit to determine what + // to do in that case: squelch the exception if the bit is set, otherwise + // call the error reporter. Calling WarningOnlyErrorReporter with a + // non-warning will assert, so we need to make sure we do the former. + JS::ContextOptionsRef(cx()).setAutoJSAPIOwnsErrorReporting(mOldAutoJSAPIOwnsErrorReporting); } if (mOldErrorReporter.isSome()) { diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 44222f47a992..6d91de1c7b3e 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -229,6 +229,13 @@ ReportError(JSContext *cx, const char *message, JSErrorReport *reportp, if (cx->options().autoJSAPIOwnsErrorReporting() || JS_IsRunning(cx)) { if (ErrorToException(cx, message, reportp, callback, userRef)) return; + + /* + * The AutoJSAPI error reporter only allows warnings to be reported so + * just ignore this error rather than try to report it. + */ + if (cx->options().autoJSAPIOwnsErrorReporting()) + return; } /* diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index ce9f2c44e278..e9abba006ced 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -608,6 +608,12 @@ js::ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp, static bool IsDuckTypedErrorObject(JSContext *cx, HandleObject exnObject, const char **filename_strp) { + /* + * This function is called from ErrorReport::init and so should not generate + * any new exceptions. + */ + AutoClearPendingException acpe(cx); + bool found; if (!JS_HasProperty(cx, exnObject, js_message_str, &found) || !found) return false; diff --git a/js/src/jsexn.h b/js/src/jsexn.h index f601c03cca6c..5a5f6f3c3bcd 100644 --- a/js/src/jsexn.h +++ b/js/src/jsexn.h @@ -115,6 +115,20 @@ ExnTypeFromProtoKey(JSProtoKey key) return type; } +class AutoClearPendingException +{ + JSContext *cx; + + public: + explicit AutoClearPendingException(JSContext *cxArg) + : cx(cxArg) + { } + + ~AutoClearPendingException() { + cx->clearPendingException(); + } +}; + } // namespace js #endif /* jsexn_h */