function eventListener(domEvent) {
  var eventType = domEvent.type;
  var eventTarget = domEvent.target;
  /**
   * Manage emulated events and early bailout.
   * Since PointerEvent is not used yet (lack of support in older Safari), it's
   * necessary to manually manage the mess of browser touch/mouse events.
   * And bailout early for termination events when there is no active responder.
   */
  // Flag when browser may produce emulated events

  if (eventType === 'touchstart') {
    isEmulatingMouseEvents = true;
  } // Remove flag when browser will not produce emulated events


  if (eventType === 'touchmove' || trackedTouchCount > 1) {
    isEmulatingMouseEvents = false;
  } // Ignore various events in particular circumstances


  if ( // Ignore browser emulated mouse events
  eventType === 'mousedown' && isEmulatingMouseEvents || eventType === 'mousemove' && isEmulatingMouseEvents || // Ignore mousemove if a mousedown didn't occur first
  eventType === 'mousemove' && trackedTouchCount < 1) {
    return;
  } // Remove flag after emulated events are finished


  if (isEmulatingMouseEvents && eventType === 'mouseup') {
    if (trackedTouchCount === 0) {
      isEmulatingMouseEvents = false;
    }

    return;
  }

  var isStartEvent = isStartish(eventType) && isPrimaryPointerDown(domEvent);
  var isMoveEvent = isMoveish(eventType);
  var isEndEvent = isEndish(eventType);
  var isScrollEvent = isScroll(eventType);
  var isSelectionChangeEvent = isSelectionChange(eventType);
  var responderEvent = createResponderEvent(domEvent);
  /**
   * Record the state of active pointers
   */

  if (isStartEvent || isMoveEvent || isEndEvent) {
    if (domEvent.touches) {
      trackedTouchCount = domEvent.touches.length;
    } else {
      if (isStartEvent) {
        trackedTouchCount = 1;
      } else if (isEndEvent) {
        trackedTouchCount = 0;
      }
    }

    useResponderEvents_ResponderTouchHistoryStore.recordTouchTrack(eventType, responderEvent.nativeEvent);
  }
  /**
   * Responder System logic
   */


  var eventPaths = getResponderPaths(domEvent);
  var wasNegotiated = false;
  var wantsResponder; // If an event occured that might change the current responder...

  if (isStartEvent || isMoveEvent || isScrollEvent && trackedTouchCount > 0) {
    // If there is already a responder, prune the event paths to the lowest common ancestor
    // of the existing responder and deepest target of the event.
    var currentResponderIdPath = currentResponder.idPath;
    var eventIdPath = eventPaths.idPath;

    if (currentResponderIdPath != null && eventIdPath != null) {
      var lowestCommonAncestor = getLowestCommonAncestor(currentResponderIdPath, eventIdPath);

      if (lowestCommonAncestor != null) {
        var indexOfLowestCommonAncestor = eventIdPath.indexOf(lowestCommonAncestor); // Skip the current responder so it doesn't receive unexpected "shouldSet" events.

        var index = indexOfLowestCommonAncestor + (lowestCommonAncestor === currentResponder.id ? 1 : 0);
        eventPaths = {
          idPath: eventIdPath.slice(index),
          nodePath: eventPaths.nodePath.slice(index)
        };
      } else {
        eventPaths = null;
      }
    }

    if (eventPaths != null) {
      // If a node wants to become the responder, attempt to transfer.
      wantsResponder = findWantsResponder(eventPaths, domEvent, responderEvent);

      if (wantsResponder != null) {
        // Sets responder if none exists, or negotates with existing responder.
        attemptTransfer(responderEvent, wantsResponder);
        wasNegotiated = true;
      }
    }
  } // If there is now a responder, invoke its callbacks for the lifecycle of the gesture.


  if (currentResponder.id != null && currentResponder.node != null) {
    var _currentResponder = currentResponder,
        id = _currentResponder.id,
        node = _currentResponder.node;

    var _getResponderConfig = getResponderConfig(id),
        onResponderStart = _getResponderConfig.onResponderStart,
        onResponderMove = _getResponderConfig.onResponderMove,
        onResponderEnd = _getResponderConfig.onResponderEnd,
        onResponderRelease = _getResponderConfig.onResponderRelease,
        onResponderTerminate = _getResponderConfig.onResponderTerminate,
        onResponderTerminationRequest = _getResponderConfig.onResponderTerminationRequest;

    responderEvent.bubbles = false;
    responderEvent.cancelable = false;
    responderEvent.currentTarget = node; // Start

    if (isStartEvent) {
      if (onResponderStart != null) {
        responderEvent.dispatchConfig.registrationName = 'onResponderStart';
        onResponderStart(responderEvent);
      }
    } // Move
    else if (isMoveEvent) {
        if (onResponderMove != null) {
          responderEvent.dispatchConfig.registrationName = 'onResponderMove';
          onResponderMove(responderEvent);
        }
      } else {
        var isTerminateEvent = isCancelish(eventType) || // native context menu
        eventType === 'contextmenu' || // window blur
        eventType === 'blur' && eventTarget === window || // responder (or ancestors) blur
        eventType === 'blur' && eventTarget.contains(node) && domEvent.relatedTarget !== node || // native scroll without using a pointer
        isScrollEvent && trackedTouchCount === 0 || // native scroll on node that is parent of the responder (allow siblings to scroll)
        isScrollEvent && eventTarget.contains(node) && eventTarget !== node || // native select/selectionchange on node
        isSelectionChangeEvent && hasValidSelection(domEvent);
        var isReleaseEvent = isEndEvent && !isTerminateEvent && !hasTargetTouches(node, domEvent.touches); // End

        if (isEndEvent) {
          if (onResponderEnd != null) {
            responderEvent.dispatchConfig.registrationName = 'onResponderEnd';
            onResponderEnd(responderEvent);
          }
        } // Release


        if (isReleaseEvent) {
          if (onResponderRelease != null) {
            responderEvent.dispatchConfig.registrationName = 'onResponderRelease';
            onResponderRelease(responderEvent);
          }

          changeCurrentResponder(emptyResponder);
        } // Terminate


        if (isTerminateEvent) {
          var shouldTerminate = true; // Responders can still avoid termination but only for these events.

          if (eventType === 'contextmenu' || eventType === 'scroll' || eventType === 'selectionchange') {
            // Only call this function is it wasn't already called during negotiation.
            if (wasNegotiated) {
              shouldTerminate = false;
            } else if (onResponderTerminationRequest != null) {
              responderEvent.dispatchConfig.registrationName = 'onResponderTerminationRequest';

              if (onResponderTerminationRequest(responderEvent) === false) {
                shouldTerminate = false;
              }
            }
          }

          if (shouldTerminate) {
            if (onResponderTerminate != null) {
              responderEvent.dispatchConfig.registrationName = 'onResponderTerminate';
              onResponderTerminate(responderEvent);
            }

            changeCurrentResponder(emptyResponder);
            isEmulatingMouseEvents = false;
            trackedTouchCount = 0;
          }
        }
      }
  }
}
Process native events

A single event listener is used to manage the responder system.
All pointers are tracked in the ResponderTouchHistoryStore. Native events
are interpreted in terms of the Responder System and checked to see if
the responder should be transferred. Each host node that is attached to
the Responder System has an ID, which is used to look up its associated
callbacks.