summaryrefslogtreecommitdiff
path: root/dom/base/ScriptSettings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/ScriptSettings.cpp')
-rw-r--r--dom/base/ScriptSettings.cpp97
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,