diff options
Diffstat (limited to 'dom/base/ScriptSettings.cpp')
-rw-r--r-- | dom/base/ScriptSettings.cpp | 97 |
1 files changed, 60 insertions, 37 deletions
diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index 3fbfb9043..daf8ebb33 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -312,36 +312,15 @@ AutoJSAPI::~AutoJSAPI() { if (mOwnErrorReporting) { MOZ_ASSERT(NS_IsMainThread(), "See corresponding assertion in TakeOwnershipOfErrorReporting()"); - JS::ContextOptionsRef(cx()).setAutoJSAPIOwnsErrorReporting(mOldAutoJSAPIOwnsErrorReporting); - if (HasException()) { - - // AutoJSAPI uses a JSAutoNullableCompartment, and may be in a null - // compartment when the destructor is called. However, the JS engine - // requires us to be in a compartment when we fetch the pending exception. - // In this case, we enter the privileged junk scope and don't dispatch any - // error events. - JS::Rooted<JSObject*> errorGlobal(cx(), JS::CurrentGlobalOrNull(cx())); - if (!errorGlobal) - errorGlobal = xpc::PrivilegedJunkScope(); - JSAutoCompartment ac(cx(), errorGlobal); - nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal); - JS::Rooted<JS::Value> exn(cx()); - js::ErrorReport jsReport(cx()); - if (StealException(&exn) && jsReport.init(cx(), exn)) { - nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport(); - xpcReport->Init(jsReport.report(), jsReport.message(), - nsContentUtils::IsCallerChrome(), - win ? win->WindowID() : 0); - if (win) { - DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn); - } else { - xpcReport->LogToConsole(); - } - } else { - NS_WARNING("OOMed while acquiring uncaught exception from JSAPI"); - } - } + ReportException(); + + // 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()) { @@ -502,17 +481,61 @@ AutoJSAPI::TakeOwnershipOfErrorReporting() JS_SetErrorReporter(rt, WarningOnlyErrorReporter); } +void +AutoJSAPI::ReportException() +{ + MOZ_ASSERT(OwnsErrorReporting(), "This is not our exception to report!"); + if (!HasException()) { + return; + } + + // AutoJSAPI uses a JSAutoNullableCompartment, and may be in a null + // compartment when the destructor is called. However, the JS engine + // requires us to be in a compartment when we fetch the pending exception. + // In this case, we enter the privileged junk scope and don't dispatch any + // error events. + JS::Rooted<JSObject*> errorGlobal(cx(), JS::CurrentGlobalOrNull(cx())); + if (!errorGlobal) + errorGlobal = xpc::PrivilegedJunkScope(); + JSAutoCompartment ac(cx(), errorGlobal); + nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal); + JS::Rooted<JS::Value> exn(cx()); + js::ErrorReport jsReport(cx()); + if (StealException(&exn) && jsReport.init(cx(), exn)) { + nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport(); + xpcReport->Init(jsReport.report(), jsReport.message(), + nsContentUtils::IsCallerChrome(), + win ? win->WindowID() : 0); + if (win) { + DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn); + } else { + xpcReport->LogToConsole(); + } + } else { + NS_WARNING("OOMed while acquiring uncaught exception from JSAPI"); + } +} + +bool +AutoJSAPI::PeekException(JS::MutableHandle<JS::Value> aVal) +{ + MOZ_ASSERT_IF(mIsMainThread, CxPusherIsStackTop()); + MOZ_ASSERT(HasException()); + MOZ_ASSERT(js::GetContextCompartment(cx())); + if (!JS_GetPendingException(cx(), aVal)) { + return false; + } + return true; +} + bool AutoJSAPI::StealException(JS::MutableHandle<JS::Value> aVal) { - MOZ_ASSERT(CxPusherIsStackTop()); - MOZ_ASSERT(HasException()); - MOZ_ASSERT(js::GetContextCompartment(cx())); - if (!JS_GetPendingException(cx(), aVal)) { - return false; - } - JS_ClearPendingException(cx()); - return true; + if (!PeekException(aVal)) { + return false; + } + JS_ClearPendingException(cx()); + return true; } AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject, |