/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "core/events/EventTarget.h"

#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptEventListener.h"
#include "bindings/core/v8/SourceLocation.h"
#include "bindings/core/v8/V8DOMActivityLogger.h"
#include "core/dom/ExceptionCode.h"
#include "core/editing/Editor.h"
#include "core/events/Event.h"
#include "core/events/EventUtil.h"
#include "core/events/PointerEvent.h"
#include "core/frame/FrameHost.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "platform/EventDispatchForbiddenScope.h"
#include "platform/Histogram.h"
#include "wtf/PtrUtil.h"
#include "wtf/StdLibExtras.h"
#include "wtf/Threading.h"
#include "wtf/Vector.h"
#include <memory>

using namespace WTF;

namespace blink {
namespace {

enum PassiveForcedListenerResultType {
    PreventDefaultNotCalled,
    DocumentLevelTouchPreventDefaultCalled,
    PassiveForcedListenerResultTypeMax
};

Event::PassiveMode eventPassiveMode(const RegisteredEventListener& eventListener)
{
    if (!eventListener.passive())
        return Event::PassiveMode::NotPassive;
    if (eventListener.passiveForcedForDocumentTarget())
        return Event::PassiveMode::PassiveForcedDocumentLevel;
    return Event::PassiveMode::Passive;
}

Settings* windowSettings(LocalDOMWindow* executingWindow)
{
    if (executingWindow) {
        if (LocalFrame* frame = executingWindow->frame()) {
            return frame->settings();
        }
    }
    return nullptr;
}

bool isTouchScrollBlockingEvent(const AtomicString& eventType)
{
    return eventType == EventTypeNames::touchstart
        || eventType == EventTypeNames::touchmove;
}

bool isScrollBlockingEvent(const AtomicString& eventType)
{
    return isTouchScrollBlockingEvent(eventType)
        || eventType == EventTypeNames::mousewheel
        || eventType == EventTypeNames::wheel;
}

double blockedEventsWarningThreshold(const ExecutionContext* context, const Event* event)
{
    if (!event->cancelable())
        return 0.0;
    if (!isScrollBlockingEvent(event->type()))
        return 0.0;

    if (!context->isDocument())
        return 0.0;
    FrameHost* frameHost = toDocument(context)->frameHost();
    if (!frameHost)
        return 0.0;
    return frameHost->settings().blockedMainThreadEventsWarningThreshold();
}

void reportBlockedEvent(ExecutionContext* context, const Event* event, RegisteredEventListener* registeredListener, double delayedSeconds)
{
    if (registeredListener->listener()->type() != EventListener::JSEventListenerType)
        return;

    V8AbstractEventListener* v8Listener = V8AbstractEventListener::cast(registeredListener->listener());
    v8::HandleScope handles(v8Listener->isolate());
    v8::Local<v8::Context> v8Context = toV8Context(context, v8Listener->world());
    if (v8Context.IsEmpty())
        return;
    v8::Context::Scope contextScope(v8Context);
    v8::Local<v8::Object> handler = v8Listener->getListenerObject(context);

    String messageText = String::format(
        "Handling of '%s' input event was delayed for %ld ms due to main thread being busy. "
        "Consider marking event handler as 'passive' to make the page more responsive.",
        event->type().getString().utf8().data(), lround(delayedSeconds * 1000));

    v8::Local<v8::Function> function = eventListenerEffectiveFunction(v8Listener->isolate(), handler);
    std::unique_ptr<SourceLocation> location = SourceLocation::fromFunction(function);
    ConsoleMessage* message = ConsoleMessage::create(JSMessageSource, WarningMessageLevel, messageText, std::move(location));
    context->addConsoleMessage(message);
    registeredListener->setBlockedEventWarningEmitted();
}


} // namespace

EventTargetData::EventTargetData()
{
}

EventTargetData::~EventTargetData()
{
}

DEFINE_TRACE(EventTargetData)
{
    visitor->trace(eventListenerMap);
}

DEFINE_TRACE_WRAPPERS(EventTarget)
{
    EventListenerIterator iterator(const_cast<EventTarget*>(this));
    while (EventListener* listener = iterator.nextListener()) {
        if (listener->type() != EventListener::JSEventListenerType)
            continue;
        V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener);
        if (!v8listener->hasExistingListenerObject())
            continue;

        visitor->traceWrappers(v8listener);
    }
}

EventTarget::EventTarget()
{
}

EventTarget::~EventTarget()
{
}

Node* EventTarget::toNode()
{
    return nullptr;
}

const DOMWindow* EventTarget::toDOMWindow() const
{
    return nullptr;
}

const LocalDOMWindow* EventTarget::toLocalDOMWindow() const
{
    return nullptr;
}

LocalDOMWindow* EventTarget::toLocalDOMWindow()
{
    return nullptr;
}

MessagePort* EventTarget::toMessagePort()
{
    return nullptr;
}

inline LocalDOMWindow* EventTarget::executingWindow()
{
    if (ExecutionContext* context = getExecutionContext())
        return context->executingWindow();
    return nullptr;
}

void EventTarget::setDefaultAddEventListenerOptions(const AtomicString& eventType, AddEventListenerOptionsResolved& options)
{
    if (!isScrollBlockingEvent(eventType)) {
        if (!options.hasPassive())
            options.setPassive(false);
        return;
    }

    if (LocalDOMWindow* executingWindow = this->executingWindow()) {
        if (options.hasPassive()) {
            UseCounter::count(executingWindow->document(), options.passive() ? UseCounter::AddEventListenerPassiveTrue : UseCounter::AddEventListenerPassiveFalse);
        }
    }

    if (RuntimeEnabledFeatures::passiveDocumentEventListenersEnabled() && isTouchScrollBlockingEvent(eventType)) {
        if (!options.hasPassive()) {
            if (Node* node = toNode()) {
                if (node->isDocumentNode() || node->document().documentElement() == node || node->document().body() == node) {
                    options.setPassive(true);
                    options.setPassiveForcedForDocumentTarget(true);
                    return;
                }
            } else if (toLocalDOMWindow()) {
                options.setPassive(true);
                options.setPassiveForcedForDocumentTarget(true);
                return;
            }
        }
    }

    if (Settings* settings = windowSettings(executingWindow())) {
        switch (settings->passiveListenerDefault()) {
        case PassiveListenerDefault::False:
            if (!options.hasPassive())
                options.setPassive(false);
            break;
        case PassiveListenerDefault::True:
            if (!options.hasPassive())
                options.setPassive(true);
            break;
        case PassiveListenerDefault::ForceAllTrue:
            options.setPassive(true);
            break;
        }
    } else {
        if (!options.hasPassive())
            options.setPassive(false);
    }
}

bool EventTarget::addEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
{
    AddEventListenerOptionsResolved options;
    options.setCapture(useCapture);
    setDefaultAddEventListenerOptions(eventType, options);
    return addEventListenerInternal(eventType, listener, options);
}

bool EventTarget::addEventListener(const AtomicString& eventType, EventListener* listener, const AddEventListenerOptionsOrBoolean& optionsUnion)
{
    if (optionsUnion.isBoolean())
        return addEventListener(eventType, listener, optionsUnion.getAsBoolean());
    if (optionsUnion.isAddEventListenerOptions()) {
        AddEventListenerOptionsResolved options = optionsUnion.getAsAddEventListenerOptions();
        return addEventListener(eventType, listener, options);
    }
    return addEventListener(eventType, listener);
}

bool EventTarget::addEventListener(const AtomicString& eventType, EventListener* listener, AddEventListenerOptionsResolved& options)
{
    setDefaultAddEventListenerOptions(eventType, options);
    return addEventListenerInternal(eventType, listener, options);
}

bool EventTarget::addEventListenerInternal(const AtomicString& eventType, EventListener* listener, const AddEventListenerOptionsResolved& options)
{
    if (!listener)
        return false;

    V8DOMActivityLogger* activityLogger = V8DOMActivityLogger::currentActivityLoggerIfIsolatedWorld();
    if (activityLogger) {
        Vector<String> argv;
        argv.append(toNode() ? toNode()->nodeName() : interfaceName());
        argv.append(eventType);
        activityLogger->logEvent("blinkAddEventListener", argv.size(), argv.data());
    }

    RegisteredEventListener registeredListener;
    bool added = ensureEventTargetData().eventListenerMap.add(eventType, listener, options, &registeredListener);
    if (added)
        addedEventListener(eventType, registeredListener);
    return added;
}

