Bug 949722 - Assigning to '.onerror' of XHR appends an event listener, rather than overwriting it (only in workers). r=khuey, a=lsblakk
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Sat, 21 Dec 2013 02:22:13 +0200
changeset 175536 5a1f8b015361e6e87213a0f7229ba523f3572ab0
parent 175535 35e2fe893f945fb0df758e6e0c0214b9073a5933
child 175537 b71255e32a12433b7b65e77bb41b97d1db3f2d40
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey, lsblakk
bugs949722
milestone28.0a2
Bug 949722 - Assigning to '.onerror' of XHR appends an event listener, rather than overwriting it (only in workers). r=khuey, a=lsblakk
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
dom/src/events/nsJSEventListener.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/test/errorwarning_worker.js
dom/workers/test/xhr_worker.js
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -521,18 +521,17 @@ nsEventListenerManager::ListenerCanHandl
     return true;
   }
   if (aEvent->message == NS_USER_DEFINED_EVENT) {
     if (mIsMainThreadELM) {
       return aLs->mTypeAtom == aEvent->userType;
     }
     return aLs->mTypeString.Equals(aEvent->typeString);
   }
-  MOZ_ASSERT_IF(aEvent->eventStructType != NS_SCRIPT_ERROR_EVENT,
-                mIsMainThreadELM);
+  MOZ_ASSERT(mIsMainThreadELM);
   return aLs->mEventType == aEvent->message;
 }
 
 void
 nsEventListenerManager::AddEventListenerByType(const EventListenerHolder& aListener, 
                                                const nsAString& aType,
                                                const EventListenerFlags& aFlags)
 {
@@ -591,21 +590,16 @@ nsEventListenerManager::SetEventHandlerI
     // If we didn't find a script listener or no listeners existed
     // create and add a new one.
     EventListenerFlags flags;
     flags.mListenerIsJSListener = true;
 
     nsCOMPtr<nsIJSEventListener> scriptListener;
     NS_NewJSEventListener(aScopeObject, mTarget, aName,
                           aHandler, getter_AddRefs(scriptListener));
-
-    if (!aName && aTypeString.EqualsLiteral("error")) {
-      eventType = NS_LOAD_ERROR;
-    }
-
     EventListenerHolder holder(scriptListener);
     AddEventListenerInternal(holder, eventType, aName, aTypeString, flags,
                              true);
 
     ls = FindEventHandler(eventType, aName, aTypeString);
   } else {
     nsIJSEventListener* scriptListener = ls->GetJSListener();
     MOZ_ASSERT(scriptListener,
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -482,17 +482,17 @@ public:
     return handler ? handler->EventHandler() : nullptr;
   }
   mozilla::dom::OnErrorEventHandlerNonNull* GetOnErrorEventHandler()
   {
     const nsEventHandler* handler;
     if (mIsMainThreadELM) {
       handler = GetEventHandlerInternal(nsGkAtoms::onerror, EmptyString());
     } else {
-      handler = GetEventHandlerInternal(nullptr, NS_LITERAL_STRING("onerror"));
+      handler = GetEventHandlerInternal(nullptr, NS_LITERAL_STRING("error"));
     }
     return handler ? handler->OnErrorEventHandler() : nullptr;
   }
   mozilla::dom::OnBeforeUnloadEventHandlerNonNull* GetOnBeforeUnloadEventHandler()
   {
     const nsEventHandler* handler =
       GetEventHandlerInternal(nsGkAtoms::onbeforeunload, EmptyString());
     return handler ? handler->OnBeforeUnloadEventHandler() : nullptr;
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -164,17 +164,19 @@ nsJSEventListener::HandleEvent(nsIDOMEve
     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) {
+    if (scriptEvent &&
+        (scriptEvent->message == NS_LOAD_ERROR ||
+         scriptEvent->typeString.EqualsLiteral("error"))) {
       errorMsg = scriptEvent->errorMsg;
       msgOrEvent.SetAsString() = static_cast<nsAString*>(&errorMsg);
 
       file = scriptEvent->fileName;
       fileName = &file;
 
       lineNumber.Construct();
       lineNumber.Value() = scriptEvent->lineNr;
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1211,31 +1211,33 @@ 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...
-          InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
+          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");
 
           nsIDOMEventTarget* target = static_cast<nsIDOMEventTarget*>(globalTarget);
           if (NS_FAILED(nsEventDispatcher::Dispatch(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))) {
             NS_WARNING("Failed to dispatch main thread error event!");
             status = nsEventStatus_eIgnore;
@@ -3117,16 +3119,17 @@ WorkerPrivateParent<Derived>::BroadcastE
     JSContext* cx = windowAction.mJSContext;
 
     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();
 
     nsEventStatus status = nsEventStatus_eIgnore;
     rv = sgo->HandleScriptError(&event, &status);
     if (NS_FAILED(rv)) {
--- a/dom/workers/test/errorwarning_worker.js
+++ b/dom/workers/test/errorwarning_worker.js
@@ -31,8 +31,12 @@ onmessage = function(event) {
     }
 
   } else {
     postMessage({ type: 'finish' });
   }
 }
 
 onerror = errorHandler;
+onerror = onerror;
+if (!onerror || onerror != onerror) {
+  throw "onerror wasn't set properly";
+}
--- a/dom/workers/test/xhr_worker.js
+++ b/dom/workers/test/xhr_worker.js
@@ -24,24 +24,28 @@ xhr.onload = onload;
 xhr.addEventListener("load", onload, false);
 xhr.removeEventListener("load", onload, false);
 if (!xhr.onload) {
   var message = { type: "error",
                   error: "Lost message listener!" };
   postMessage(message);
 }
 
-xhr.addEventListener("error", function(event) {
+xhr.onerror = function(event) {
   if (event.target != xhr) {
     throw "onerror event.target != xhr";
   }
   var message = { type: "error",
                   error: event.target.status };
   postMessage(message);
-}, false);
+};
+xhr.onerror = xhr.onerror;
+if (!xhr.onerror || xhr.onerror != xhr.onerror) {
+  throw "onerror wasn't set properly";
+}
 
 function onprogress(event) {
   if (event.target != xhr) {
     throw "onprogress event.target != xhr";
   }
   var message = { type: "progress",
                   current: event.loaded,
                   total: event.total };