Bug 972312 part 2. Get rid of InternalScriptErrorEvent and just use mozilla::dom::ErrorEvent for the cases that used to use it. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Sun, 23 Feb 2014 00:01:12 -0500
changeset 170409 24aa8fa1f13adfd87ff4de5d4a668014571c9905
parent 170408 8374817674559644752f4e72ee7f6413008e0596
child 170410 ab395abf96b9705d4ab00dcf310df7d6d17f9d96
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewerssmaug
bugs972312
milestone30.0a1
Bug 972312 part 2. Get rid of InternalScriptErrorEvent and just use mozilla::dom::ErrorEvent for the cases that used to use it. r=smaug
dom/base/nsIScriptGlobalObject.h
dom/base/nsJSEnvironment.cpp
dom/events/nsDOMEvent.cpp
dom/events/nsDOMEvent.h
dom/events/nsJSEventListener.cpp
dom/events/test/error_event_worker.js
dom/events/test/mochitest.ini
dom/events/test/test_error_events.html
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IDBRequest.h
dom/indexedDB/IndexedDatabaseManager.cpp
dom/workers/WorkerPrivate.cpp
widget/BasicEvents.h
widget/ContentEvents.h
widget/EventClassList.h
widget/tests/test_assign_event_data.html
--- a/dom/base/nsIScriptGlobalObject.h
+++ b/dom/base/nsIScriptGlobalObject.h
@@ -10,30 +10,36 @@
 #include "nsISupports.h"
 #include "nsIGlobalObject.h"
 #include "js/TypeDecls.h"
 #include "mozilla/EventForwards.h"
 
 class nsIScriptContext;
 class nsIScriptGlobalObject;
 
+namespace mozilla {
+namespace dom {
+class ErrorEventInit;
+} // namespace dom
+} // namespace mozilla
+
 // A helper function for nsIScriptGlobalObject implementations to use
 // when handling a script error.  Generally called by the global when a context
 // notifies it of an error via nsIScriptGlobalObject::HandleScriptError.
 // Returns true if HandleDOMEvent was actually called, in which case
 // aStatus will be filled in with the status.
 bool
 NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
-                     mozilla::InternalScriptErrorEvent *aErrorEvent,
+                     const mozilla::dom::ErrorEventInit &aErrorEvent,
                      nsEventStatus *aStatus);
 
 
 #define NS_ISCRIPTGLOBALOBJECT_IID \
-{ 0x30c64680, 0x909a, 0x4435, \
-  { 0x90, 0x3b, 0x29, 0x3e, 0xb5, 0x5d, 0xc7, 0xa0 } }
+{ 0x6995e1ff, 0x9fc5, 0x44a7, \
+ { 0xbd, 0x7c, 0xe7, 0xcd, 0x44, 0x47, 0x22, 0x87 } }
 
 /**
  * The global object which keeps a script context for each supported script
  * language. This often used to store per-window global state.
  * This is a heavyweight interface implemented only by DOM globals, and
  * it might go away some time in the future.
  */
 
@@ -69,19 +75,19 @@ public:
    * same object the global is using for a global for that language.
    */
   virtual void OnFinalize(JSObject* aObject) = 0;
 
   /**
    * Handle a script error.  Generally called by a script context.
    */
   virtual nsresult HandleScriptError(
-                     mozilla::InternalScriptErrorEvent *aErrorEvent,
+                     const mozilla::dom::ErrorEventInit &aErrorEventInit,
                      nsEventStatus *aEventStatus) {
-    NS_ENSURE_STATE(NS_HandleScriptError(this, aErrorEvent, aEventStatus));
+    NS_ENSURE_STATE(NS_HandleScriptError(this, aErrorEventInit, aEventStatus));
     return NS_OK;
   }
 
   virtual bool IsBlackForCC(bool aTracingNeeded = true) { return false; }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptGlobalObject,
                               NS_ISCRIPTGLOBALOBJECT_IID)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -47,16 +47,18 @@
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptNameSpaceManager.h"
 #include "StructuredCloneTags.h"
