Bug 972312 part 2. Get rid of InternalScriptErrorEvent and just use mozilla::dom::ErrorEvent for the cases that used to use it. r=smaug,khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Sun, 23 Feb 2014 00:01:12 -0500
changeset 187455 73abdca84f678c3bd0da5163299206dd330f2821
parent 187454 b1851a02b1cab36969b9c2770648c8e39ea201a8
child 187456 3cc8da2bf7467e2c44f8b46343a17f1778cf4998
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, khuey
bugs972312
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 972312 part 2. Get rid of InternalScriptErrorEvent and just use mozilla::dom::ErrorEvent for the cases that used to use it. r=smaug,khuey
dom/base/nsIScriptGlobalObject.h
dom/base/nsJSEnvironment.cpp
dom/events/moz.build
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 {
+struct 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/moz.build
+++ b/dom/events/moz.build
@@ -53,47 +53,58 @@ UNIFIED_SOURCES += [
     'nsDOMBeforeUnloadEvent.cpp',
     'nsDOMClipboardEvent.cpp',
     'nsDOMCommandEvent.cpp',
     'nsDOMCompositionEvent.cpp',
     'nsDOMDataContainerEvent.cpp',
     'nsDOMDataTransfer.cpp',
     'nsDOMDeviceMotionEvent.cpp',
     'nsDOMDragEvent.cpp',
-    'nsDOMEvent.cpp',
     'nsDOMEventTargetHelper.cpp',
     'nsDOMFocusEvent.cpp',
     'nsDOMKeyboardEvent.cpp',
     'nsDOMMessageEvent.cpp',
     'nsDOMMouseEvent.cpp',
     'nsDOMMouseScrollEvent.cpp',
     'nsDOMMutationEvent.cpp',
     'nsDOMNotifyAudioAvailableEvent.cpp',
-    'nsDOMNotifyPaintEvent.cpp',
-    'nsDOMScrollAreaEvent.cpp',
     'nsDOMSimpleGestureEvent.cpp',
     'nsDOMTextEvent.cpp',
     'nsDOMTouchEvent.cpp',
     'nsDOMTransitionEvent.cpp',
-    'nsDOMUIEvent.cpp',
     'nsDOMXULCommandEvent.cpp',
     'nsEventDispatcher.cpp',
-    'nsEventListenerManager.cpp',
     'nsEventListenerService.cpp',
     'nsIMEStateManager.cpp',
     'nsJSEventListener.cpp',
     'nsPaintRequest.cpp',
     'nsPrivateTextRange.cpp',
     'PointerEvent.cpp',
     'TextComposition.cpp',
     'Touch.cpp',
 ]
 
-# nsEventStateManager.cpp should be built separately because of Mac OS X headers.
 SOURCES += [
+    # nsDOMEvent.cpp should be built separately because it includes
+    # ipc/IPCMessageUtils.h, which on Windows includes windows.h.
+    'nsDOMEvent.cpp',
+    # nsDOMEvent.cpp should be built separately because it includes
+    # ipc/IPCMessageUtils.h, which on Windows includes windows.h.
+    'nsDOMNotifyPaintEvent.cpp',
+    # nsDOMEvent.cpp should be built separately because it includes
+    # ipc/IPCMessageUtils.h, which on Windows includes windows.h.
+    'nsDOMScrollAreaEvent.cpp',
+    # nsDOMEvent.cpp should be built separately because it includes
+    # ipc/IPCMessageUtils.h, which on Windows includes windows.h.
+    'nsDOMUIEvent.cpp',
+    # nsDOMEvent.cpp should be built separately because it includes
+    # mozilla/HalSensor.h, which includes ipc/IPCMessageUtils.h, which
+    # on Windows includes windows.h.
+    'nsEventListenerManager.cpp',
+    # nsEventStateManager.cpp should be built separately because of Mac OS X headers.
     'nsEventStateManager.cpp',
 ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     UNIFIED_SOURCES += ['SpeechRecognitionError.cpp']
 
 FAIL_ON_WARNINGS = True
 
--- 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"
@@ -37,16 +38,17 @@ namespace {
 #ifdef MOZ_ENABLE_PROFILER_SPS
 uint64_t gNextRequestSerialNumber = 1;
 #endif
 
 } // anonymous namespace
 
 USING_INDEXEDDB_NAMESPACE
 using mozilla::dom::OwningIDBObjectStoreOrIDBIndexOrIDBCursor;
+using mozilla::dom::ErrorEventInit;
 using namespace mozilla;
 
 IDBRequest::IDBRequest(IDBDatabase* aDatabase)
 : IDBWrapperCache(aDatabase),
   mResultVal(JSVAL_VOID),
   mActorParent(nullptr),
 #ifdef MOZ_ENABLE_PROFILER_SPS
   mSerialNumber(gNextRequestSerialNumber++),
@@ -295,20 +297,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;
     },