Bug 814026, r=mrbkap.
authorBen Turner <bent.mozilla@gmail.com>
Tue, 18 Dec 2012 08:01:42 -0800
changeset 125482 fd8fd1a7aecd8b8242bccf77ae48a19df5ee6fe4
parent 125481 dd277d439d313b477f4809c20783668478c3ecd7
child 125483 e1427a1f27c4d62cfa70aac8b64a2831db4b8af6
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs814026
milestone20.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 814026, r=mrbkap.
dom/workers/EventListenerManager.cpp
--- a/dom/workers/EventListenerManager.cpp
+++ b/dom/workers/EventListenerManager.cpp
@@ -4,16 +4,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "EventListenerManager.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/Vector.h"
 #include "mozilla/Util.h"
+#include "nsAutoJSValHolder.h"
 
 #include "Events.h"
 #include "EventTarget.h"
 
 using namespace mozilla::dom;
 USING_WORKERS_NAMESPACE
 using mozilla::ErrorResult;
 
@@ -327,29 +328,43 @@ EventListenerManager::DispatchEvent(JSCo
   ListenerCollection* collection =
     GetCollectionForType(&mCollectionHead,
                          INTERNED_STRING_TO_JSID(aCx, eventType));
   if (!collection) {
     return false;
   }
 
   ContextAllocPolicy ap(aCx);
-  js::Vector<JSObject*, 10, ContextAllocPolicy> listeners(ap);
+
+  // XXXbent There is no reason to use nsAutoJSValHolder here as we should be
+  //         able to use js::AutoValueVector. Worse, nsAutoJSValHolder is much
+  //         slower. However, js::AutoValueVector causes crashes on Android at
+  //         the moment so we don't have much choice.
+  js::Vector<nsAutoJSValHolder, 10, ContextAllocPolicy> listeners(ap);
 
   for (PRCList* elem = PR_NEXT_LINK(&collection->mListenerHead);
        elem != &collection->mListenerHead;
        elem = PR_NEXT_LINK(elem)) {
     ListenerData* listenerData = static_cast<ListenerData*>(elem);
 
     // Listeners that don't want untrusted events will be skipped if this is an
     // untrusted event.
-    if ((eventIsTrusted || listenerData->mWantsUntrusted) &&
-        !listeners.append(listenerData->mListener)) {
-      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-      return false;
+    if (eventIsTrusted || listenerData->mWantsUntrusted) {
+      nsAutoJSValHolder holder;
+      if (!holder.Hold(aCx)) {
+        aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+        return false;
+      }
+
+      holder = listenerData->mListener;
+
+      if (!listeners.append(holder)) {
+        aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+        return false;
+      }
     }
   }
 
   if (listeners.empty()) {
     return false;
   }
 
   SetEventTarget(aEvent, aTarget.GetJSObject());
@@ -360,17 +375,17 @@ EventListenerManager::DispatchEvent(JSCo
     }
 
     // If anything fails in here we want to report the exception and continue on
     // to the next listener rather than bailing out. If something fails and
     // does not set an exception then we bail out entirely as we've either run
     // out of memory or the operation callback has indicated that we should
     // stop running.
 
-    jsval listenerVal = OBJECT_TO_JSVAL(listeners[index]);
+    jsval listenerVal = listeners[index];
 
     JSObject* listenerObj;
     if (!JS_ValueToObject(aCx, listenerVal, &listenerObj)) {
       if (!JS_ReportPendingException(aCx)) {
         aRv.Throw(NS_ERROR_FAILURE);
         return false;
       }
       continue;