+#include "mozilla/AutoRestore.h"
+#include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ImageDataBinding.h"
 #include "nsAXPCNativeCallContext.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 
 #include "nsJSPrincipals.h"
 
 #ifdef XP_MACOSX
@@ -307,34 +309,40 @@ private:
 };
 
 // A utility function for script languages to call.  Although it looks small,
 // the use of nsIDocShell and nsPresContext triggers a huge number of
 // dependencies that most languages would not otherwise need.
 // XXXmarkh - This function is mis-placed!
 bool
 NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
-                     InternalScriptErrorEvent *aErrorEvent,
+                     const ErrorEventInit &aErrorEventInit,
                      nsEventStatus *aStatus)
 {
   bool called = false;
   nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aScriptGlobal));
   nsIDocShell *docShell = win ? win->GetDocShell() : nullptr;
   if (docShell) {
     nsRefPtr<nsPresContext> presContext;
     docShell->GetPresContext(getter_AddRefs(presContext));
 
     static int32_t errorDepth; // Recursion prevention
     ++errorDepth;
 
-    if (presContext && errorDepth < 2) {
+    if (errorDepth < 2) {
       // Dispatch() must be synchronous for the recursion block
       // (errorDepth) to work.
-      nsEventDispatcher::Dispatch(win, presContext, aErrorEvent, nullptr,
-                                  aStatus);
+      nsRefPtr<ErrorEvent> event =
+        ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(win.get()),
+                                NS_LITERAL_STRING("error"),
+                                aErrorEventInit);
+      event->SetTrusted(true);
+
+      nsEventDispatcher::DispatchDOMEvent(win, nullptr, event, presContext,
+                                          aStatus);
       called = true;
     }
     --errorDepth;
   }
   return called;
 }
 
 namespace mozilla {
@@ -439,54 +447,57 @@ public:
     nsEventStatus status = nsEventStatus_eIgnore;
     // First, notify the DOM that we have a script error.
     if (mDispatchEvent) {
       nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mScriptGlobal));
       nsIDocShell* docShell = win ? win->GetDocShell() : nullptr;
       if (docShell &&
           !JSREPORT_IS_WARNING(mFlags) &&
           !sHandlingScriptError) {
-        sHandlingScriptError = true; // Recursion prevention
+        AutoRestore<bool> recursionGuard(sHandlingScriptError);
+        sHandlingScriptError = true;
 
         nsRefPtr<nsPresContext> presContext;
         docShell->GetPresContext(getter_AddRefs(presContext));
 
-        if (presContext) {
-          InternalScriptErrorEvent errorevent(true, NS_LOAD_ERROR);
-
-          errorevent.fileName = mFileName.get();
-
-          nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
-          NS_ENSURE_STATE(sop);
-          nsIPrincipal* p = sop->GetPrincipal();
-          NS_ENSURE_STATE(p);
-
-          bool sameOrigin = !mOriginPrincipal;
-
-          if (p && !sameOrigin) {
-            if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
-              sameOrigin = false;
-            }
+        ErrorEventInit init;
+        init.mCancelable = true;
+        init.mFilename = mFileName;
+        init.mBubbles = true;
+
+        nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
+        NS_ENSURE_STATE(sop);
+        nsIPrincipal* p = sop->GetPrincipal();
+        NS_ENSURE_STATE(p);
+
+        bool sameOrigin = !mOriginPrincipal;
+
+        if (p && !sameOrigin) {
+          if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
+            sameOrigin = false;
           }
-
-          NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
-          if (sameOrigin) {
-            errorevent.errorMsg = mErrorMsg.get();
-            errorevent.lineNr = mLineNumber;
-          } else {
-            NS_WARNING("Not same origin error!");
-            errorevent.errorMsg = xoriginMsg.get();
-            errorevent.lineNr = 0;
-          }
-
-          nsEventDispatcher::Dispatch(win, presContext, &errorevent, nullptr,
-                                      &status);
         }
 
-        sHandlingScriptError = false;
+        NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
+        if (sameOrigin) {
+          init.mMessage = mErrorMsg;
+          init.mLineno = mLineNumber;
+        } else {
+          NS_WARNING("Not same origin error!");
+          init.mMessage = xoriginMsg;
+          init.mLineno = 0;
+        }
+
+        nsRefPtr<ErrorEvent> event =
+          ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(win.get()),
+                                  NS_LITERAL_STRING("error"), init);
+        event->SetTrusted(true);
+
+        nsEventDispatcher::DispatchDOMEvent(win, nullptr, event, presContext,
+                                            &status);
       }
     }
 
     if (status != nsEventStatus_eConsumeNoDefault) {
       AsyncErrorReporter::ReportError();
     }
 
     return NS_OK;
