lib/jsdom/living/events/EventTarget-impl.js
function innerInvokeEventListeners(eventImpl, listeners) {
  let found = false;

  const { type, target } = eventImpl;
  const wrapper = idlUtils.wrapperForImpl(target);

  if (!listeners || !listeners[type]) {
    return found;
  }

  // Copy event listeners before iterating since the list can be modified during the iteration.
  const handlers = listeners[type].slice();

  for (let i = 0; i < handlers.length; i++) {
    const listener = handlers[i];
    const { capture, once, passive } = listener.options;

    // Check if the event listener has been removed since the listeners has been cloned.
    if (!listeners[type].includes(listener)) {
      continue;
    }

    found = true;

    if (
      (eventImpl.eventPhase === Event.CAPTURING_PHASE && !capture) ||
      (eventImpl.eventPhase === Event.BUBBLING_PHASE && capture)
    ) {
      continue;
    }

    if (once) {
      listeners[type].splice(listeners[type].indexOf(listener), 1);
    }

    if (passive) {
      eventImpl._inPassiveListenerFlag = true;
    }

    try {
      if (typeof listener.callback === "object") {
        if (typeof listener.callback.handleEvent === "function") {
          listener.callback.handleEvent(idlUtils.wrapperForImpl(eventImpl));
        }
      } else {
        listener.callback.call(eventImpl.currentTarget, idlUtils.wrapperForImpl(eventImpl));
      }
    } catch (e) {
      let window = null;
      if (wrapper && wrapper._document) {
        // Triggered by Window
        window = wrapper;
      } else if (target._ownerDocument) {
        // Triggered by most webidl2js'ed instances
        window = target._ownerDocument._defaultView;
      } else if (wrapper._ownerDocument) {
        // Currently triggered by XHR and some other non-webidl2js things
        window = wrapper._ownerDocument._defaultView;
      }

      if (window) {
        reportException(window, e);
      }
      // Errors in window-less documents just get swallowed... can you think of anything better?
    }

    eventImpl._inPassiveListenerFlag = false;

    if (eventImpl._stopImmediatePropagationFlag) {
      return found;
    }
  }

  return found;
}
function innerInvokeEventListeners(eventImpl, listeners) {
  let found = false;

  const { type, target } = eventImpl;
  const wrapper = idlUtils.wrapperForImpl(target);

  if (!listeners || !listeners[type]) {
    return found;
  }

  // Copy event listeners before iterating since the list can be modified during the iteration.
  const handlers = listeners[type].slice();

  for (let i = 0; i < handlers.length; i++) {
    const listener = handlers[i];
    const { capture, once, passive } = listener.options;

    // Check if the event listener has been removed since the listeners has been cloned.
    if (!listeners[type].includes(listener)) {
      continue;
    }

    found = true;

    if (
      (eventImpl.eventPhase === Event.CAPTURING_PHASE && !capture) ||
      (eventImpl.eventPhase === Event.BUBBLING_PHASE && capture)
    ) {
      continue;
    }

    if (once) {
      listeners[type].splice(listeners[type].indexOf(listener), 1);
    }

    if (passive) {
      eventImpl._inPassiveListenerFlag = true;
    }

    try {
      if (typeof listener.callback === "object") {
        if (typeof listener.callback.handleEvent === "function") {
          listener.callback.handleEvent(idlUtils.wrapperForImpl(eventImpl));
        }
      } else {
        listener.callback.call(eventImpl.currentTarget, idlUtils.wrapperForImpl(eventImpl));
      }
    } catch (e) {
      let window = null;
      if (wrapper && wrapper._document) {
        // Triggered by Window
        window = wrapper;
      } else if (target._ownerDocument) {
        // Triggered by most webidl2js'ed instances
        window = target._ownerDocument._defaultView;
      } else if (wrapper._ownerDocument) {
        // Currently triggered by XHR and some other non-webidl2js things
        window = wrapper._ownerDocument._defaultView;
      }

      if (window) {
        reportException(window, e);
      }
      // Errors in window-less documents just get swallowed... can you think of anything better?
    }

    eventImpl._inPassiveListenerFlag = false;

    if (eventImpl._stopImmediatePropagationFlag) {
      return found;
    }
  }

  return found;
}
https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke