Ejemplo n.º 1
0
void EventTarget::fireEventListeners(Event& event, EventTargetData* d, EventListenerVector& entry)
{
    Ref<EventTarget> protectedThis(*this);

    // 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.

    size_t i = 0;
    size_t size = entry.size();
    if (!d->firingEventIterators)
        d->firingEventIterators = std::make_unique<FiringEventIteratorVector>();
    d->firingEventIterators->append(FiringEventIterator(event.type(), i, size));

    ScriptExecutionContext* context = scriptExecutionContext();
    Document* document = nullptr;
    InspectorInstrumentationCookie willDispatchEventCookie;
    if (is<Document>(context)) {
        document = downcast<Document>(context);
        willDispatchEventCookie = InspectorInstrumentation::willDispatchEvent(*document, event, size > 0);
    }

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

        if (event.eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture)
            continue;
        if (event.eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture)
            continue;

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

        // Do this before invocation to avoid reentrancy issues.
        if (registeredListener.isOnce)
            removeEventListener(event.type(), *registeredListener.listener, ListenerOptions(registeredListener.useCapture));

        if (registeredListener.isPassive)
            event.setInPassiveListener(true);

        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willHandleEvent(context, 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.
        registeredListener.listener->handleEvent(context, &event);
        InspectorInstrumentation::didHandleEvent(cookie);

        if (registeredListener.isPassive)
            event.setInPassiveListener(false);
    }

    d->firingEventIterators->removeLast();

    if (document)
        InspectorInstrumentation::didDispatchEvent(willDispatchEventCookie);
}
Ejemplo n.º 2
0
void EventTarget::fireEventListeners(Event* event, EventTargetData* d, EventListenerVector& entry)
{
    RefPtrWillBeRawPtr<EventTarget> protect(this);

    // 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 (event->type() == EventTypeNames::beforeunload) {
        if (LocalDOMWindow* executingWindow = this->executingWindow()) {
            if (executingWindow->top())
                UseCounter::count(executingWindow->document(), UseCounter::SubFrameBeforeUnloadFired);
            UseCounter::count(executingWindow->document(), UseCounter::DocumentBeforeUnloadFired);
        }
    } else if (event->type() == EventTypeNames::unload) {
        if (LocalDOMWindow* executingWindow = this->executingWindow())
            UseCounter::count(executingWindow->document(), UseCounter::DocumentUnloadFired);
    } else if (event->type() == EventTypeNames::DOMFocusIn || event->type() == EventTypeNames::DOMFocusOut) {
        if (LocalDOMWindow* executingWindow = this->executingWindow())
            UseCounter::count(executingWindow->document(), UseCounter::DOMFocusInOutEvent);
    } else if (event->type() == EventTypeNames::focusin || event->type() == EventTypeNames::focusout) {
        if (LocalDOMWindow* executingWindow = this->executingWindow())
            UseCounter::count(executingWindow->document(), UseCounter::FocusInOutEvent);
    }

    size_t i = 0;
    size_t size = entry.size();
    if (!d->firingEventIterators)
        d->firingEventIterators = adoptPtr(new FiringEventIteratorVector);
    d->firingEventIterators->append(FiringEventIterator(event->type(), i, size));
    for ( ; i < size; ++i) {
        RegisteredEventListener& registeredListener = entry[i];
        if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture)
            continue;
        if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.useCapture)
            continue;

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

        ExecutionContext* context = executionContext();
        if (!context)
            break;

        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willHandleEvent(this, event, registeredListener.listener.get(), registeredListener.useCapture);
        // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
        // event listeners, even though that violates some versions of the DOM spec.
        registeredListener.listener->handleEvent(context, event);
        InspectorInstrumentation::didHandleEvent(cookie);
    }
    d->firingEventIterators->removeLast();
}