--- a/dom/events/nsDOMEvent.cpp
+++ b/dom/events/nsDOMEvent.cpp
@@ -759,25 +759,16 @@ nsDOMEvent::GetEventPopupControlState(Wi
         break;
       case NS_MOUSE_DOUBLECLICK :
         if (::PopupAllowedForEvent("dblclick"))
           abuse = openControlled;
         break;
       }
     }
     break;
-  case NS_SCRIPT_ERROR_EVENT :
-    switch(aEvent->message) {
-    case NS_LOAD_ERROR :
-      // Any error event will allow popups, if enabled in the pref.
-      if (::PopupAllowedForEvent("error"))
-        abuse = openControlled;
-      break;
-    }
-    break;
   case NS_FORM_EVENT :
     // For these following events only allow popups if they're
     // triggered while handling user input. See
     // nsPresShell::HandleEventInternal() for details.
     if (nsEventStateManager::IsHandlingUserInput()) {
       switch(aEvent->message) {
       case NS_FORM_SUBMIT :
         if (::PopupAllowedForEvent("submit"))
--- a/dom/events/nsDOMEvent.h
+++ b/dom/events/nsDOMEvent.h
@@ -22,16 +22,17 @@
 
 class nsIContent;
 class nsIDOMEventTarget;
 class nsPresContext;
 
 namespace mozilla {
 namespace dom {
 class EventTarget;
+class ErrorEvent;
 }
 }
 
 // Dummy class so we can cast through it to get from nsISupports to
 // nsDOMEvent subclasses with only two non-ambiguous static casts.
 class nsDOMEventBase : public nsIDOMEvent
 {
 };
@@ -85,16 +86,21 @@ public:
   }
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
   {
     return mozilla::dom::EventBinding::Wrap(aCx, aScope, this);
   }
 
+  virtual mozilla::dom::ErrorEvent* AsErrorEvent()
+  {
+    return nullptr;
+  }
+
   // nsIDOMEvent Interface
   NS_DECL_NSIDOMEVENT
 
   void InitPresContextData(nsPresContext* aPresContext);
 
   // Returns true if the event should be trusted.
   bool Init(mozilla::dom::EventTarget* aGlobal);
 
--- a/dom/events/nsJSEventListener.cpp
+++ b/dom/events/nsJSEventListener.cpp
@@ -14,16 +14,17 @@
 #include "nsVariant.h"
 #include "nsIDOMBeforeUnloadEvent.h"
 #include "nsGkAtoms.h"
 #include "xpcpublic.h"
 #include "nsJSEnvironment.h"
 #include "nsDOMJSUtils.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/Likely.h"
+#include "mozilla/dom/ErrorEvent.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "nsDOMEvent.h"
 
 #ifdef DEBUG
 
 #include "nspr.h" // PR_fprintf
 
 class EventListenerCounter
@@ -162,29 +163,26 @@ nsJSEventListener::HandleEvent(nsIDOMEve
 
     nsString errorMsg, file;
     EventOrString msgOrEvent;
     Optional<nsAString> fileName;
     Optional<uint32_t> lineNumber;
     Optional<uint32_t> columnNumber;
 
     NS_ENSURE_TRUE(aEvent, NS_ERROR_UNEXPECTED);
-    InternalScriptErrorEvent* scriptEvent =
-      aEvent->GetInternalNSEvent()->AsScriptErrorEvent();
-    if (scriptEvent &&
-        (scriptEvent->message == NS_LOAD_ERROR ||
-         scriptEvent->typeString.EqualsLiteral("error"))) {
-      errorMsg = scriptEvent->errorMsg;
+    ErrorEvent* scriptEvent = aEvent->InternalDOMEvent()->AsErrorEvent();
+    if (scriptEvent) {
+      scriptEvent->GetMessage(errorMsg);
       msgOrEvent.SetAsString().SetData(errorMsg.Data(), errorMsg.Length());
 
-      file = scriptEvent->fileName;
+      scriptEvent->GetFilename(file);
       fileName = &file;
 
       lineNumber.Construct();
-      lineNumber.Value() = scriptEvent->lineNr;
+      lineNumber.Value() = scriptEvent->Lineno();
     } else {
       msgOrEvent.SetAsEvent() = aEvent->InternalDOMEvent();
     }
 
     nsRefPtr<OnErrorEventHandlerNonNull> handler =
       mHandler.OnErrorEventHandler();
     ErrorResult rv;
     bool handled = handler->Call(mTarget, msgOrEvent, fileName, lineNumber,
new file mode 100644
--- /dev/null
+++ b/dom/events/test/error_event_worker.js
@@ -0,0 +1,15 @@
+ addEventListener("error", function(e) {
+     var obj = {};
+     for (var prop of ["message", "filename", "lineno"]) {
+       obj[prop] = e[prop]
+     }
+     obj.type = "event";
+     postMessage(obj);
+});
+onerror = function(message, filename, lineno) {
+  var obj = { message: message, filename: filename, lineno: lineno,
+	      type: "callback" }
+  postMessage(obj);
+  return false;
+}
+throw new Error("workerhello");
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -1,16 +1,17 @@
 [DEFAULT]
 support-files =
   bug226361_iframe.xhtml
   bug299673.js
   bug322588-popup.html
   bug426082.html
   bug457672.html
   bug656379-1.html
+  error_event_worker.js
   empty.js
   window_bug493251.html
   window_bug659071.html
   window_wheel_default_action.html
 
 [test_addEventListenerExtraArg.html]
 [test_all_synthetic_events.html]
 [test_bug226361.xhtml]
@@ -125,15 +126,16 @@ skip-if = toolkit == 'android' #CRASH_DU
 [test_dom_keyboard_event.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dom_mouse_event.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dom_wheel_event.html]
 [test_draggableprop.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dragstart.html]
+[test_error_events.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_eventctors.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_focus_disabled.html]
 [test_messageEvent.html]
 [test_moz_mouse_pixel_scroll_event.html]
 [test_wheel_default_action.html]
new file mode 100644
--- /dev/null
+++ b/dom/events/test/test_error_events.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for error events being ErrorEvent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+  var errorEvent;
+  var file;
+  var line;
+  var msg;
+  window.addEventListener("error", function errorListener(e) {
+    window.removeEventListener("error", errorListener);
+    errorEvent = e;
+  });
+  var oldOnerror = window.onerror;
+  window.onerror = function(message, filename, lineno) {
+    window.onerror = oldOnerror;
+    file = filename;
+    line = lineno;
+    msg = message;
+  }
+  throw new Error("hello");
+</script>
+<script>
+  generate_tests(assert_equals, [
+    [ "Event filename", errorEvent.filename, location.href ],
+    [ "Callback filename", file, location.href ],
+    [ "Event line number", errorEvent.lineno, 23 ],
+    [ "Callback line number", line, 23 ],
+    [ "Event message", errorEvent.message, "Error: hello" ],
+    [ "Callback message", msg, "Error: hello" ]
+  ]);
+</script>
+<script>
+  var workerLocation = location.protocol + "//" + location.host +
+    location.pathname.replace("test_error_events.html", "error_event_worker.js");
+  var eventFileTest = async_test("Worker event filename");
+  var eventLineTest = async_test("Worker event line number");
+  var eventMessageTest = async_test("Worker event message");
+  var callbackFileTest = async_test("Worker callback filename");
+  var callbackLineTest = async_test("Worker callback line number");
+  var callbackMessageTest = async_test("Worker callback message");
+  var w = new Worker("error_event_worker.js");
+  w.addEventListener("message", function(msg) {
+    if (msg.data.type == "event") {
+      eventFileTest.step(function() { assert_equals(msg.data.filename, workerLocation); });
+      eventFileTest.done();
+      eventLineTest.step(function() { assert_equals(msg.data.lineno, 15); });
+      eventLineTest.done();
+      eventMessageTest.step(function() { assert_equals(msg.data.message, "Error: workerhello"); });
+      eventMessageTest.done();
+    } else {
+      callbackFileTest.step(function() { assert_equals(msg.data.filename, workerLocation); });
+      callbackFileTest.done();
+      callbackLineTest.step(function() { assert_equals(msg.data.lineno, 15); });
+      callbackLineTest.done();
+      callbackMessageTest.step(function() { assert_equals(msg.data.message, "Error: workerhello"); });
+      callbackMessageTest.done();
+    }
+  });
+</script>
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "IDBRequest.h"
 
 #include "nsIScriptContext.h"
 
 #include "mozilla/ContentEvents.h"
+#include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/IDBOpenDBRequestBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDOMClassInfoID.h"
 #include "nsDOMJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsEventDispatcher.h"
@@ -295,20 +296,20 @@ IDBRequest::CaptureCaller()
     return;
   }
 
   mFilename.Assign(NS_ConvertUTF8toUTF16(filename));
   mLineNo = lineNo;
 }
 
 void
-IDBRequest::FillScriptErrorEvent(InternalScriptErrorEvent* aEvent) const
+IDBRequest::FillScriptErrorEvent(ErrorEventInit& aEventInit) const
 {
-  aEvent->lineNr = mLineNo;
-  aEvent->fileName = mFilename.get();
+  aEventInit.mLineno = mLineNo;
+  aEventInit.mFilename = mFilename;
 }
 
 mozilla::dom::IDBRequestReadyState
 IDBRequest::ReadyState() const
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (IsPending()) {
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -20,16 +20,17 @@
 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
 
 class nsIScriptContext;
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 class OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
+class ErrorEventInit;
 }
 }
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class HelperBase;
 class IDBCursor;
 class IDBFactory;
@@ -96,17 +97,17 @@ public:
   IndexedDBRequestParentBase*
   GetActorParent() const
   {
     return mActorParent;
   }
 
   void CaptureCaller();
 
-  void FillScriptErrorEvent(mozilla::InternalScriptErrorEvent* aEvent) const;
+  void FillScriptErrorEvent(ErrorEventInit& aEventInit) const;
 
   bool
   IsPending() const
   {
     return !mHaveResultOrErrorCode;
   }
 
 #ifdef MOZ_ENABLE_PROFILER_SPS
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -12,16 +12,17 @@
 #include "nsIFileStorage.h"
 #include "nsIObserverService.h"
 #include "nsIScriptError.h"
 
 #include "jsapi.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/CondVar.h"
 #include "mozilla/ContentEvents.h"
+#include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/quota/OriginOrPatternString.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/Utilities.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/Services.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
@@ -335,46 +336,45 @@ IndexedDatabaseManager::FireWindowOnErro
     return ret.ErrorCode();
   }
 
   nsString errorName;
   if (error) {
     error->GetName(errorName);
   }
 