void EventTarget::addedEventListener(const AtomicString& eventType, RegisteredEventListener& registeredListener)
{
    if (eventType == EventTypeNames::auxclick) {
        if (LocalDOMWindow* executingWindow = this->executingWindow()) {
            UseCounter::count(executingWindow->document(), UseCounter::AuxclickAddListenerCount);
        }
    } else if (EventUtil::isPointerEventType(eventType)) {
        if (LocalDOMWindow* executingWindow = this->executingWindow()) {
            UseCounter::count(executingWindow->document(), UseCounter::PointerEventAddListenerCount);
        }
    } else if (eventType == EventTypeNames::slotchange) {
        if (LocalDOMWindow* executingWindow = this->executingWindow()) {
            UseCounter::count(executingWindow->document(), UseCounter::SlotChangeEventAddListener);
        }
    }
}

bool EventTarget::removeEventListener(const AtomicString& eventType, const EventListener* listener, bool useCapture)
{
    EventListenerOptions options;
    options.setCapture(useCapture);
    return removeEventListenerInternal(eventType, listener, options);
}

bool EventTarget::removeEventListener(const AtomicString& eventType, const EventListener* listener, const EventListenerOptionsOrBoolean& optionsUnion)
{
    if (optionsUnion.isBoolean())
        return removeEventListener(eventType, listener, optionsUnion.getAsBoolean());
    if (optionsUnion.isEventListenerOptions()) {
        EventListenerOptions options = optionsUnion.getAsEventListenerOptions();
        return removeEventListener(eventType, listener, options);
    }
    return removeEventListener(eventType, listener);
}

bool EventTarget::removeEventListener(const AtomicString& eventType, const EventListener* listener, EventListenerOptions& options)
{
    return removeEventListenerInternal(eventType, listener, options);
}

bool EventTarget::removeEventListenerInternal(const AtomicString& eventType, const EventListener* listener, const EventListenerOptions& options)
{
    if (!listener)
        return false;

    EventTargetData* d = eventTargetData();
    if (!d)
        return false;

    size_t indexOfRemovedListener;
    RegisteredEventListener registeredListener;

    if (!d->eventListenerMap.remove(eventType, listener, options, &indexOfRemovedListener, &registeredListener))
        return false;

    // Notify firing events planning to invoke the listener at 'index' that
    // they have one less listener to invoke.
    if (d->firingEventIterators) {
        for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
            FiringEventIterator& firingIterator = d->firingEventIterators->at(i);
            if (eventType != firingIterator.eventType)
                continue;

            if (indexOfRemovedListener >= firingIterator.end)
                continue;

            --firingIterator.end;
            // Note that when firing an event listener,
            // firingIterator.iterator indicates the next event listener
            // that would fire, not the currently firing event
            // listener. See EventTarget::fireEventListeners.
            if (indexOfRemovedListener < firingIterator.iterator)
                --firingIterator.iterator;
        }
    }
    removedEventListener(eventType, registeredListener);
    return true;
}

void EventTarget::removedEventListener(const AtomicString& eventType, const RegisteredEventListener& registeredListener)
{
}

bool EventTarget::setAttributeEventListener(const AtomicString& eventType, EventListener* listener)
{
    clearAttributeEventListener(eventType);
    if (!listener)
        return false;
    return addEventListener(eventType, listener, false);
}

EventListener* EventTarget::getAttributeEventListener(const AtomicString& eventType)
{
    EventListenerVector* listenerVector = getEventListeners(eventType);
    if (!listenerVector)
        return nullptr;
    for (auto& eventListener : *listenerVector) {
        EventListener* listener = eventListener.listener();
        if (listener->isAttribute() && listener->belongsToTheCurrentWorld())
            return listener;
    }
    return nullptr;
}

bool EventTarget::clearAttributeEventListener(const AtomicString& eventType)
{
    EventListener* listener = getAttributeEventListener(eventType);
    if (!listener)
        return false;
    return removeEventListener(eventType, listener, false);
}

bool EventTarget::dispatchEventForBindings(Event* event, ExceptionState& exceptionState)
{
    if (!event->wasInitialized()) {
        exceptionState.throwDOMException(InvalidStateError, "The event provided is uninitialized.");
        return false;
    }
    if (event->isBeingDispatched()) {
        exceptionState.throwDOMException(InvalidStateError, "The event is already being dispatched.");
        return false;
    }

    if (!getExecutionContext())
        return false;

    event->setTrusted(false);

    // Return whether the event was cancelled or not to JS not that it
    // might have actually been default handled; so check only against
    // CanceledByEventHandler.
    return dispatchEventInternal(event) != DispatchEventResult::CanceledByEventHandler;
}

DispatchEventResult EventTarget::dispatchEvent(Event* event)
{
    event->setTrusted(true);
    return dispatchEventInternal(event);
}

