UNPKG

4.97 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2013-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8
9'use strict';
10
11var EventPluginHub = require('./EventPluginHub');
12var EventPluginUtils = require('./EventPluginUtils');
13
14var accumulateInto = require('./accumulateInto');
15var forEachAccumulated = require('./forEachAccumulated');
16var warning = require('fbjs/lib/warning');
17
18var getListener = EventPluginHub.getListener;
19
20/**
21 * Some event types have a notion of different registration names for different
22 * "phases" of propagation. This finds listeners by a given phase.
23 */
24function listenerAtPhase(inst, event, propagationPhase) {
25 var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
26 return getListener(inst, registrationName);
27}
28
29/**
30 * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
31 * here, allows us to not have to bind or create functions for each event.
32 * Mutating the event's members allows us to not have to create a wrapping
33 * "dispatch" object that pairs the event with the listener.
34 */
35function accumulateDirectionalDispatches(inst, phase, event) {
36 if (process.env.NODE_ENV !== 'production') {
37 process.env.NODE_ENV !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0;
38 }
39 var listener = listenerAtPhase(inst, event, phase);
40 if (listener) {
41 event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
42 event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
43 }
44}
45
46/**
47 * Collect dispatches (must be entirely collected before dispatching - see unit
48 * tests). Lazily allocate the array to conserve memory. We must loop through
49 * each event and perform the traversal for each one. We cannot perform a
50 * single traversal for the entire collection of events because each event may
51 * have a different target.
52 */
53function accumulateTwoPhaseDispatchesSingle(event) {
54 if (event && event.dispatchConfig.phasedRegistrationNames) {
55 EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
56 }
57}
58
59/**
60 * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
61 */
62function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
63 if (event && event.dispatchConfig.phasedRegistrationNames) {
64 var targetInst = event._targetInst;
65 var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null;
66 EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
67 }
68}
69
70/**
71 * Accumulates without regard to direction, does not look for phased
72 * registration names. Same as `accumulateDirectDispatchesSingle` but without
73 * requiring that the `dispatchMarker` be the same as the dispatched ID.
74 */
75function accumulateDispatches(inst, ignoredDirection, event) {
76 if (event && event.dispatchConfig.registrationName) {
77 var registrationName = event.dispatchConfig.registrationName;
78 var listener = getListener(inst, registrationName);
79 if (listener) {
80 event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
81 event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
82 }
83 }
84}
85
86/**
87 * Accumulates dispatches on an `SyntheticEvent`, but only for the
88 * `dispatchMarker`.
89 * @param {SyntheticEvent} event
90 */
91function accumulateDirectDispatchesSingle(event) {
92 if (event && event.dispatchConfig.registrationName) {
93 accumulateDispatches(event._targetInst, null, event);
94 }
95}
96
97function accumulateTwoPhaseDispatches(events) {
98 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
99}
100
101function accumulateTwoPhaseDispatchesSkipTarget(events) {
102 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
103}
104
105function accumulateEnterLeaveDispatches(leave, enter, from, to) {
106 EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
107}
108
109function accumulateDirectDispatches(events) {
110 forEachAccumulated(events, accumulateDirectDispatchesSingle);
111}
112
113/**
114 * A small set of propagation patterns, each of which will accept a small amount
115 * of information, and generate a set of "dispatch ready event objects" - which
116 * are sets of events that have already been annotated with a set of dispatched
117 * listener functions/ids. The API is designed this way to discourage these
118 * propagation strategies from actually executing the dispatches, since we
119 * always want to collect the entire set of dispatches before executing event a
120 * single one.
121 *
122 * @constructor EventPropagators
123 */
124var EventPropagators = {
125 accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
126 accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
127 accumulateDirectDispatches: accumulateDirectDispatches,
128 accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches
129};
130
131module.exports = EventPropagators;
\No newline at end of file