-  mozilla::InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
-  request->FillScriptErrorEvent(&event);
-  NS_ABORT_IF_FALSE(event.fileName,
-                    "FillScriptErrorEvent should give us a non-null string "
-                    "for our error's fileName");
+  ErrorEventInit init;
+  request->FillScriptErrorEvent(init);
 
-  event.errorMsg = errorName.get();
+  init.mMessage = errorName;
+  init.mCancelable = true;
+  init.mBubbles = true;
 
   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aOwner));
   NS_ASSERTION(sgo, "How can this happen?!");
 
   nsEventStatus status = nsEventStatus_eIgnore;
-  if (NS_FAILED(sgo->HandleScriptError(&event, &status))) {
+  if (NS_FAILED(sgo->HandleScriptError(init, &status))) {
     NS_WARNING("Failed to dispatch script error event");
     status = nsEventStatus_eIgnore;
   }
 
   bool preventDefaultCalled = status == nsEventStatus_eConsumeNoDefault;
   if (preventDefaultCalled) {
     return NS_OK;
   }
 
   // Log an error to the error console.
   nsCOMPtr<nsIScriptError> scriptError =
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (NS_FAILED(scriptError->InitWithWindowID(errorName,
-                                              nsDependentString(event.fileName),
-                                              EmptyString(), event.lineNr,
+                                              init.mFilename,
+                                              EmptyString(), init.mLineno,
                                               0, 0,
                                               "IndexedDB",
                                               aOwner->WindowID()))) {
     NS_WARNING("Failed to init script error!");
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIConsoleService> consoleService =
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1181,26 +1181,26 @@ public:
     if (!filename) {
       return false;
     }
 
     // We should not fire error events for warnings but instead make sure that
     // they show up in the error console.
     if (!JSREPORT_IS_WARNING(aFlags)) {
       // First fire an ErrorEvent at the worker.
+      ErrorEventInit init;
+      init.mMessage = aMessage;
+      init.mFilename = aFilename;
+      init.mLineno = aLineNumber;
+      init.mCancelable = true;
+      init.mBubbles = true;
+
       if (aTarget) {
-        ErrorEventInit init;
-        init.mMessage = aMessage;
-        init.mFilename = aFilename;
-        init.mLineno = aLineNumber;
-        init.mCancelable = true;
-
         nsRefPtr<ErrorEvent> event =
           ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
-
         event->SetTrusted(true);
 
         nsEventStatus status = nsEventStatus_eIgnore;
         aTarget->DispatchDOMEvent(nullptr, event, nullptr, &status);
 
         if (status == nsEventStatus_eConsumeNoDefault) {
           return true;
         }
@@ -1214,40 +1214,32 @@ public:
 
         nsEventStatus status = nsEventStatus_eIgnore;
         nsIScriptGlobalObject* sgo;
 
         if (aWorkerPrivate) {
           WorkerGlobalScope* globalTarget = aWorkerPrivate->GlobalScope();
           MOZ_ASSERT(target == globalTarget->GetWrapperPreserveColor());
 
-          // Icky, we have to fire an InternalScriptErrorEvent...
-          MOZ_ASSERT(!NS_IsMainThread());
-          InternalScriptErrorEvent event(true, NS_USER_DEFINED_EVENT);
-          event.lineNr = aLineNumber;
-          event.errorMsg = aMessage.get();
-          event.fileName = aFilename.get();
-          event.typeString = NS_LITERAL_STRING("error");
+          nsRefPtr<ErrorEvent> event =
+            ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
+          event->SetTrusted(true);
 
           nsIDOMEventTarget* target = static_cast<nsIDOMEventTarget*>(globalTarget);
-          if (NS_FAILED(nsEventDispatcher::Dispatch(target, nullptr, &event,
-                                                    nullptr, &status))) {
+          if (NS_FAILED(nsEventDispatcher::DispatchDOMEvent(target, nullptr,
+                                                            event, nullptr,
+                                                            &status))) {
             NS_WARNING("Failed to dispatch worker thread error event!");
             status = nsEventStatus_eIgnore;
           }
         }
         else if ((sgo = nsJSUtils::GetStaticScriptGlobal(target))) {
-          // Icky, we have to fire an InternalScriptErrorEvent...
           MOZ_ASSERT(NS_IsMainThread());
-          InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
-          event.lineNr = aLineNumber;
-          event.errorMsg = aMessage.get();
-          event.fileName = aFilename.get();
-
-          if (NS_FAILED(sgo->HandleScriptError(&event, &status))) {
+
+          if (NS_FAILED(sgo->HandleScriptError(init, &status))) {
             NS_WARNING("Failed to dispatch main thread error event!");
             status = nsEventStatus_eIgnore;
           }
         }
 
         // Was preventDefault() called?
         if (status == nsEventStatus_eConsumeNoDefault) {
           return true;
@@ -3188,23 +3180,25 @@ WorkerPrivateParent<Derived>::BroadcastE
 
     AutoCxPusher autoPush(cx);
 
     nsCOMPtr<nsIScriptGlobalObject> sgo =
       do_QueryInterface(windowAction.mWindow);
     MOZ_ASSERT(sgo);
 
     MOZ_ASSERT(NS_IsMainThread());
-    InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
-    event.lineNr = aLineNumber;
-    event.errorMsg = aMessage.BeginReading();
-    event.fileName = aFilename.BeginReading();
+    ErrorEventInit init;
+    init.mLineno = aLineNumber;
+    init.mFilename = aFilename;
+    init.mMessage = aMessage;
+    init.mCancelable = true;
+    init.mBubbles = true;
 
     nsEventStatus status = nsEventStatus_eIgnore;
-    rv = sgo->HandleScriptError(&event, &status);
+    rv = sgo->HandleScriptError(init, &status);
     if (NS_FAILED(rv)) {
       Throw(cx, rv);
       JS_ReportPendingException(cx);
       continue;
     }
 
     if (status == nsEventStatus_eConsumeNoDefault) {
       shouldLogErrorToConsole = false;
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -44,17 +44,16 @@ enum nsEventStructType
   NS_POINTER_EVENT,                  // PointerEvent
 
   // TouchEvents.h
   NS_GESTURENOTIFY_EVENT,            // WidgetGestureNotifyEvent
   NS_SIMPLE_GESTURE_EVENT,           // WidgetSimpleGestureEvent
   NS_TOUCH_EVENT,                    // WidgetTouchEvent
 
   // ContentEvents.h
-  NS_SCRIPT_ERROR_EVENT,             // InternalScriptErrorEvent
   NS_SCROLLPORT_EVENT,               // InternalScrollPortEvent
   NS_SCROLLAREA_EVENT,               // InternalScrollAreaEvent
   NS_FORM_EVENT,                     // InternalFormEvent
   NS_FOCUS_EVENT,                    // InternalFocusEvent
   NS_CLIPBOARD_EVENT,                // InternalClipboardEvent
   NS_TRANSITION_EVENT,               // InternalTransitionEvent
   NS_ANIMATION_EVENT,                // InternalAnimationEvent
 
--- a/widget/ContentEvents.h
+++ b/widget/ContentEvents.h
@@ -15,65 +15,16 @@
 #include "nsRect.h"
 #include "nsStringGlue.h"
 
 class nsIContent;
 
 namespace mozilla {
 
 /******************************************************************************
- * mozilla::InternalScriptErrorEvent
- ******************************************************************************/
-
-class InternalScriptErrorEvent : public WidgetEvent
-{
-public:
-  virtual InternalScriptErrorEvent* AsScriptErrorEvent() MOZ_OVERRIDE
-  {
-    return this;
-  }
-
-  InternalScriptErrorEvent(bool aIsTrusted, uint32_t aMessage) :
-    WidgetEvent(aIsTrusted, aMessage, NS_SCRIPT_ERROR_EVENT),
-    lineNr(0), errorMsg(nullptr), fileName(nullptr)
-  {
-  }
-
-  virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
-  {
-    MOZ_ASSERT(eventStructType == NS_SCRIPT_ERROR_EVENT,
-               "Duplicate() must be overridden by sub class");
-    InternalScriptErrorEvent* result =
-      new InternalScriptErrorEvent(false, message);
-    result->AssignScriptErrorEventData(*this, true);
-    result->mFlags = mFlags;
-    return result;
-  }
-
-
-  int32_t           lineNr;
-  const char16_t*  errorMsg;
-  const char16_t*  fileName;
-
-  // XXX Not tested by test_assign_event_data.html
-  void AssignScriptErrorEventData(const InternalScriptErrorEvent& aEvent,
-                                  bool aCopyTargets)
-  {
-    AssignEventData(aEvent, aCopyTargets);
-
-    lineNr = aEvent.lineNr;
-
-    // We don't copy errorMsg and fileName.  If it's necessary, perhaps, this
-    // should duplicate the characters and free them at destructing.
-    errorMsg = nullptr;
-    fileName = nullptr;
-  }
-};
-
-/******************************************************************************
  * mozilla::InternalScrollPortEvent
  ******************************************************************************/
 
 class InternalScrollPortEvent : public WidgetGUIEvent
 {
 public:
   virtual InternalScrollPortEvent* AsScrollPortEvent() MOZ_OVERRIDE
   {
--- a/widget/EventClassList.h
+++ b/widget/EventClassList.h
@@ -36,17 +36,16 @@ NS_EVENT_CLASS(Widget, WheelEvent)
 NS_EVENT_CLASS(Widget, PointerEvent)
 
 // TouchEvents.h
 NS_EVENT_CLASS(Widget, GestureNotifyEvent)
 NS_EVENT_CLASS(Widget, SimpleGestureEvent)
 NS_EVENT_CLASS(Widget, TouchEvent)
 
 // ContentEvents.h
-NS_EVENT_CLASS(Internal, ScriptErrorEvent)
 NS_EVENT_CLASS(Internal, ScrollPortEvent)
 NS_EVENT_CLASS(Internal, ScrollAreaEvent)
 NS_EVENT_CLASS(Internal, FormEvent)
 NS_EVENT_CLASS(Internal, ClipboardEvent)
 NS_EVENT_CLASS(Internal, FocusEvent)
 NS_EVENT_CLASS(Internal, TransitionEvent)
 NS_EVENT_CLASS(Internal, AnimationEvent)
 
--- a/widget/tests/test_assign_event_data.html
+++ b/widget/tests/test_assign_event_data.html
@@ -69,27 +69,16 @@ function onEvent(aEvent)
         typeof(aEvent[attr]) != "function") {
       gCopiedEvent.push({ name: attr, value: aEvent[attr]});
     }
   }
   setTimeout(gCallback, 0);
 }
 
 const kTests = [
-  { description: "InternalScriptErrorEvent",
-    targetID: "input-text", eventType: "error",
-    dispatchEvent: function () {
-      return;
-    },
-    canRun: function () {
-      todo(false, "InternalScriptErrorEvent isn't tested");
-      return false;
-    },
-    todoMismatch: [],
-  },
   { description: "InternalScrollPortEvent (overflow, vertical)",
     targetID: "scrollable-div", eventType: "overflow",
     dispatchEvent: function () {
       document.getElementById("scrolled-div").style.height = "500px";
     },
     canRun: function () {
       return true;
     },