DispatchEventResult EventTarget::dispatchEventInternal(Event* event)
{
    event->setTarget(this);
    event->setCurrentTarget(this);
    event->setEventPhase(Event::kAtTarget);
    DispatchEventResult dispatchResult = fireEventListeners(event);
    event->setEventPhase(0);
    return dispatchResult;
}

void EventTarget::uncaughtExceptionInEventHandler()
{
}

static const AtomicString& legacyType(const Event* event)
{
    if (event->type() == EventTypeNames::transitionend)
        return EventTypeNames::webkitTransitionEnd;

    if (event->type() == EventTypeNames::animationstart)
        return EventTypeNames::webkitAnimationStart;

    if (event->type() == EventTypeNames::animationend)
        return EventTypeNames::webkitAnimationEnd;

    if (event->type() == EventTypeNames::animationiteration)
        return EventTypeNames::webkitAnimationIteration;

    if (event->type() == EventTypeNames::wheel)
        return EventTypeNames::mousewheel;

    return emptyAtom;
}

void EventTarget::countLegacyEvents(const AtomicString& legacyTypeName, EventListenerVector* listenersVector, EventListenerVector* legacyListenersVector)
{
    UseCounter::Feature unprefixedFeature;
    UseCounter::Feature prefixedFeature;
    UseCounter::Feature prefixedAndUnprefixedFeature;
    if (legacyTypeName == EventTypeNames::webkitTransitionEnd) {
        prefixedFeature = UseCounter::PrefixedTransitionEndEvent;
        unprefixedFeature = UseCounter::UnprefixedTransitionEndEvent;
        prefixedAndUnprefixedFeature = UseCounter::PrefixedAndUnprefixedTransitionEndEvent;
    } else if (legacyTypeName == EventTypeNames::webkitAnimationEnd) {
        prefixedFeature = UseCounter::PrefixedAnimationEndEvent;
        unprefixedFeature = UseCounter::UnprefixedAnimationEndEvent;
        prefixedAndUnprefixedFeature = UseCounter::PrefixedAndUnprefixedAnimationEndEvent;
    } else if (legacyTypeName == EventTypeNames::webkitAnimationStart) {
        prefixedFeature = UseCounter::PrefixedAnimationStartEvent;
        unprefixedFeature = UseCounter::UnprefixedAnimationStartEvent;
        prefixedAndUnprefixedFeature = UseCounter::PrefixedAndUnprefixedAnimationStartEvent;
    } else if (legacyTypeName == EventTypeNames::webkitAnimationIteration) {
        prefixedFeature = UseCounter::PrefixedAnimationIterationEvent;
        unprefixedFeature = UseCounter::UnprefixedAnimationIterationEvent;
        prefixedAndUnprefixedFeature = UseCounter::PrefixedAndUnprefixedAnimationIterationEvent;
    } else if (legacyTypeName == EventTypeNames::mousewheel) {
        prefixedFeature = UseCounter::MouseWheelEvent;
        unprefixedFeature = UseCounter::WheelEvent;
        prefixedAndUnprefixedFeature = UseCounter::MouseWheelAndWheelEvent;
    } else {
        return;
    }

    if (LocalDOMWindow* executingWindow = this->executingWindow()) {
        if (legacyListenersVector) {
            if (listenersVector)
                UseCounter::count(executingWindow->document(), prefixedAndUnprefixedFeature);
            else
                UseCounter::count(executingWindow->document(), prefixedFeature);
        } else if (listenersVector) {
            UseCounter::count(executingWindow->document(), unprefixedFeature);
        }
    }
}

DispatchEventResult EventTarget::fireEventListeners(Event* event)
{
#if DCHECK_IS_ON()
    DCHECK(!EventDispatchForbiddenScope::isEventDispatchForbidden());
#endif
    DCHECK(event);
    DCHECK(event->wasInitialized());

    EventTargetData* d = eventTargetData();
    if (!d)
        return DispatchEventResult::NotCanceled;

    EventListenerVector* legacyListenersVector = nullptr;
    AtomicString legacyTypeName = legacyType(event);
    if (!legacyTypeName.isEmpty())
        legacyListenersVector = d->eventListenerMap.find(legacyTypeName);

    EventListenerVector* listenersVector = d->eventListenerMap.find(event->type());

    bool firedEventListeners = false;
    if (listenersVector) {
        firedEventListeners = fireEventListeners(event, d, *listenersVector);
    } else if (legacyListenersVector) {
        AtomicString unprefixedTypeName = event->type();
        event->setType(legacyTypeName);
        firedEventListeners = fireEventListeners(event, d, *legacyListenersVector);
        event->setType(unprefixedTypeName);
    }

    // Only invoke the callback if event listeners were fired for this phase.
    if (firedEventListeners)
        event->doneDispatchingEventAtCurrentTarget();

    // TODO(dtapuska): Should we really do counting here for these events
    // if we really didn't fire a listener? For example having a bubbling
    // listener on an event that doesn't bubble likely records a UMA
    // metric where it probably shouldn't because it was never fired.
    // See https://crbug.com/612829
    Editor::countEvent(getExecutionContext(), event);
    countLegacyEvents(legacyTypeName, listenersVector, legacyListenersVector);
    return dispatchEventResult(*event);
}

