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