Bug 1550937. Stop using [array] in nsIEventListenerService. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Sat, 11 May 2019 08:28:29 +0000
changeset 532359 6103006e3172f0ef258a30256b8cc7a6553e7f14
parent 532358 08eb61c337951a2f136faa08b029e34234aae08b
child 532360 d51f3432e142ef24333b125087f5fccc2fbc366a
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1550937
milestone68.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 1550937. Stop using [array] in nsIEventListenerService. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D30773
dom/events/EventListenerManager.cpp
dom/events/EventListenerManager.h
dom/events/EventListenerService.cpp
dom/events/nsIEventListenerService.idl
dom/events/test/test_bug448602.html
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -28,17 +28,16 @@
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/TimelineConsumers.h"
 #include "mozilla/EventTimelineMarker.h"
 #include "mozilla/TimeStamp.h"
 
 #include "EventListenerService.h"
-#include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsDOMCID.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
 #include "nsIContentSecurityPolicy.h"
 #include "mozilla/dom/Document.h"
@@ -1455,20 +1454,20 @@ bool EventListenerManager::HasListenersF
   return false;
 }
 
 bool EventListenerManager::HasListeners() const {
   return !mListeners.IsEmpty();
 }
 
 nsresult EventListenerManager::GetListenerInfo(
-    nsCOMArray<nsIEventListenerInfo>* aList) {
+    nsTArray<RefPtr<nsIEventListenerInfo>>& aList) {
   nsCOMPtr<EventTarget> target = mTarget;
   NS_ENSURE_STATE(target);
-  aList->Clear();
+  aList.Clear();
   nsAutoTObserverArray<Listener, 2>::ForwardIterator iter(mListeners);
   while (iter.HasMore()) {
     const Listener& listener = iter.GetNext();
     // If this is a script handler and we haven't yet
     // compiled the event handler itself go ahead and compile it
     if (listener.mListenerType == Listener::eJSEventListener &&
         listener.mHandlerIsString) {
       CompileEventHandlerInternal(const_cast<Listener*>(&listener), nullptr,
@@ -1505,17 +1504,17 @@ nsresult EventListenerManager::GetListen
         // which have been destroyed.
         continue;
       }
     }
 
     RefPtr<EventListenerInfo> info = new EventListenerInfo(
         eventType, callback, callbackGlobal, listener.mFlags.mCapture,
         listener.mFlags.mAllowUntrustedEvents, listener.mFlags.mInSystemGroup);
-    aList->AppendElement(info.forget());
+    aList.AppendElement(info.forget());
   }
   return NS_OK;
 }
 
 bool EventListenerManager::HasUnloadListeners() {
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
     Listener* listener = &mListeners.ElementAt(i);
--- a/dom/events/EventListenerManager.h
+++ b/dom/events/EventListenerManager.h
@@ -11,27 +11,25 @@
 #include "mozilla/dom/EventListenerBinding.h"
 #include "mozilla/JSEventHandler.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMEventListener.h"
 #include "nsTObserverArray.h"
+#include "nsTArray.h"
 
 class nsIDocShell;
 class nsIEventListenerInfo;
 class nsPIDOMWindowInner;
 class JSTracer;
 
 struct EventTypeData;
 
-template <class T>
-class nsCOMArray;
-
 namespace mozilla {
 
 class ELMCreationDetector;
 class EventListenerManager;
 
 namespace dom {
 class Event;
 class EventTarget;
@@ -397,17 +395,17 @@ class EventListenerManager final : publi
    * Returns true if there is at least one event listener.
    */
   bool HasListeners() const;
 
   /**
    * Sets aList to the list of nsIEventListenerInfo objects representing the
    * listeners managed by this listener manager.
    */
-  nsresult GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList);
+  nsresult GetListenerInfo(nsTArray<RefPtr<nsIEventListenerInfo>>& aList);
 
   uint32_t GetIdentifierForEvent(nsAtom* aEvent);
 
   /**
    * Returns true if there may be a paint event listener registered,
    * false if there definitely isn't.
    */
   bool MayHavePaintEventListener() { return mMayHavePaintEventListener; }
--- a/dom/events/EventListenerService.cpp
+++ b/dom/events/EventListenerService.cpp
@@ -192,65 +192,41 @@ EventListenerService::EventListenerServi
 }
 
 EventListenerService::~EventListenerService() {
   MOZ_ASSERT(sInstance == this);
   sInstance = nullptr;
 }
 
 NS_IMETHODIMP
-EventListenerService::GetListenerInfoFor(EventTarget* aEventTarget,
-                                         uint32_t* aCount,
-                                         nsIEventListenerInfo*** aOutArray) {
+EventListenerService::GetListenerInfoFor(
+    EventTarget* aEventTarget,
+    nsTArray<RefPtr<nsIEventListenerInfo>>& aOutArray) {
   NS_ENSURE_ARG_POINTER(aEventTarget);
-  *aCount = 0;
-  *aOutArray = nullptr;
-  nsCOMArray<nsIEventListenerInfo> listenerInfos;
 
   EventListenerManager* elm = aEventTarget->GetExistingListenerManager();
   if (elm) {
-    elm->GetListenerInfo(&listenerInfos);
+    elm->GetListenerInfo(aOutArray);
   }
 
-  int32_t count = listenerInfos.Count();
-  if (count == 0) {
-    return NS_OK;
-  }
-
-  listenerInfos.Forget(aOutArray);
-  *aCount = count;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-EventListenerService::GetEventTargetChainFor(EventTarget* aEventTarget,
-                                             bool aComposed, uint32_t* aCount,
-                                             EventTarget*** aOutArray) {
-  *aCount = 0;
-  *aOutArray = nullptr;
+EventListenerService::GetEventTargetChainFor(
+    EventTarget* aEventTarget, bool aComposed,
+    nsTArray<RefPtr<EventTarget>>& aOutArray) {
   NS_ENSURE_ARG(aEventTarget);
   WidgetEvent event(true, eVoidEvent);
   event.SetComposed(aComposed);
   nsTArray<EventTarget*> targets;
   nsresult rv = EventDispatcher::Dispatch(aEventTarget, nullptr, &event,
                                           nullptr, nullptr, nullptr, &targets);
   NS_ENSURE_SUCCESS(rv, rv);
-  int32_t count = targets.Length();
-  if (count == 0) {
-    return NS_OK;
-  }
-
-  *aOutArray =
-      static_cast<EventTarget**>(moz_xmalloc(sizeof(EventTarget*) * count));
-
-  for (int32_t i = 0; i < count; ++i) {
-    NS_ADDREF((*aOutArray)[i] = targets[i]);
-  }
-  *aCount = count;
-
+  aOutArray.AppendElements(targets);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 EventListenerService::HasListenersFor(EventTarget* aEventTarget,
                                       const nsAString& aType, bool* aRetVal) {
   NS_ENSURE_TRUE(aEventTarget, NS_ERROR_UNEXPECTED);
 
--- a/dom/events/nsIEventListenerService.idl
+++ b/dom/events/nsIEventListenerService.idl
@@ -61,34 +61,28 @@ interface nsIEventListenerInfo : nsISupp
 
 [scriptable, uuid(77aab5f7-213d-4db4-9f22-e46dfb774f15)]
 interface nsIEventListenerService : nsISupports
 {
   /**
    * Returns an array of nsIEventListenerInfo objects.
    * If aEventTarget doesn't have any listeners, this returns null.
    */
-  void getListenerInfoFor(in EventTarget aEventTarget,
-                          [optional] out unsigned long aCount,
-                          [retval, array, size_is(aCount)] out
-                            nsIEventListenerInfo aOutArray);
+  Array<nsIEventListenerInfo> getListenerInfoFor(in EventTarget aEventTarget);
 
   /**
    * Returns an array of event targets.
    * aEventTarget will be at index 0.
    * The objects are the ones that would be used as DOMEvent.currentTarget while
    * dispatching an event to aEventTarget
    * @note Some events, especially 'load', may actually have a shorter
    *       event target chain than what this methods returns.
    */
-  void getEventTargetChainFor(in EventTarget aEventTarget,
-                              in boolean composed,
-                              [optional] out unsigned long aCount,
-                              [retval, array, size_is(aCount)] out
-                                EventTarget aOutArray);
+  Array<EventTarget> getEventTargetChainFor(in EventTarget aEventTarget,
+                                            in boolean composed);
 
   /**
    * Returns true if a event target has any listener for the given type.
    */
   boolean hasListenersFor(in EventTarget aEventTarget,
                           in AString aType);
 
   /**
--- a/dom/events/test/test_bug448602.html
+++ b/dom/events/test/test_bug448602.html
@@ -22,47 +22,47 @@ https://bugzilla.mozilla.org/show_bug.cg
 var els, root, l2, l3;
 
 function runTests() {
   els = SpecialPowers.Cc["@mozilla.org/eventlistenerservice;1"]
                      .getService(SpecialPowers.Ci.nsIEventListenerService);
 
   // Event listener info tests
   root = document.getElementById("testroot");
-  var infos = els.getListenerInfoFor(root, {});
+  var infos = els.getListenerInfoFor(root);
   is(infos.length, 0, "Element shouldn't have listeners (1)");
 
   var listenerSource = 'alert(event);';
   root.setAttribute("onclick", listenerSource);
-  infos = els.getListenerInfoFor(root, {});
+  infos = els.getListenerInfoFor(root);
   is(infos.length, 1, "Element should have listeners (1)");
   is(infos[0].toSource(), 'function onclick(event) {\n' + listenerSource + '\n}',
      "Unexpected serialization (1)");
   is(infos[0].type, "click", "Wrong type (1)");
   is(infos[0].capturing, false, "Wrong phase (1)");
   is(infos[0].allowsUntrusted, true, "Should allow untrusted events (1)");
   is(SpecialPowers.unwrap(infos[0].listenerObject), root.onclick,
      "Should have the right listener object (1)");
 
   root.removeAttribute("onclick");
   root.setAttribute("onclick", "...invalid script...");
   SimpleTest.expectUncaughtException(true);
-  infos = els.getListenerInfoFor(root, {});
+  infos = els.getListenerInfoFor(root);
   SimpleTest.expectUncaughtException(false);
   is(infos.length, 1);
   is(infos[0].listenerObject, null);
 
   root.removeAttribute("onclick");
-  infos = els.getListenerInfoFor(root, {});
+  infos = els.getListenerInfoFor(root);
   is(infos.length, 0, "Element shouldn't have listeners (2)");
 
   var l = function (e) { alert(e); };
   root.addEventListener("foo", l, true, true);
   root.addEventListener("foo", l, false, false);
-  infos = els.getListenerInfoFor(root, {});
+  infos = els.getListenerInfoFor(root);
   is(infos.length, 2, "Element should have listeners (2)");
   is(infos[0].toSource(), "(function (e) { alert(e); })",
      "Unexpected serialization (2)");
   is(infos[0].type, "foo", "Wrong type (2)");
   is(infos[0].capturing, true, "Wrong phase (2)");
   is(infos[0].allowsUntrusted, true, "Should allow untrusted events (2)");
   is(SpecialPowers.unwrap(infos[0].listenerObject), l,
      "Should have the right listener object (2)");
@@ -71,35 +71,35 @@ function runTests() {
   is(infos[1].type, "foo", "Wrong type (3)");
   is(infos[1].capturing, false, "Wrong phase (3)");
   is(infos[1].allowsUntrusted, false, "Shouldn't allow untrusted events (1)");
   is(SpecialPowers.unwrap(infos[1].listenerObject), l,
      "Should have the right listener object (3)");
 
   root.removeEventListener("foo", l, true);
   root.removeEventListener("foo", l);
-  infos = els.getListenerInfoFor(root, {});
+  infos = els.getListenerInfoFor(root);
   is(infos.length, 0, "Element shouldn't have listeners (3)");
 
   root.onclick = l;
-  infos = els.getListenerInfoFor(root, {});
+  infos = els.getListenerInfoFor(root);
   is(infos.length, 1, "Element should have listeners (3)");
   is(infos[0].toSource(), '(function (e) { alert(e); })',
      "Unexpected serialization (4)");
   is(infos[0].type, "click", "Wrong type (4)");
   is(infos[0].capturing, false, "Wrong phase (4)");
   is(infos[0].allowsUntrusted, true, "Should allow untrusted events (3)");
   is(SpecialPowers.unwrap(infos[0].listenerObject), l,
      "Should have the right listener object (4)");
 
   // Event target chain tests
   l2 = document.getElementById("testlevel2");
   l3 = document.getElementById("testlevel3");
   var textnode = l3.firstChild;
-  var chain = els.getEventTargetChainFor(textnode, true, {});
+  var chain = els.getEventTargetChainFor(textnode, true);
   ok(chain.length > 3, "Too short event target chain.");
   ok(SpecialPowers.compare(chain[0], textnode), "Wrong chain item (1)");
   ok(SpecialPowers.compare(chain[1], l3), "Wrong chain item (2)");
   ok(SpecialPowers.compare(chain[2], l2), "Wrong chain item (3)");
   ok(SpecialPowers.compare(chain[3], root), "Wrong chain item (4)");
 
   var hasDocumentInChain = false;
   var hasWindowInChain = false;
@@ -110,17 +110,17 @@ function runTests() {
       hasWindowInChain = true;
     }
   }
 
   ok(hasDocumentInChain, "Should have document in event target chain!");
   ok(hasWindowInChain, "Should have window in event target chain!");
 
   try {
-    els.getListenerInfoFor(null, {});
+    els.getListenerInfoFor(null);
     ok(false, "Should have thrown an exception.");
   } catch (ex) {
     ok(true, "We should be still running.");
   }
   setTimeout(testAllListener, 0);
 }
 
 function dispatchTrusted(t, o) {