UNPKG

7.82 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 _prodInvariant = require('./reactProdInvariant');
12
13var ReactErrorUtils = require('./ReactErrorUtils');
14
15var invariant = require('fbjs/lib/invariant');
16var warning = require('fbjs/lib/warning');
17
18/**
19 * Injected dependencies:
20 */
21
22/**
23 * - `ComponentTree`: [required] Module that can convert between React instances
24 * and actual node references.
25 */
26var ComponentTree;
27var TreeTraversal;
28var injection = {
29 injectComponentTree: function (Injected) {
30 ComponentTree = Injected;
31 if (process.env.NODE_ENV !== 'production') {
32 process.env.NODE_ENV !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0;
33 }
34 },
35 injectTreeTraversal: function (Injected) {
36 TreeTraversal = Injected;
37 if (process.env.NODE_ENV !== 'production') {
38 process.env.NODE_ENV !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0;
39 }
40 }
41};
42
43function isEndish(topLevelType) {
44 return topLevelType === 'topMouseUp' || topLevelType === 'topTouchEnd' || topLevelType === 'topTouchCancel';
45}
46
47function isMoveish(topLevelType) {
48 return topLevelType === 'topMouseMove' || topLevelType === 'topTouchMove';
49}
50function isStartish(topLevelType) {
51 return topLevelType === 'topMouseDown' || topLevelType === 'topTouchStart';
52}
53
54var validateEventDispatches;
55if (process.env.NODE_ENV !== 'production') {
56 validateEventDispatches = function (event) {
57 var dispatchListeners = event._dispatchListeners;
58 var dispatchInstances = event._dispatchInstances;
59
60 var listenersIsArr = Array.isArray(dispatchListeners);
61 var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
62
63 var instancesIsArr = Array.isArray(dispatchInstances);
64 var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
65
66 process.env.NODE_ENV !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0;
67 };
68}
69
70/**
71 * Dispatch the event to the listener.
72 * @param {SyntheticEvent} event SyntheticEvent to handle
73 * @param {boolean} simulated If the event is simulated (changes exn behavior)
74 * @param {function} listener Application-level callback
75 * @param {*} inst Internal component instance
76 */
77function executeDispatch(event, simulated, listener, inst) {
78 var type = event.type || 'unknown-event';
79 event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);
80 if (simulated) {
81 ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event);
82 } else {
83 ReactErrorUtils.invokeGuardedCallback(type, listener, event);
84 }
85 event.currentTarget = null;
86}
87
88/**
89 * Standard/simple iteration through an event's collected dispatches.
90 */
91function executeDispatchesInOrder(event, simulated) {
92 var dispatchListeners = event._dispatchListeners;
93 var dispatchInstances = event._dispatchInstances;
94 if (process.env.NODE_ENV !== 'production') {
95 validateEventDispatches(event);
96 }
97 if (Array.isArray(dispatchListeners)) {
98 for (var i = 0; i < dispatchListeners.length; i++) {
99 if (event.isPropagationStopped()) {
100 break;
101 }
102 // Listeners and Instances are two parallel arrays that are always in sync.
103 executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);
104 }
105 } else if (dispatchListeners) {
106 executeDispatch(event, simulated, dispatchListeners, dispatchInstances);
107 }
108 event._dispatchListeners = null;
109 event._dispatchInstances = null;
110}
111
112/**
113 * Standard/simple iteration through an event's collected dispatches, but stops
114 * at the first dispatch execution returning true, and returns that id.
115 *
116 * @return {?string} id of the first dispatch execution who's listener returns
117 * true, or null if no listener returned true.
118 */
119function executeDispatchesInOrderStopAtTrueImpl(event) {
120 var dispatchListeners = event._dispatchListeners;
121 var dispatchInstances = event._dispatchInstances;
122 if (process.env.NODE_ENV !== 'production') {
123 validateEventDispatches(event);
124 }
125 if (Array.isArray(dispatchListeners)) {
126 for (var i = 0; i < dispatchListeners.length; i++) {
127 if (event.isPropagationStopped()) {
128 break;
129 }
130 // Listeners and Instances are two parallel arrays that are always in sync.
131 if (dispatchListeners[i](event, dispatchInstances[i])) {
132 return dispatchInstances[i];
133 }
134 }
135 } else if (dispatchListeners) {
136 if (dispatchListeners(event, dispatchInstances)) {
137 return dispatchInstances;
138 }
139 }
140 return null;
141}
142
143/**
144 * @see executeDispatchesInOrderStopAtTrueImpl
145 */
146function executeDispatchesInOrderStopAtTrue(event) {
147 var ret = executeDispatchesInOrderStopAtTrueImpl(event);
148 event._dispatchInstances = null;
149 event._dispatchListeners = null;
150 return ret;
151}
152
153/**
154 * Execution of a "direct" dispatch - there must be at most one dispatch
155 * accumulated on the event or it is considered an error. It doesn't really make
156 * sense for an event with multiple dispatches (bubbled) to keep track of the
157 * return values at each dispatch execution, but it does tend to make sense when
158 * dealing with "direct" dispatches.
159 *
160 * @return {*} The return value of executing the single dispatch.
161 */
162function executeDirectDispatch(event) {
163 if (process.env.NODE_ENV !== 'production') {
164 validateEventDispatches(event);
165 }
166 var dispatchListener = event._dispatchListeners;
167 var dispatchInstance = event._dispatchInstances;
168 !!Array.isArray(dispatchListener) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : _prodInvariant('103') : void 0;
169 event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null;
170 var res = dispatchListener ? dispatchListener(event) : null;
171 event.currentTarget = null;
172 event._dispatchListeners = null;
173 event._dispatchInstances = null;
174 return res;
175}
176
177/**
178 * @param {SyntheticEvent} event
179 * @return {boolean} True iff number of dispatches accumulated is greater than 0.
180 */
181function hasDispatches(event) {
182 return !!event._dispatchListeners;
183}
184
185/**
186 * General utilities that are useful in creating custom Event Plugins.
187 */
188var EventPluginUtils = {
189 isEndish: isEndish,
190 isMoveish: isMoveish,
191 isStartish: isStartish,
192
193 executeDirectDispatch: executeDirectDispatch,
194 executeDispatchesInOrder: executeDispatchesInOrder,
195 executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
196 hasDispatches: hasDispatches,
197
198 getInstanceFromNode: function (node) {
199 return ComponentTree.getInstanceFromNode(node);
200 },
201 getNodeFromInstance: function (node) {
202 return ComponentTree.getNodeFromInstance(node);
203 },
204 isAncestor: function (a, b) {
205 return TreeTraversal.isAncestor(a, b);
206 },
207 getLowestCommonAncestor: function (a, b) {
208 return TreeTraversal.getLowestCommonAncestor(a, b);
209 },
210 getParentInstance: function (inst) {
211 return TreeTraversal.getParentInstance(inst);
212 },
213 traverseTwoPhase: function (target, fn, arg) {
214 return TreeTraversal.traverseTwoPhase(target, fn, arg);
215 },
216 traverseEnterLeave: function (from, to, fn, argFrom, argTo) {
217 return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);
218 },
219
220 injection: injection
221};
222
223module.exports = EventPluginUtils;
\No newline at end of file