diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index f5980c1c56d6..8a26e5e83726 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -431,6 +431,7 @@ public: nsIPrincipal* aScriptOriginPrincipal, nsIPrincipal* aGlobalPrincipal, nsPIDOMWindow* aWindow, + JS::Handle aError, bool aDispatchEvent) // Pass an empty category, then compute ours : AsyncErrorReporter(aRuntime, aErrorReport, aFallbackMessage, @@ -439,6 +440,7 @@ public: , mScriptGlobal(aScriptGlobal) , mOriginPrincipal(aScriptOriginPrincipal) , mDispatchEvent(aDispatchEvent) + , mError(aRuntime, aError) { } @@ -458,7 +460,8 @@ public: nsRefPtr presContext; docShell->GetPresContext(getter_AddRefs(presContext)); - ErrorEventInit init; + ThreadsafeAutoJSContext cx; + RootedDictionary init(cx); init.mCancelable = true; init.mFilename = mFileName; init.mBubbles = true; @@ -480,6 +483,7 @@ public: if (sameOrigin) { init.mMessage = mErrorMsg; init.mLineno = mLineNumber; + init.mError = mError; } else { NS_WARNING("Not same origin error!"); init.mMessage = xoriginMsg; @@ -507,6 +511,7 @@ private: nsCOMPtr mScriptGlobal; nsCOMPtr mOriginPrincipal; bool mDispatchEvent; + JS::PersistentRootedValue mError; static bool sHandlingScriptError; }; @@ -551,6 +556,9 @@ NS_ScriptErrorReporter(JSContext *cx, // XXX this means we are not going to get error reports on non DOM contexts nsIScriptContext *context = nsJSUtils::GetDynamicScriptContext(cx); + JS::Rooted exception(cx); + ::JS_GetPendingException(cx, &exception); + // Note: we must do this before running any more code on cx (if cx is the // dynamic script context). ::JS_ClearPendingException(cx); @@ -573,6 +581,7 @@ NS_ScriptErrorReporter(JSContext *cx, nsJSPrincipals::get(report->originPrincipals), scriptPrincipal->GetPrincipal(), win, + exception, /* We do not try to report Out Of Memory via a dom * event because the dom event handler would * encounter an OOM exception trying to process the diff --git a/dom/events/nsJSEventListener.cpp b/dom/events/nsJSEventListener.cpp index d589699d8c3b..79cad28e957c 100644 --- a/dom/events/nsJSEventListener.cpp +++ b/dom/events/nsJSEventListener.cpp @@ -165,6 +165,7 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent) Optional fileName; Optional lineNumber; Optional columnNumber; + Optional> error; NS_ENSURE_TRUE(aEvent, NS_ERROR_UNEXPECTED); ErrorEvent* scriptEvent = aEvent->InternalDOMEvent()->AsErrorEvent(); @@ -177,6 +178,10 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent) lineNumber.Construct(); lineNumber.Value() = scriptEvent->Lineno(); + + ThreadsafeAutoJSContext cx; + error.Construct(cx); + error.Value() = scriptEvent->Error(cx); } else { msgOrEvent.SetAsEvent() = aEvent->InternalDOMEvent(); } @@ -185,7 +190,7 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent) mHandler.OnErrorEventHandler(); ErrorResult rv; bool handled = handler->Call(mTarget, msgOrEvent, fileName, lineNumber, - columnNumber, rv); + columnNumber, error, rv); if (rv.Failed()) { return rv.ErrorCode(); } diff --git a/dom/webidl/ErrorEvent.webidl b/dom/webidl/ErrorEvent.webidl index c4ca51ef5bd4..3349078ba0af 100644 --- a/dom/webidl/ErrorEvent.webidl +++ b/dom/webidl/ErrorEvent.webidl @@ -10,6 +10,7 @@ interface ErrorEvent : Event readonly attribute DOMString filename; readonly attribute unsigned long lineno; readonly attribute unsigned long column; + readonly attribute any error; }; dictionary ErrorEventInit : EventInit @@ -18,4 +19,5 @@ dictionary ErrorEventInit : EventInit DOMString filename = ""; unsigned long lineno = 0; unsigned long column = 0; + any error = null; }; diff --git a/dom/webidl/EventHandler.webidl b/dom/webidl/EventHandler.webidl index 6eceffc4a533..32fcdcfaec04 100644 --- a/dom/webidl/EventHandler.webidl +++ b/dom/webidl/EventHandler.webidl @@ -21,7 +21,7 @@ callback OnBeforeUnloadEventHandlerNonNull = DOMString? (Event event); typedef OnBeforeUnloadEventHandlerNonNull? OnBeforeUnloadEventHandler; [TreatNonObjectAsNull] -callback OnErrorEventHandlerNonNull = boolean ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column); +callback OnErrorEventHandlerNonNull = boolean ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column, optional any error); typedef OnErrorEventHandlerNonNull? OnErrorEventHandler; [NoInterfaceObject] diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 8fdfbc73867d..749a6b452510 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -1185,7 +1185,7 @@ public: // they show up in the error console. if (!JSREPORT_IS_WARNING(aFlags)) { // First fire an ErrorEvent at the worker. - ErrorEventInit init; + RootedDictionary init(aCx); init.mMessage = aMessage; init.mFilename = aFilename; init.mLineno = aLineNumber; @@ -3135,7 +3135,7 @@ WorkerPrivateParent::BroadcastErrorToSharedWorkers( continue; } - ErrorEventInit errorInit; + RootedDictionary errorInit(aCx); errorInit.mBubbles = false; errorInit.mCancelable = true; errorInit.mMessage = aMessage; @@ -3201,7 +3201,7 @@ WorkerPrivateParent::BroadcastErrorToSharedWorkers( MOZ_ASSERT(sgo); MOZ_ASSERT(NS_IsMainThread()); - ErrorEventInit init; + RootedDictionary init(aCx); init.mLineno = aLineNumber; init.mFilename = aFilename; init.mMessage = aMessage;