mirror of
https://github.com/zebrajr/react.git
synced 2025-12-07 00:20:28 +01:00
* Inline fbjs/lib/invariant * Inline fbjs/lib/warning * Remove remaining usage of fbjs in packages/*.js * Fix lint * Remove fbjs from dependencies * Protect against accidental fbjs imports * Fix broken test mocks * Allow transitive deps on fbjs/ for UMD bundles * Remove fbjs from release script
130 lines
4.5 KiB
JavaScript
130 lines
4.5 KiB
JavaScript
/**
|
|
* Copyright (c) 2013-present, Facebook, Inc.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
import {
|
|
getParentInstance,
|
|
traverseTwoPhase,
|
|
traverseEnterLeave,
|
|
} from 'shared/ReactTreeTraversal';
|
|
import warning from 'shared/warning';
|
|
|
|
import {getListener} from './EventPluginHub';
|
|
import accumulateInto from './accumulateInto';
|
|
import forEachAccumulated from './forEachAccumulated';
|
|
|
|
type PropagationPhases = 'bubbled' | 'captured';
|
|
|
|
/**
|
|
* Some event types have a notion of different registration names for different
|
|
* "phases" of propagation. This finds listeners by a given phase.
|
|
*/
|
|
function listenerAtPhase(inst, event, propagationPhase: PropagationPhases) {
|
|
const registrationName =
|
|
event.dispatchConfig.phasedRegistrationNames[propagationPhase];
|
|
return getListener(inst, registrationName);
|
|
}
|
|
|
|
/**
|
|
* A small set of propagation patterns, each of which will accept a small amount
|
|
* of information, and generate a set of "dispatch ready event objects" - which
|
|
* are sets of events that have already been annotated with a set of dispatched
|
|
* listener functions/ids. The API is designed this way to discourage these
|
|
* propagation strategies from actually executing the dispatches, since we
|
|
* always want to collect the entire set of dispatches before executing even a
|
|
* single one.
|
|
*/
|
|
|
|
/**
|
|
* Tags a `SyntheticEvent` with dispatched listeners. Creating this function
|
|
* here, allows us to not have to bind or create functions for each event.
|
|
* Mutating the event's members allows us to not have to create a wrapping
|
|
* "dispatch" object that pairs the event with the listener.
|
|
*/
|
|
function accumulateDirectionalDispatches(inst, phase, event) {
|
|
if (__DEV__) {
|
|
warning(inst, 'Dispatching inst must not be null');
|
|
}
|
|
const listener = listenerAtPhase(inst, event, phase);
|
|
if (listener) {
|
|
event._dispatchListeners = accumulateInto(
|
|
event._dispatchListeners,
|
|
listener,
|
|
);
|
|
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Collect dispatches (must be entirely collected before dispatching - see unit
|
|
* tests). Lazily allocate the array to conserve memory. We must loop through
|
|
* each event and perform the traversal for each one. We cannot perform a
|
|
* single traversal for the entire collection of events because each event may
|
|
* have a different target.
|
|
*/
|
|
function accumulateTwoPhaseDispatchesSingle(event) {
|
|
if (event && event.dispatchConfig.phasedRegistrationNames) {
|
|
traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
|
|
*/
|
|
function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
|
|
if (event && event.dispatchConfig.phasedRegistrationNames) {
|
|
const targetInst = event._targetInst;
|
|
const parentInst = targetInst ? getParentInstance(targetInst) : null;
|
|
traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Accumulates without regard to direction, does not look for phased
|
|
* registration names. Same as `accumulateDirectDispatchesSingle` but without
|
|
* requiring that the `dispatchMarker` be the same as the dispatched ID.
|
|
*/
|
|
function accumulateDispatches(inst, ignoredDirection, event) {
|
|
if (inst && event && event.dispatchConfig.registrationName) {
|
|
const registrationName = event.dispatchConfig.registrationName;
|
|
const listener = getListener(inst, registrationName);
|
|
if (listener) {
|
|
event._dispatchListeners = accumulateInto(
|
|
event._dispatchListeners,
|
|
listener,
|
|
);
|
|
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Accumulates dispatches on an `SyntheticEvent`, but only for the
|
|
* `dispatchMarker`.
|
|
* @param {SyntheticEvent} event
|
|
*/
|
|
function accumulateDirectDispatchesSingle(event) {
|
|
if (event && event.dispatchConfig.registrationName) {
|
|
accumulateDispatches(event._targetInst, null, event);
|
|
}
|
|
}
|
|
|
|
export function accumulateTwoPhaseDispatches(events) {
|
|
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
|
|
}
|
|
|
|
export function accumulateTwoPhaseDispatchesSkipTarget(events) {
|
|
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
|
|
}
|
|
|
|
export function accumulateEnterLeaveDispatches(leave, enter, from, to) {
|
|
traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
|
|
}
|
|
|
|
export function accumulateDirectDispatches(events) {
|
|
forEachAccumulated(events, accumulateDirectDispatchesSingle);
|
|
}
|