bool EventTarget::checkTypeThenUseCount(
    const Event* event, const AtomicString& eventTypeToCount, const UseCounter::Feature feature)
{
    if (event->type() == eventTypeToCount) {
        if (LocalDOMWindow* executingWindow = this->executingWindow())
            UseCounter::count(executingWindow->document(), feature);
        return true;
    }
    return false;
}

bool EventTarget::fireEventListeners(Event* event, EventTargetData* d, EventListenerVector& entry)
{
    // Fire all listeners registered for this event. Don't fire listeners removed
    // during event dispatch. Also, don't fire event listeners added during event
    // dispatch. Conveniently, all new event listeners will be added after or at
    // index |size|, so iterating up to (but not including) |size| naturally excludes
    // new event listeners.

    if (checkTypeThenUseCount(event, EventTypeNames::beforeunload, UseCounter::DocumentBeforeUnloadFired)) {
        if (LocalDOMWindow* executingWindow = this->executingWindow()) {
            if (executingWindow != executingWindow->top())
                UseCounter::count(executingWindow->document(), UseCounter::SubFrameBeforeUnloadFired);
        }
    } else if (checkTypeThenUseCount(event, EventTypeNames::unload, UseCounter::DocumentUnloadFired)) {
    } else if (checkTypeThenUseCount(event, EventTypeNames::DOMFocusIn, UseCounter::DOMFocusInOutEvent)) {
    } else if (checkTypeThenUseCount(event, EventTypeNames::DOMFocusOut, UseCounter::DOMFocusInOutEvent)) {
    } else if (checkTypeThenUseCount(event, EventTypeNames::focusin, UseCounter::FocusInOutEvent)) {
    } else if (checkTypeThenUseCount(event, EventTypeNames::focusout, UseCounter::FocusInOutEvent)) {
    } else if (checkTypeThenUseCount(event, EventTypeNames::textInput, UseCounter::TextInputFired)) {
    } else if (checkTypeThenUseCount(event, EventTypeNames::touchstart, UseCounter::TouchStartFired)) {
    } else if (checkTypeThenUseCount(event, EventTypeNames::mousedown, UseCounter::MouseDownFired)) {
    } else if (checkTypeThenUseCount(event, EventTypeNames::pointerdown, UseCounter::PointerDownFired)) {
        if (LocalDOMWindow* executingWindow = this->executingWindow()) {
            if (event->isPointerEvent() && static_cast<PointerEvent*>(event)->pointerType() == "touch")
                UseCounter::count(executingWindow->document(), UseCounter::PointerDownFiredForTouch);
        }
    } else if (checkTypeThenUseCount(event, EventTypeNames::pointerenter, UseCounter::PointerEnterLeaveFired)
        || checkTypeThenUseCount(event, EventTypeNames::pointerleave, UseCounter::PointerEnterLeaveFired)
        || checkTypeThenUseCount(event, EventTypeNames::pointerover, UseCounter::PointerOverOutFired)
        || checkTypeThenUseCount(event, EventTypeNames::pointerout, UseCounter::PointerOverOutFired)) {
        LocalDOMWindow* executingWindow = this->executingWindow();
        Node* node = toNode();
        if (executingWindow && node && node->getNodeType() == Node::kElementNode && event->isPointerEvent()) {
            const Element* element = static_cast<Element*>(node);
            const PointerEvent* pointerEvent = static_cast<PointerEvent*>(event);
            const UseCounter::Feature feature = (event->type() == EventTypeNames::pointerenter || event->type() == EventTypeNames::pointerleave)
                ? UseCounter::PointerEnterLeaveFiredWhileCaptured
                : UseCounter::PointerOverOutFiredWhileCaptured;
            if (element->hasPointerCapture(pointerEvent->pointerId()) && element->hasProcessedPointerCapture(pointerEvent->pointerId()))
                UseCounter::count(executingWindow->document(), feature);
        }
    }

    ExecutionContext* context = getExecutionContext();
    if (!context)
        return false;

    size_t i = 0;
    size_t size = entry.size();
    if (!d->firingEventIterators)
        d->firingEventIterators = wrapUnique(new FiringEventIteratorVector);
    d->firingEventIterators->append(FiringEventIterator(event->type(), i, size));

    double blockedEventThreshold = blockedEventsWarningThreshold(context, event);
    double now = 0.0;
    bool shouldReportBlockedEvent = false;
    if (blockedEventThreshold) {
        now = WTF::monotonicallyIncreasingTime();
        shouldReportBlockedEvent = now - event->platformTimeStamp() > blockedEventThreshold;
    }
    bool firedListener = false;

    while (i < size) {
        RegisteredEventListener registeredListener = entry[i];

        // Move the iterator past this event listener. This must match
        // the handling of the FiringEventIterator::iterator in
        // EventTarget::removeEventListener.
        ++i;

        if (event->eventPhase() == Event::kCapturingPhase && !registeredListener.capture())
            continue;
        if (event->eventPhase() == Event::kBubblingPhase && registeredListener.capture())
            continue;

        EventListener* listener = registeredListener.listener();
        // The listener will be retained by Member<EventListener> in the registeredListener,
        // i and size are updated with the firing event iterator
        // in case the listener is removed from the listener vector below.
        if (registeredListener.once())
            removeEventListener(event->type(), listener, registeredListener.capture());

        // If stopImmediatePropagation has been called, we just break out immediately, without
        // handling any more events on this target.
        if (event->immediatePropagationStopped())
            break;

        event->setHandlingPassive(eventPassiveMode(registeredListener));
        bool passiveForced = registeredListener.passiveForcedForDocumentTarget();

        InspectorInstrumentation::NativeBreakpoint nativeBreakpoint(context, this, event);

        // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
        // event listeners, even though that violates some versions of the DOM spec.
        listener->handleEvent(context, event);
        firedListener = true;

        // If we're about to report this event listener as blocking, make sure it wasn't
        // removed while handling the event.
        if (shouldReportBlockedEvent && i > 0 && entry[i - 1].listener() == listener
            && !entry[i - 1].passive() && !entry[i - 1].blockedEventWarningEmitted() && !event->defaultPrevented()) {
            reportBlockedEvent(context, event, &entry[i - 1], now - event->platformTimeStamp());
        }

        if (passiveForced) {
            DEFINE_STATIC_LOCAL(EnumerationHistogram, passiveForcedHistogram, ("Event.PassiveForcedEventDispatchCancelled", PassiveForcedListenerResultTypeMax));
            PassiveForcedListenerResultType breakageType = PreventDefaultNotCalled;
            if (event->preventDefaultCalledDuringPassive())
                breakageType = DocumentLevelTouchPreventDefaultCalled;

            passiveForcedHistogram.count(breakageType);
        }

        event->setHandlingPassive(Event::PassiveMode::NotPassive);

        CHECK_LE(i, size);
    }
    d->firingEventIterators->removeLast();
    return firedListener;
}

DispatchEventResult EventTarget::dispatchEventResult(const Event& event)
{
    if (event.defaultPrevented())
        return DispatchEventResult::CanceledByEventHandler;
    if (event.defaultHandled())
        return DispatchEventResult::CanceledByDefaultEventHandler;
    return DispatchEventResult::NotCanceled;
}

EventListenerVector* EventTarget::getEventListeners(const AtomicString& eventType)
{
    EventTargetData* data = eventTargetData();
    if (!data)
        return nullptr;
    return data->eventListenerMap.find(eventType);
}

Vector<AtomicString> EventTarget::eventTypes()
{
    EventTargetData* d = eventTargetData();
    return d ? d->eventListenerMap.eventTypes() : Vector<AtomicString>();
}

void EventTarget::removeAllEventListeners()
{
    EventTargetData* d = eventTargetData();
    if (!d)
        return;
    d->eventListenerMap.clear();

    // Notify firing events planning to invoke the listener at 'index' that
    // they have one less listener to invoke.
    if (d->firingEventIterators) {
        for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
            d->firingEventIterators->at(i).iterator = 0;
            d->firingEventIterators->at(i).end = 0;
        }
    }
}

} // namespace blink
