Bug 981261 part.2 Rename nsListenerStruct to nsEventListenerManager::Listener r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 17 Mar 2014 15:56:51 +0900
changeset 192078 95a8536c310a983b1e35fb10660d5ec1b13a3975
parent 192077 b604111dc9d686f1bb2033a30523e9b8843dda28
child 192079 4166d9d87a057565e674ea5b2361d7be613e49ca
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs981261
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 981261 part.2 Rename nsListenerStruct to nsEventListenerManager::Listener r=smaug
dom/events/nsEventListenerManager.cpp
dom/events/nsEventListenerManager.h
--- a/dom/events/nsEventListenerManager.cpp
+++ b/dom/events/nsEventListenerManager.cpp
@@ -140,17 +140,17 @@ nsEventListenerManager::Shutdown()
   Event::Shutdown();
 }
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsEventListenerManager, Release)
 
 inline void
 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
-                            nsListenerStruct& aField,
+                            nsEventListenerManager::Listener& aField,
                             const char* aName,
                             unsigned aFlags)
 {
   if (MOZ_UNLIKELY(aCallback.WantDebugInfo())) {
     nsAutoCString name;
     name.AppendASCII(aName);
     if (aField.mTypeAtom) {
       name.AppendASCII(" event=");
@@ -221,54 +221,56 @@ nsEventListenerManager::AddEventListener
   if (!aListener || mClearingListeners) {
     return;
   }
 
   // Since there is no public API to call us with an EventListenerHolder, we
   // know that there's an EventListenerHolder on the stack holding a strong ref
   // to the listener.
 
-  nsListenerStruct* ls;
+  Listener* listener;
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; i++) {
-    ls = &mListeners.ElementAt(i);
+    listener = &mListeners.ElementAt(i);
     // mListener == aListener is the last one, since it can be a bit slow.
-    if (ls->mListenerIsHandler == aHandler &&
-        ls->mFlags == aFlags &&
-        EVENT_TYPE_EQUALS(ls, aType, aTypeAtom, aTypeString, aAllEvents) &&
-        ls->mListener == aListener) {
+    if (listener->mListenerIsHandler == aHandler &&
+        listener->mFlags == aFlags &&
+        EVENT_TYPE_EQUALS(listener, aType, aTypeAtom, aTypeString,
+                          aAllEvents) &&
+        listener->mListener == aListener) {
       return;
     }
   }
 
   mNoListenerForEvent = NS_EVENT_NULL;
   mNoListenerForEventAtom = nullptr;
 
-  ls = aAllEvents ? mListeners.InsertElementAt(0) : mListeners.AppendElement();
-  ls->mListener = aListener;
+  listener = aAllEvents ? mListeners.InsertElementAt(0) :
+                          mListeners.AppendElement();
+  listener->mListener = aListener;
   MOZ_ASSERT(aType < PR_UINT16_MAX);
-  ls->mEventType = aType;
-  ls->mTypeString = aTypeString;
-  ls->mTypeAtom = aTypeAtom;
-  ls->mFlags = aFlags;
-  ls->mListenerIsHandler = aHandler;
-  ls->mHandlerIsString = false;
-  ls->mAllEvents = aAllEvents;
+  listener->mEventType = aType;
+  listener->mTypeString = aTypeString;
+  listener->mTypeAtom = aTypeAtom;
+  listener->mFlags = aFlags;
+  listener->mListenerIsHandler = aHandler;
+  listener->mHandlerIsString = false;
+  listener->mAllEvents = aAllEvents;
 
   // Detect the type of event listener.
   nsCOMPtr<nsIXPConnectWrappedJS> wjs;
   if (aFlags.mListenerIsJSListener) {
     MOZ_ASSERT(!aListener.HasWebIDLCallback());
-    ls->mListenerType = eJSEventListener;
+    listener->mListenerType = eJSEventListener;
   } else if (aListener.HasWebIDLCallback()) {
-    ls->mListenerType = eWebIDLListener;
+    listener->mListenerType = eWebIDLListener;
   } else if ((wjs = do_QueryInterface(aListener.GetXPCOMCallback()))) {
-    ls->mListenerType = eWrappedJSListener;
+    listener->mListenerType = eWrappedJSListener;
   } else {
-    ls->mListenerType = eNativeListener;
+    listener->mListenerType = eNativeListener;
   }
 
 
   if (aFlags.mInSystemGroup) {
     mMayHaveSystemGroupListeners = true;
   }
   if (aFlags.mCapture) {
     mMayHaveCapturingListeners = true;
@@ -467,33 +469,34 @@ nsEventListenerManager::RemoveEventListe
                           const nsAString& aTypeString,
                           const EventListenerFlags& aFlags,
                           bool aAllEvents)
 {
   if (!aListener || !aType || mClearingListeners) {
     return;
   }
 
-  nsListenerStruct* ls;
+  Listener* listener;
 
   uint32_t count = mListeners.Length();
   uint32_t typeCount = 0;
   bool deviceType = IsDeviceType(aType);
 #ifdef MOZ_B2G
   bool timeChangeEvent = (aType == NS_MOZ_TIME_CHANGE_EVENT);
   bool networkEvent = (aType == NS_NETWORK_UPLOAD_EVENT ||
                        aType == NS_NETWORK_DOWNLOAD_EVENT);
 #endif // MOZ_B2G
 
   for (uint32_t i = 0; i < count; ++i) {
-    ls = &mListeners.ElementAt(i);
-    if (EVENT_TYPE_EQUALS(ls, aType, aUserType, aTypeString, aAllEvents)) {
+    listener = &mListeners.ElementAt(i);
+    if (EVENT_TYPE_EQUALS(listener, aType, aUserType, aTypeString,
+                          aAllEvents)) {
       ++typeCount;
-      if (ls->mListener == aListener &&
-          ls->mFlags.EqualsIgnoringTrustness(aFlags)) {
+      if (listener->mListener == aListener &&
+          listener->mFlags.EqualsIgnoringTrustness(aFlags)) {
         nsRefPtr<nsEventListenerManager> kungFuDeathGrip = this;
         mListeners.RemoveElementAt(i);
         --count;
         mNoListenerForEvent = NS_EVENT_NULL;
         mNoListenerForEventAtom = nullptr;
         if (mTarget && aUserType) {
           mTarget->EventListenerRemoved(aUserType);
         }
@@ -523,33 +526,34 @@ nsEventListenerManager::RemoveEventListe
     if (window) {
       window->DisableNetworkEvent(aType);
     }
 #endif // MOZ_B2G
   }
 }
 
 bool
-nsEventListenerManager::ListenerCanHandle(nsListenerStruct* aLs,
+nsEventListenerManager::ListenerCanHandle(Listener* aListener,
                                           WidgetEvent* aEvent)
 {
   // This is slightly different from EVENT_TYPE_EQUALS in that it returns
   // true even when aEvent->message == NS_USER_DEFINED_EVENT and
-  // aLs=>mEventType != NS_USER_DEFINED_EVENT as long as the atoms are the same
-  if (aLs->mAllEvents) {
+  // aListener=>mEventType != NS_USER_DEFINED_EVENT as long as the atoms are
+  // the same
+  if (aListener->mAllEvents) {
     return true;
   }
   if (aEvent->message == NS_USER_DEFINED_EVENT) {
     if (mIsMainThreadELM) {
-      return aLs->mTypeAtom == aEvent->userType;
+      return aListener->mTypeAtom == aEvent->userType;
     }
-    return aLs->mTypeString.Equals(aEvent->typeString);
+    return aListener->mTypeString.Equals(aEvent->typeString);
   }
   MOZ_ASSERT(mIsMainThreadELM);
-  return aLs->mEventType == aEvent->message;
+  return aListener->mEventType == aEvent->message;
 }
 
 void
 nsEventListenerManager::AddEventListenerByType(const EventListenerHolder& aListener, 
                                                const nsAString& aType,
                                                const EventListenerFlags& aFlags)
 {
   nsCOMPtr<nsIAtom> atom =
@@ -565,84 +569,85 @@ nsEventListenerManager::RemoveEventListe
                           const EventListenerFlags& aFlags)
 {
   nsCOMPtr<nsIAtom> atom =
     mIsMainThreadELM ? do_GetAtom(NS_LITERAL_STRING("on") + aType) : nullptr;
   uint32_t type = nsContentUtils::GetEventId(atom);
   RemoveEventListenerInternal(aListener, type, atom, aType, aFlags);
 }
 
-nsListenerStruct*
+nsEventListenerManager::Listener*
 nsEventListenerManager::FindEventHandler(uint32_t aEventType,
                                          nsIAtom* aTypeAtom,
                                          const nsAString& aTypeString)
 {
   // Run through the listeners for this type and see if a script
   // listener is registered
-  nsListenerStruct *ls;
+  Listener* listener;
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
-    ls = &mListeners.ElementAt(i);
-    if (ls->mListenerIsHandler &&
-        EVENT_TYPE_EQUALS(ls, aEventType, aTypeAtom, aTypeString, false)) {
-      return ls;
+    listener = &mListeners.ElementAt(i);
+    if (listener->mListenerIsHandler &&
+        EVENT_TYPE_EQUALS(listener, aEventType, aTypeAtom, aTypeString,
+                          false)) {
+      return listener;
     }
   }
   return nullptr;
 }
 
-nsListenerStruct*
+nsEventListenerManager::Listener*
 nsEventListenerManager::SetEventHandlerInternal(JS::Handle<JSObject*> aScopeObject,
                                                 nsIAtom* aName,
                                                 const nsAString& aTypeString,
                                                 const nsEventHandler& aHandler,
                                                 bool aPermitUntrustedEvents)
 {
   MOZ_ASSERT(aScopeObject || aHandler.HasEventHandler(),
              "Must have one or the other!");
   MOZ_ASSERT(aName || !aTypeString.IsEmpty());
 
   uint32_t eventType = nsContentUtils::GetEventId(aName);
-  nsListenerStruct* ls = FindEventHandler(eventType, aName, aTypeString);
+  Listener* listener = FindEventHandler(eventType, aName, aTypeString);
 
-  if (!ls) {
+  if (!listener) {
     // 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));
     EventListenerHolder holder(scriptListener);
     AddEventListenerInternal(holder, eventType, aName, aTypeString, flags,
                              true);
 
-    ls = FindEventHandler(eventType, aName, aTypeString);
+    listener = FindEventHandler(eventType, aName, aTypeString);
   } else {
-    nsIJSEventListener* scriptListener = ls->GetJSListener();
+    nsIJSEventListener* scriptListener = listener->GetJSListener();
     MOZ_ASSERT(scriptListener,
                "How can we have an event handler with no nsIJSEventListener?");
 
     bool same = scriptListener->GetHandler() == aHandler;
     // Possibly the same listener, but update still the context and scope.
     scriptListener->SetHandler(aHandler, aScopeObject);
     if (mTarget && !same && aName) {
       mTarget->EventListenerRemoved(aName);
       mTarget->EventListenerAdded(aName);
     }
   }
 
   // Set flag to indicate possible need for compilation later
-  ls->mHandlerIsString = !aHandler.HasEventHandler();
+  listener->mHandlerIsString = !aHandler.HasEventHandler();
   if (aPermitUntrustedEvents) {
-    ls->mFlags.mAllowUntrustedEvents = true;
+    listener->mFlags.mAllowUntrustedEvents = true;
   }
 
-  return ls;
+  return listener;
 }
 
 nsresult
 nsEventListenerManager::SetEventHandler(nsIAtom *aName,
                                         const nsAString& aBody,
                                         uint32_t aLanguage,
                                         bool aDeferCompilation,
                                         bool aPermitUntrustedEvents,
@@ -741,122 +746,124 @@ nsEventListenerManager::SetEventHandler(
   NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
 
   NS_ENSURE_STATE(global->GetGlobalJSObject());
 
   JSAutoRequest ar(context->GetNativeContext());
   JS::Rooted<JSObject*> scope(context->GetNativeContext(),
                               global->GetGlobalJSObject());
 
-  nsListenerStruct* ls = SetEventHandlerInternal(scope, aName,
-                                                 EmptyString(),
-                                                 nsEventHandler(),
-                                                 aPermitUntrustedEvents);
+  Listener* listener = SetEventHandlerInternal(scope, aName,
+                                               EmptyString(),
+                                               nsEventHandler(),
+                                               aPermitUntrustedEvents);
 
   if (!aDeferCompilation) {
-    return CompileEventHandlerInternal(ls, &aBody, aElement);
+    return CompileEventHandlerInternal(listener, &aBody, aElement);
   }
 
   return NS_OK;
 }
 
 void
 nsEventListenerManager::RemoveEventHandler(nsIAtom* aName,
                                            const nsAString& aTypeString)
 {
   if (mClearingListeners) {
     return;
   }
 
   uint32_t eventType = nsContentUtils::GetEventId(aName);
-  nsListenerStruct* ls = FindEventHandler(eventType, aName, aTypeString);
+  Listener* listener = FindEventHandler(eventType, aName, aTypeString);
 
-  if (ls) {
-    mListeners.RemoveElementAt(uint32_t(ls - &mListeners.ElementAt(0)));
+  if (listener) {
+    mListeners.RemoveElementAt(uint32_t(listener - &mListeners.ElementAt(0)));
     mNoListenerForEvent = NS_EVENT_NULL;
     mNoListenerForEventAtom = nullptr;
     if (mTarget && aName) {
       mTarget->EventListenerRemoved(aName);
     }
   }
 }
 
 nsresult
-nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
-                                                    const nsAString* aBody,
-                                                    Element* aElement)
+nsEventListenerManager::CompileEventHandlerInternal(
+                          Listener* aListener,
+                          const nsAString* aBody,
+                          Element* aElement)
 {
-  NS_PRECONDITION(aListenerStruct->GetJSListener(),
+  NS_PRECONDITION(aListener->GetJSListener(),
                   "Why do we not have a JS listener?");
-  NS_PRECONDITION(aListenerStruct->mHandlerIsString,
+  NS_PRECONDITION(aListener->mHandlerIsString,
                   "Why are we compiling a non-string JS listener?");
 
   nsresult result = NS_OK;
 
-  nsIJSEventListener *listener = aListenerStruct->GetJSListener();
-  NS_ASSERTION(!listener->GetHandler().HasEventHandler(),
+  nsIJSEventListener* jsListener = aListener->GetJSListener();
+  NS_ASSERTION(!jsListener->GetHandler().HasEventHandler(),
                "What is there to compile?");
 
   nsCOMPtr<nsIDocument> doc;
   nsCOMPtr<nsIScriptGlobalObject> global =
     GetScriptGlobalAndDocument(getter_AddRefs(doc));
   NS_ENSURE_STATE(global);
 
   nsIScriptContext* context = global->GetScriptContext();
   NS_ENSURE_STATE(context);
 
   // Push a context to make sure exceptions are reported in the right place.
   AutoPushJSContext cx(context->GetNativeContext());
   JS::Rooted<JSObject*> handler(cx);
 
-  JS::Rooted<JSObject*> scope(cx, listener->GetEventScope());
+  JS::Rooted<JSObject*> scope(cx, jsListener->GetEventScope());
 
-  nsCOMPtr<nsIAtom> typeAtom = aListenerStruct->mTypeAtom;
+  nsCOMPtr<nsIAtom> typeAtom = aListener->mTypeAtom;
   nsIAtom* attrName = typeAtom;
 
-  if (aListenerStruct->mHandlerIsString) {
+  if (aListener->mHandlerIsString) {
     // OK, we didn't find an existing compiled event handler.  Flag us
     // as not a string so we don't keep trying to compile strings
     // which can't be compiled
-    aListenerStruct->mHandlerIsString = false;
+    aListener->mHandlerIsString = false;
 
     // mTarget may not be an Element if it's a window and we're
     // getting an inline event listener forwarded from <html:body> or
     // <html:frameset> or <xul:window> or the like.
     // XXX I don't like that we have to reference content from
     // here. The alternative is to store the event handler string on
     // the nsIJSEventListener itself, and that still doesn't address
     // the arg names issue.
     nsCOMPtr<Element> element = do_QueryInterface(mTarget);
     MOZ_ASSERT(element || aBody, "Where will we get our body?");
     nsAutoString handlerBody;
     const nsAString* body = aBody;
     if (!aBody) {
-      if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGLoad)
+      if (aListener->mTypeAtom == nsGkAtoms::onSVGLoad) {
         attrName = nsGkAtoms::onload;
-      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGUnload)
+      } else if (aListener->mTypeAtom == nsGkAtoms::onSVGUnload) {
         attrName = nsGkAtoms::onunload;
-      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGResize)
+      } else if (aListener->mTypeAtom == nsGkAtoms::onSVGResize) {
         attrName = nsGkAtoms::onresize;
-      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGScroll)
+      } else if (aListener->mTypeAtom == nsGkAtoms::onSVGScroll) {
         attrName = nsGkAtoms::onscroll;
-      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGZoom)
+      } else if (aListener->mTypeAtom == nsGkAtoms::onSVGZoom) {
         attrName = nsGkAtoms::onzoom;
-      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onbeginEvent)
+      } else if (aListener->mTypeAtom == nsGkAtoms::onbeginEvent) {
         attrName = nsGkAtoms::onbegin;
-      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onrepeatEvent)
+      } else if (aListener->mTypeAtom == nsGkAtoms::onrepeatEvent) {
         attrName = nsGkAtoms::onrepeat;
-      else if (aListenerStruct->mTypeAtom == nsGkAtoms::onendEvent)
+      } else if (aListener->mTypeAtom == nsGkAtoms::onendEvent) {
         attrName = nsGkAtoms::onend;
+      }
 
       element->GetAttr(kNameSpaceID_None, attrName, handlerBody);
       body = &handlerBody;
       aElement = element;
     }
-    aListenerStruct = nullptr;
+    aListener = nullptr;
 
     uint32_t lineNo = 0;
     nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
     MOZ_ASSERT(body);
     MOZ_ASSERT(aElement);
     nsIURI *uri = aElement->OwnerDoc()->GetDocumentURI();
     if (uri) {
       uri->GetSpec(url);
@@ -897,76 +904,76 @@ nsEventListenerManager::CompileEventHand
     JS::Rooted<JSObject*> handlerFun(cx);
     result = nsJSUtils::CompileFunction(cx, JS::NullPtr(), options,
                                         nsAtomCString(typeAtom),
                                         argCount, argNames, *body, handlerFun.address());
     NS_ENSURE_SUCCESS(result, result);
     handler = handlerFun;
     NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
   } else {
-    aListenerStruct = nullptr;
+    aListener = nullptr;
   }
 
   if (handler) {
     nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
     // Bind it
     JS::Rooted<JSObject*> boundHandler(cx);
     context->BindCompiledEventHandler(mTarget, scope, handler, &boundHandler);
     // Note - We pass null for aIncumbentGlobal below. We could also pass the
     // compilation global, but since the handler is guaranteed to be scripted,
     // there's no need to use an override, since the JS engine will always give
     // us the right answer.
     if (!boundHandler) {
-      listener->ForgetHandler();
-    } else if (listener->EventName() == nsGkAtoms::onerror && win) {
+      jsListener->ForgetHandler();
+    } else if (jsListener->EventName() == nsGkAtoms::onerror && win) {
       nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
         new OnErrorEventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
-      listener->SetHandler(handlerCallback);
-    } else if (listener->EventName() == nsGkAtoms::onbeforeunload && win) {
+      jsListener->SetHandler(handlerCallback);
+    } else if (jsListener->EventName() == nsGkAtoms::onbeforeunload && win) {
       nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
         new OnBeforeUnloadEventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
-      listener->SetHandler(handlerCallback);
+      jsListener->SetHandler(handlerCallback);
     } else {
       nsRefPtr<EventHandlerNonNull> handlerCallback =
         new EventHandlerNonNull(boundHandler, /* aIncumbentGlobal = */ nullptr);
-      listener->SetHandler(handlerCallback);
+      jsListener->SetHandler(handlerCallback);
     }
   }
 
   return result;
 }
 
 nsresult
-nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
+nsEventListenerManager::HandleEventSubType(Listener* aListener,
                                            nsIDOMEvent* aDOMEvent,
                                            EventTarget* aCurrentTarget)
 {
   nsresult result = NS_OK;
-  EventListenerHolder listener(aListenerStruct->mListener);  // strong ref
+  EventListenerHolder listenerHolder(aListener->mListener);  // strong ref
 
   // If this is a script handler and we haven't yet
   // compiled the event handler itself
-  if ((aListenerStruct->mListenerType == eJSEventListener) &&
-      aListenerStruct->mHandlerIsString) {
-    result = CompileEventHandlerInternal(aListenerStruct, nullptr, nullptr);
-    aListenerStruct = nullptr;
+  if ((aListener->mListenerType == eJSEventListener) &&
+      aListener->mHandlerIsString) {
+    result = CompileEventHandlerInternal(aListener, nullptr, nullptr);
+    aListener = nullptr;
   }
 
   if (NS_SUCCEEDED(result)) {
     if (mIsMainThreadELM) {
       nsContentUtils::EnterMicroTask();
     }
     // nsIDOMEvent::currentTarget is set in nsEventDispatcher.
-    if (listener.HasWebIDLCallback()) {
+    if (listenerHolder.HasWebIDLCallback()) {
       ErrorResult rv;
-      listener.GetWebIDLCallback()->
+      listenerHolder.GetWebIDLCallback()->
         HandleEvent(aCurrentTarget, *(aDOMEvent->InternalDOMEvent()), rv);
       result = rv.ErrorCode();
     } else {
-      result = listener.GetXPCOMCallback()->HandleEvent(aDOMEvent);
+      result = listenerHolder.GetXPCOMCallback()->HandleEvent(aDOMEvent);
     }
     if (mIsMainThreadELM) {
       nsContentUtils::LeaveMicroTask();
     }
   }
 
   return result;
 }
@@ -983,50 +990,52 @@ nsEventListenerManager::HandleEventInter
                                             EventTarget* aCurrentTarget,
                                             nsEventStatus* aEventStatus)
 {
   //Set the value of the internal PreventDefault flag properly based on aEventStatus
   if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
     aEvent->mFlags.mDefaultPrevented = true;
   }
 
-  nsAutoTObserverArray<nsListenerStruct, 2>::EndLimitedIterator iter(mListeners);
+  nsAutoTObserverArray<Listener, 2>::EndLimitedIterator iter(mListeners);
   Maybe<nsAutoPopupStatePusher> popupStatePusher;
   if (mIsMainThreadELM) {
     popupStatePusher.construct(Event::GetEventPopupControlState(aEvent));
   }
 
   bool hasListener = false;
   while (iter.HasMore()) {
     if (aEvent->mFlags.mImmediatePropagationStopped) {
       break;
     }
-    nsListenerStruct* ls = &iter.GetNext();
+    Listener* listener = &iter.GetNext();
     // Check that the phase is same in event and event listener.
     // Handle only trusted events, except when listener permits untrusted events.
-    if (ListenerCanHandle(ls, aEvent)) {
+    if (ListenerCanHandle(listener, aEvent)) {
       hasListener = true;
-      if (ls->IsListening(aEvent) &&
-          (aEvent->mFlags.mIsTrusted || ls->mFlags.mAllowUntrustedEvents)) {
+      if (listener->IsListening(aEvent) &&
+          (aEvent->mFlags.mIsTrusted ||
+           listener->mFlags.mAllowUntrustedEvents)) {
         if (!*aDOMEvent) {
           // This is tiny bit slow, but happens only once per event.
           nsCOMPtr<mozilla::dom::EventTarget> et =
             do_QueryInterface(aEvent->originalTarget);
           nsEventDispatcher::CreateEvent(et, aPresContext,
                                          aEvent, EmptyString(), aDOMEvent);
         }
         if (*aDOMEvent) {
           if (!aEvent->currentTarget) {
             aEvent->currentTarget = aCurrentTarget->GetTargetForDOMEvent();
             if (!aEvent->currentTarget) {
               break;
             }
           }
 
-          if (NS_FAILED(HandleEventSubType(ls, *aDOMEvent, aCurrentTarget))) {
+          if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent,
+                                           aCurrentTarget))) {
             aEvent->mFlags.mExceptionHasBeenRisen = true;
           }
         }
       }
     }
   }
 
   aEvent->currentTarget = nullptr;
@@ -1099,41 +1108,41 @@ nsEventListenerManager::RemoveListenerFo
 }
 
 bool
 nsEventListenerManager::HasMutationListeners()
 {
   if (mMayHaveMutationListeners) {
     uint32_t count = mListeners.Length();
     for (uint32_t i = 0; i < count; ++i) {
-      nsListenerStruct* ls = &mListeners.ElementAt(i);
-      if (ls->mEventType >= NS_MUTATION_START &&
-          ls->mEventType <= NS_MUTATION_END) {
+      Listener* listener = &mListeners.ElementAt(i);
+      if (listener->mEventType >= NS_MUTATION_START &&
+          listener->mEventType <= NS_MUTATION_END) {
         return true;
       }
     }
   }
 
   return false;
 }
 
 uint32_t
 nsEventListenerManager::MutationListenerBits()
 {
   uint32_t bits = 0;
   if (mMayHaveMutationListeners) {
     uint32_t count = mListeners.Length();
     for (uint32_t i = 0; i < count; ++i) {
-      nsListenerStruct* ls = &mListeners.ElementAt(i);
-      if (ls->mEventType >= NS_MUTATION_START &&
-          ls->mEventType <= NS_MUTATION_END) {
-        if (ls->mEventType == NS_MUTATION_SUBTREEMODIFIED) {
+      Listener* listener = &mListeners.ElementAt(i);
+      if (listener->mEventType >= NS_MUTATION_START &&
+          listener->mEventType <= NS_MUTATION_END) {
+        if (listener->mEventType == NS_MUTATION_SUBTREEMODIFIED) {
           return kAllMutationBits;
         }
-        bits |= MutationBitForEventType(ls->mEventType);
+        bits |= MutationBitForEventType(listener->mEventType);
       }
     }
   }
   return bits;
 }
 
 bool
 nsEventListenerManager::HasListenersFor(const nsAString& aEventName)
@@ -1148,18 +1157,18 @@ nsEventListenerManager::HasListenersFor(
 #ifdef DEBUG
   nsAutoString name;
   aEventNameWithOn->ToString(name);
 #endif
   NS_ASSERTION(StringBeginsWith(name, NS_LITERAL_STRING("on")),
                "Event name does not start with 'on'");
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
-    nsListenerStruct* ls = &mListeners.ElementAt(i);
-    if (ls->mTypeAtom == aEventNameWithOn) {
+    Listener* listener = &mListeners.ElementAt(i);
+    if (listener->mTypeAtom == aEventNameWithOn) {
       return true;
     }
   }
   return false;
 }
 
 bool
 nsEventListenerManager::HasListeners()
@@ -1170,49 +1179,50 @@ nsEventListenerManager::HasListeners()
 nsresult
 nsEventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
 {
   nsCOMPtr<EventTarget> target = do_QueryInterface(mTarget);
   NS_ENSURE_STATE(target);
   aList->Clear();
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
-    const nsListenerStruct& ls = mListeners.ElementAt(i);
+    const Listener& listener = mListeners.ElementAt(i);
     // If this is a script handler and we haven't yet
     // compiled the event handler itself go ahead and compile it
-    if ((ls.mListenerType == eJSEventListener) && ls.mHandlerIsString) {
-      CompileEventHandlerInternal(const_cast<nsListenerStruct*>(&ls), nullptr,
+    if (listener.mListenerType == eJSEventListener &&
+        listener.mHandlerIsString) {
+      CompileEventHandlerInternal(const_cast<Listener*>(&listener), nullptr,
                                   nullptr);
     }
     nsAutoString eventType;
-    if (ls.mAllEvents) {
+    if (listener.mAllEvents) {
       eventType.SetIsVoid(true);
     } else {
-      eventType.Assign(Substring(nsDependentAtomString(ls.mTypeAtom), 2));
+      eventType.Assign(Substring(nsDependentAtomString(listener.mTypeAtom), 2));
     }
     // EventListenerInfo is defined in XPCOM, so we have to go ahead
     // and convert to an XPCOM callback here...
     nsRefPtr<EventListenerInfo> info =
-      new EventListenerInfo(eventType, ls.mListener.ToXPCOMCallback(),
-                            ls.mFlags.mCapture,
-                            ls.mFlags.mAllowUntrustedEvents,
-                            ls.mFlags.mInSystemGroup);
+      new EventListenerInfo(eventType, listener.mListener.ToXPCOMCallback(),
+                            listener.mFlags.mCapture,
+                            listener.mFlags.mAllowUntrustedEvents,
+                            listener.mFlags.mInSystemGroup);
     aList->AppendObject(info);
   }
   return NS_OK;
 }
 
 bool
 nsEventListenerManager::HasUnloadListeners()
 {
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
-    nsListenerStruct* ls = &mListeners.ElementAt(i);
-    if (ls->mEventType == NS_PAGE_UNLOAD ||
-        ls->mEventType == NS_BEFORE_PAGE_UNLOAD) {
+    Listener* listener = &mListeners.ElementAt(i);
+    if (listener->mEventType == NS_PAGE_UNLOAD ||
+        listener->mEventType == NS_BEFORE_PAGE_UNLOAD) {
       return true;
     }
   }
   return false;
 }
 
 void
 nsEventListenerManager::SetEventHandler(nsIAtom* aEventName,
@@ -1275,29 +1285,29 @@ nsEventListenerManager::SetEventHandler(
                           !nsContentUtils::IsCallerChrome());
 }
 
 const nsEventHandler*
 nsEventListenerManager::GetEventHandlerInternal(nsIAtom *aEventName,
                                                 const nsAString& aTypeString)
 {
   uint32_t eventType = nsContentUtils::GetEventId(aEventName);
-  nsListenerStruct* ls = FindEventHandler(eventType, aEventName, aTypeString);
+  Listener* listener = FindEventHandler(eventType, aEventName, aTypeString);
 
-  if (!ls) {
+  if (!listener) {
     return nullptr;
   }
 
-  nsIJSEventListener *listener = ls->GetJSListener();
-    
-  if (ls->mHandlerIsString) {
-    CompileEventHandlerInternal(ls, nullptr, nullptr);
+  nsIJSEventListener* jsListener = listener->GetJSListener();
+
+  if (listener->mHandlerIsString) {
+    CompileEventHandlerInternal(listener, nullptr, nullptr);
   }
 
-  const nsEventHandler& handler = listener->GetHandler();
+  const nsEventHandler& handler = jsListener->GetHandler();
   if (handler.HasEventHandler()) {
     return &handler;
   }
 
   return nullptr;
 }
 
 size_t
@@ -1316,30 +1326,30 @@ nsEventListenerManager::SizeOfIncludingT
   return n;
 }
 
 void
 nsEventListenerManager::MarkForCC()
 {
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
-    const nsListenerStruct& ls = mListeners.ElementAt(i);
-    nsIJSEventListener* jsl = ls.GetJSListener();
+    const Listener& listener = mListeners.ElementAt(i);
+    nsIJSEventListener* jsl = listener.GetJSListener();
     if (jsl) {
       if (jsl->GetHandler().HasEventHandler()) {
         JS::ExposeObjectToActiveJS(jsl->GetHandler().Ptr()->Callable());
       }
       if (JSObject* scope = jsl->GetEventScope()) {
         JS::ExposeObjectToActiveJS(scope);
       }
-    } else if (ls.mListenerType == eWrappedJSListener) {
-      xpc_TryUnmarkWrappedGrayObject(ls.mListener.GetXPCOMCallback());
-    } else if (ls.mListenerType == eWebIDLListener) {
+    } else if (listener.mListenerType == eWrappedJSListener) {
+      xpc_TryUnmarkWrappedGrayObject(listener.mListener.GetXPCOMCallback());
+    } else if (listener.mListenerType == eWebIDLListener) {
       // Callback() unmarks gray
-      ls.mListener.GetWebIDLCallback()->Callback();
+      listener.mListener.GetWebIDLCallback()->Callback();
     }
   }
   if (mRefCnt.IsPurple()) {
     mRefCnt.RemovePurple();
   }
 }
 
 already_AddRefed<nsIScriptGlobalObject>
--- a/dom/events/nsEventListenerManager.h
+++ b/dom/events/nsEventListenerManager.h
@@ -18,34 +18,32 @@
 
 class nsIDOMEvent;
 struct EventTypeData;
 class nsEventTargetChainItem;
 class nsPIDOMWindow;
 class nsIEventListenerInfo;
 class nsIScriptContext;
 
-struct nsListenerStruct;
 class nsEventListenerManager;
 
 template<class T> class nsCOMArray;
 
 namespace mozilla {
 namespace dom {
 
 class EventTarget;
 class Element;
 
 typedef CallbackObjectHolder<EventListener, nsIDOMEventListener>
   EventListenerHolder;
 
 struct EventListenerFlags
 {
-  friend struct ::nsListenerStruct;
-  friend class  ::nsEventListenerManager;
+  friend class ::nsEventListenerManager;
 private:
   // If mListenerIsJSListener is true, the listener is implemented by JS.
   // Otherwise, it's implemented by native code or JS but it's wrapped.
   bool mListenerIsJSListener : 1;
 
 public:
   // If mCapture is true, it means the listener captures the event.  Otherwise,
   // it's listening at bubbling phase.
@@ -151,68 +149,70 @@ typedef enum
 {
     eNativeListener = 0,
     eJSEventListener,
     eWrappedJSListener,
     eWebIDLListener,
     eListenerTypeCount
 } nsListenerType;
 
-struct nsListenerStruct
-{
-  mozilla::dom::EventListenerHolder mListener;
-  nsCOMPtr<nsIAtom>             mTypeAtom;   // for the main thread
-  nsString                      mTypeString; // for non-main-threads
-  uint16_t                      mEventType;
-  uint8_t                       mListenerType;
-  bool                          mListenerIsHandler : 1;
-  bool                          mHandlerIsString : 1;
-  bool                          mAllEvents : 1;
-
-  mozilla::dom::EventListenerFlags mFlags;
-
-  nsIJSEventListener* GetJSListener() const {
-    return (mListenerType == eJSEventListener) ?
-      static_cast<nsIJSEventListener *>(mListener.GetXPCOMCallback()) : nullptr;
-  }
-
-  nsListenerStruct()
-  {
-    MOZ_ASSERT(sizeof(mListenerType) == 1);
-    MOZ_ASSERT(eListenerTypeCount < 255);
-  }
-
-  ~nsListenerStruct()
-  {
-    if ((mListenerType == eJSEventListener) && mListener) {
-      static_cast<nsIJSEventListener*>(mListener.GetXPCOMCallback())->Disconnect();
-    }
-  }
-
-  MOZ_ALWAYS_INLINE bool IsListening(const mozilla::WidgetEvent* aEvent) const
-  {
-    if (mFlags.mInSystemGroup != aEvent->mFlags.mInSystemGroup) {
-      return false;
-    }
-    // FIXME Should check !mFlags.mCapture when the event is in target
-    //       phase because capture phase event listeners should not be fired.
-    //       But it breaks at least <xul:dialog>'s buttons. Bug 235441.
-    return ((mFlags.mCapture && aEvent->mFlags.mInCapturePhase) ||
-            (!mFlags.mCapture && aEvent->mFlags.mInBubblingPhase));
-  }
-};
-
 /*
  * Event listener manager
  */
 
 class nsEventListenerManager
 {
+public:
+  struct Listener
+  {
+    mozilla::dom::EventListenerHolder mListener;
+    nsCOMPtr<nsIAtom> mTypeAtom; // for the main thread
+    nsString mTypeString; // for non-main-threads
+    uint16_t mEventType;
+    uint8_t mListenerType;
+    bool mListenerIsHandler : 1;
+    bool mHandlerIsString : 1;
+    bool mAllEvents : 1;
 
-public:
+    mozilla::dom::EventListenerFlags mFlags;
+
+    nsIJSEventListener* GetJSListener() const
+    {
+      return (mListenerType == eJSEventListener) ?
+        static_cast<nsIJSEventListener *>(mListener.GetXPCOMCallback()) :
+        nullptr;
+    }
+
+    Listener()
+    {
+      MOZ_ASSERT(sizeof(mListenerType) == 1);
+      MOZ_ASSERT(eListenerTypeCount < 255);
+    }
+
+    ~Listener()
+    {
+      if ((mListenerType == eJSEventListener) && mListener) {
+        static_cast<nsIJSEventListener*>(
+          mListener.GetXPCOMCallback())->Disconnect();
+      }
+    }
+
+    MOZ_ALWAYS_INLINE bool IsListening(const mozilla::WidgetEvent* aEvent) const
+    {
+      if (mFlags.mInSystemGroup != aEvent->mFlags.mInSystemGroup) {
+        return false;
+      }
+      // FIXME Should check !mFlags.mCapture when the event is in target
+      //       phase because capture phase event listeners should not be fired.
+      //       But it breaks at least <xul:dialog>'s buttons. Bug 235441.
+      return ((mFlags.mCapture && aEvent->mFlags.mInCapturePhase) ||
+              (!mFlags.mCapture && aEvent->mFlags.mInBubblingPhase));
+    }
+  };
+
   nsEventListenerManager(mozilla::dom::EventTarget* aTarget);
   virtual ~nsEventListenerManager();
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsEventListenerManager)
 
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsEventListenerManager)
 
   void AddEventListener(const nsAString& aType,
@@ -413,49 +413,49 @@ public:
   mozilla::dom::EventTarget* GetTarget() { return mTarget; }
 protected:
   void HandleEventInternal(nsPresContext* aPresContext,
                            mozilla::WidgetEvent* aEvent,
                            nsIDOMEvent** aDOMEvent,
                            mozilla::dom::EventTarget* aCurrentTarget,
                            nsEventStatus* aEventStatus);
 
-  nsresult HandleEventSubType(nsListenerStruct* aListenerStruct,
+  nsresult HandleEventSubType(Listener* aListener,
                               nsIDOMEvent* aDOMEvent,
                               mozilla::dom::EventTarget* aCurrentTarget);
 
   /**
-   * Compile the "inline" event listener for aListenerStruct.  The
+   * Compile the "inline" event listener for aListener.  The
    * body of the listener can be provided in aBody; if this is null we
    * will look for it on mTarget.  If aBody is provided, aElement should be
    * as well; otherwise it will also be inferred from mTarget.
    */
-  nsresult CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
+  nsresult CompileEventHandlerInternal(Listener* aListener,
                                        const nsAString* aBody,
                                        mozilla::dom::Element* aElement);
 
   /**
-   * Find the nsListenerStruct for the "inline" event listener for aTypeAtom.
+   * Find the Listener for the "inline" event listener for aTypeAtom.
    */
-  nsListenerStruct* FindEventHandler(uint32_t aEventType, nsIAtom* aTypeAtom,
-                                     const nsAString& aTypeString);
+  Listener* FindEventHandler(uint32_t aEventType,
+                             nsIAtom* aTypeAtom,
+                             const nsAString& aTypeString);
 
   /**
    * Set the "inline" event listener for aName to aHandler.  aHandler may be
    * have no actual handler set to indicate that we should lazily get and
    * compile the string for this listener, but in that case aContext and
    * aScopeGlobal must be non-null.  Otherwise, aContext and aScopeGlobal are
-   * allowed to be null.  The nsListenerStruct that results, if any, is returned
-   * in aListenerStruct.
+   * allowed to be null.
    */
-  nsListenerStruct* SetEventHandlerInternal(JS::Handle<JSObject*> aScopeGlobal,
-                                            nsIAtom* aName,
-                                            const nsAString& aTypeString,
-                                            const nsEventHandler& aHandler,
-                                            bool aPermitUntrustedEvents);
+  Listener* SetEventHandlerInternal(JS::Handle<JSObject*> aScopeGlobal,
+                                    nsIAtom* aName,
+                                    const nsAString& aTypeString,
+                                    const nsEventHandler& aHandler,
+                                    bool aPermitUntrustedEvents);
 
   bool IsDeviceType(uint32_t aType);
   void EnableDevice(uint32_t aType);
   void DisableDevice(uint32_t aType);
 
 public:
   /**
    * Set the "inline" event listener for aEventName to aHandler.  If
@@ -532,34 +532,34 @@ protected:
          const mozilla::dom::EventListenerFlags& aFlags,
          bool aAllEvents = false);
   void RemoveAllListeners();
   const EventTypeData* GetTypeDataForIID(const nsIID& aIID);
   const EventTypeData* GetTypeDataForEventName(nsIAtom* aName);
   nsPIDOMWindow* GetInnerWindowForTarget();
   already_AddRefed<nsPIDOMWindow> GetTargetAsInnerWindow() const;
 
-  bool ListenerCanHandle(nsListenerStruct* aLs, mozilla::WidgetEvent* aEvent);
+  bool ListenerCanHandle(Listener* aListener, mozilla::WidgetEvent* aEvent);
 
   already_AddRefed<nsIScriptGlobalObject>
   GetScriptGlobalAndDocument(nsIDocument** aDoc);
 
   uint32_t mMayHavePaintEventListener : 1;
   uint32_t mMayHaveMutationListeners : 1;
   uint32_t mMayHaveCapturingListeners : 1;
   uint32_t mMayHaveSystemGroupListeners : 1;
   uint32_t mMayHaveAudioAvailableEventListener : 1;
   uint32_t mMayHaveTouchEventListener : 1;
   uint32_t mMayHaveMouseEnterLeaveEventListener : 1;
   uint32_t mMayHavePointerEnterLeaveEventListener : 1;
   uint32_t mClearingListeners : 1;
   uint32_t mIsMainThreadELM : 1;
   uint32_t mNoListenerForEvent : 22;
 
-  nsAutoTObserverArray<nsListenerStruct, 2> mListeners;
+  nsAutoTObserverArray<Listener, 2> mListeners;
   mozilla::dom::EventTarget*                mTarget;  //WEAK
   nsCOMPtr<nsIAtom>                         mNoListenerForEventAtom;
 
   friend class ELMCreationDetector;
   static uint32_t                           sMainThreadCreatedCount;
 };
 
 /**