void
EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
                                          WidgetEvent* aEvent,
                                          nsIDOMEvent** aDOMEvent,
                                          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<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;
    }
    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(listener, aEvent)) {
      hasListener = true;
      if (listener->IsListening(aEvent) &&
          (aEvent->mFlags.mIsTrusted ||
           listener->mFlags.mAllowUntrustedEvents)) {
        if (!*aDOMEvent) {
          // This is tiny bit slow, but happens only once per event.
          nsCOMPtr<EventTarget> et =
            do_QueryInterface(aEvent->originalTarget);
          EventDispatcher::CreateEvent(et, aPresContext,
                                       aEvent, EmptyString(), aDOMEvent);
        }
        if (*aDOMEvent) {
          if (!aEvent->currentTarget) {
            aEvent->currentTarget = aCurrentTarget->GetTargetForDOMEvent();
            if (!aEvent->currentTarget) {
              break;
            }
          }

          if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent,
                                           aCurrentTarget))) {
            aEvent->mFlags.mExceptionHasBeenRisen = true;
          }
        }
      }
    }
  }

  aEvent->currentTarget = nullptr;

  if (mIsMainThreadELM && !hasListener) {
    mNoListenerForEvent = aEvent->message;
    mNoListenerForEventAtom = aEvent->userType;
  }

  if (aEvent->mFlags.mDefaultPrevented) {
    *aEventStatus = nsEventStatus_eConsumeNoDefault;
  }
}
void
EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
                                          WidgetEvent* aEvent,
                                          nsIDOMEvent** aDOMEvent,
                                          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<Listener, 2>::EndLimitedIterator iter(mListeners);
  Maybe<nsAutoPopupStatePusher> popupStatePusher;
  if (mIsMainThreadELM) {
    popupStatePusher.emplace(Event::GetEventPopupControlState(aEvent, *aDOMEvent));
  }

  bool hasListener = false;
  while (iter.HasMore()) {
    if (aEvent->mFlags.mImmediatePropagationStopped) {
      break;
    }
    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(listener, aEvent)) {
      hasListener = true;
      if (listener->IsListening(aEvent) &&
          (aEvent->mFlags.mIsTrusted ||
           listener->mFlags.mAllowUntrustedEvents)) {
        if (!*aDOMEvent) {
          // This is tiny bit slow, but happens only once per event.
          nsCOMPtr<EventTarget> et =
            do_QueryInterface(aEvent->originalTarget);
          EventDispatcher::CreateEvent(et, aPresContext,
                                       aEvent, EmptyString(), aDOMEvent);
        }
        if (*aDOMEvent) {
          if (!aEvent->currentTarget) {
            aEvent->currentTarget = aCurrentTarget->GetTargetForDOMEvent();
            if (!aEvent->currentTarget) {
              break;
            }
          }

          // Maybe add a marker to the docshell's timeline, but only
          // bother with all the logic if some docshell is recording.
          nsCOMPtr<nsIDocShell> docShell;
          bool isTimelineRecording = false;
          if (mIsMainThreadELM &&
              nsDocShell::gProfileTimelineRecordingsCount > 0 &&
              listener->mListenerType != Listener::eNativeListener) {
            docShell = GetDocShellForTarget();
            if (docShell) {
              docShell->GetRecordProfileTimelineMarkers(&isTimelineRecording);
            }
            if (isTimelineRecording) {
              nsDocShell* ds = static_cast<nsDocShell*>(docShell.get());
              nsAutoString typeStr;
              (*aDOMEvent)->GetType(typeStr);
              uint16_t phase;
              (*aDOMEvent)->GetEventPhase(&phase);
              mozilla::UniquePtr<TimelineMarker> marker =
                MakeUnique<EventTimelineMarker>(ds, TRACING_INTERVAL_START,
                                                phase, typeStr);
              ds->AddProfileTimelineMarker(Move(marker));
            }
          }

          if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent,
                                           aCurrentTarget))) {
            aEvent->mFlags.mExceptionHasBeenRisen = true;
          }

          if (isTimelineRecording) {
            nsDocShell* ds = static_cast<nsDocShell*>(docShell.get());
            ds->AddProfileTimelineMarker("DOMEvent", TRACING_INTERVAL_END);
          }
        }
      }
    }
  }

  aEvent->currentTarget = nullptr;

  if (mIsMainThreadELM && !hasListener) {
    mNoListenerForEvent = aEvent->message;
    mNoListenerForEventAtom = aEvent->userType;
  }

  if (aEvent->mFlags.mDefaultPrevented) {
    *aEventStatus = nsEventStatus_eConsumeNoDefault;
  }
}