function setResponderAndExtractTransfer(
  topLevelType,
  targetInst,
  nativeEvent,
  nativeEventTarget
) {
  var shouldSetEventType = isStartish(topLevelType)
    ? eventTypes.startShouldSetResponder
    : isMoveish(topLevelType)
      ? eventTypes.moveShouldSetResponder
      : topLevelType === "topSelectionChange"
        ? eventTypes.selectionChangeShouldSetResponder
        : eventTypes.scrollShouldSetResponder;

  // TODO: stop one short of the current responder.
  var bubbleShouldSetFrom = !responderInst
    ? targetInst
    : getLowestCommonAncestor(responderInst, targetInst);

  // When capturing/bubbling the "shouldSet" event, we want to skip the target
  // (deepest ID) if it happens to be the current responder. The reasoning:
  // It's strange to get an `onMoveShouldSetResponder` when you're *already*
  // the responder.
  var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst;
  var shouldSetEvent = ResponderSyntheticEvent.getPooled(
    shouldSetEventType,
    bubbleShouldSetFrom,
    nativeEvent,
    nativeEventTarget
  );
  shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
  if (skipOverBubbleShouldSetFrom) {
    accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);
  } else {
    accumulateTwoPhaseDispatches(shouldSetEvent);
  }
  var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent);
  if (!shouldSetEvent.isPersistent()) {
    shouldSetEvent.constructor.release(shouldSetEvent);
  }

  if (!wantsResponderInst || wantsResponderInst === responderInst) {
    return null;
  }
  var extracted;
  var grantEvent = ResponderSyntheticEvent.getPooled(
    eventTypes.responderGrant,
    wantsResponderInst,
    nativeEvent,
    nativeEventTarget
  );
  grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;

  accumulateDirectDispatches(grantEvent);
  var blockHostResponder = executeDirectDispatch(grantEvent) === true;
  if (responderInst) {
    var terminationRequestEvent = ResponderSyntheticEvent.getPooled(
      eventTypes.responderTerminationRequest,
      responderInst,
      nativeEvent,
      nativeEventTarget
    );
    terminationRequestEvent.touchHistory =
      ResponderTouchHistoryStore.touchHistory;
    accumulateDirectDispatches(terminationRequestEvent);
    var shouldSwitch =
      !hasDispatches(terminationRequestEvent) ||
      executeDirectDispatch(terminationRequestEvent);
    if (!terminationRequestEvent.isPersistent()) {
      terminationRequestEvent.constructor.release(terminationRequestEvent);
    }

    if (shouldSwitch) {
      var terminateEvent = ResponderSyntheticEvent.getPooled(
        eventTypes.responderTerminate,
        responderInst,
        nativeEvent,
        nativeEventTarget
      );
      terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
      accumulateDirectDispatches(terminateEvent);
      extracted = accumulate(extracted, [grantEvent, terminateEvent]);
      changeResponder(wantsResponderInst, blockHostResponder);
    } else {
      var rejectEvent = ResponderSyntheticEvent.getPooled(
        eventTypes.responderReject,
        wantsResponderInst,
        nativeEvent,
        nativeEventTarget
      );
      rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
      accumulateDirectDispatches(rejectEvent);
      extracted = accumulate(extracted, rejectEvent);
    }
  } else {
    extracted = accumulate(extracted, grantEvent);
    changeResponder(wantsResponderInst, blockHostResponder);
  }
  return extracted;
}
A note about event ordering in the `EventPluginHub`.

Suppose plugins are injected in the following order:

`[R, S, C]`

To help illustrate the example, assume `S` is `SimpleEventPlugin` (for
`onClick` etc) and `R` is `ResponderEventPlugin`.

"Deferred-Dispatched Events":

- The current event plugin system will traverse the list of injected plugins,
  in order, and extract events by collecting the plugin's return value of
  `extractEvents()`.
- These events that are returned from `extractEvents` are "deferred
  dispatched events".
- When returned from `extractEvents`, deferred-dispatched events contain an
  "accumulation" of deferred dispatches.
- These deferred dispatches are accumulated/collected before they are
  returned, but processed at a later time by the `EventPluginHub` (hence the
  name deferred).

In the process of returning their deferred-dispatched events, event plugins
themselves can dispatch events on-demand without returning them from
`extractEvents`. Plugins might want to do this, so that they can use event
dispatching as a tool that helps them decide which events should be extracted
in the first place.

"On-Demand-Dispatched Events":

- On-demand-dispatched events are not returned from `extractEvents`.
- On-demand-dispatched events are dispatched during the process of returning
  the deferred-dispatched events.
- They should not have side effects.
- They should be avoided, and/or eventually be replaced with another
  abstraction that allows event plugins to perform multiple "rounds" of event
  extraction.

Therefore, the sequence of event dispatches becomes:

- `R`s on-demand events (if any)   (dispatched by `R` on-demand)
- `S`s on-demand events (if any)   (dispatched by `S` on-demand)
- `C`s on-demand events (if any)   (dispatched by `C` on-demand)
- `R`s extracted events (if any)   (dispatched by `EventPluginHub`)
- `S`s extracted events (if any)   (dispatched by `EventPluginHub`)
- `C`s extracted events (if any)   (dispatched by `EventPluginHub`)

In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`
on-demand dispatch returns `true` (and some other details are satisfied) the
`onResponderGrant` deferred dispatched event is returned from
`extractEvents`. The sequence of dispatch executions in this case
will appear as follows:

- `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)
- `touchStartCapture`       (`EventPluginHub` dispatches as usual)
- `touchStart`              (`EventPluginHub` dispatches as usual)
- `responderGrant/Reject`   (`EventPluginHub` dispatches as usual)