react-dom 16.12.0 → 16.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-info.json +4 -4
- package/cjs/react-dom-server.browser.development.js +331 -594
- package/cjs/react-dom-server.browser.production.min.js +37 -37
- package/cjs/react-dom-server.node.development.js +330 -593
- package/cjs/react-dom-server.node.production.min.js +38 -38
- package/cjs/react-dom-test-utils.development.js +171 -328
- package/cjs/react-dom-test-utils.production.min.js +17 -17
- package/cjs/react-dom-unstable-fizz.browser.development.js +3 -21
- package/cjs/react-dom-unstable-fizz.browser.production.min.js +2 -2
- package/cjs/react-dom-unstable-fizz.node.development.js +2 -18
- package/cjs/react-dom-unstable-fizz.node.production.min.js +3 -3
- package/cjs/react-dom-unstable-native-dependencies.development.js +190 -305
- package/cjs/react-dom-unstable-native-dependencies.production.min.js +23 -27
- package/cjs/react-dom.development.js +11227 -13976
- package/cjs/react-dom.production.min.js +280 -278
- package/cjs/react-dom.profiling.min.js +287 -284
- package/package.json +3 -8
- package/umd/react-dom-server.browser.development.js +3320 -3594
- package/umd/react-dom-server.browser.production.min.js +35 -35
- package/umd/react-dom-test-utils.development.js +1200 -1357
- package/umd/react-dom-test-utils.production.min.js +23 -23
- package/umd/react-dom-unstable-fizz.browser.development.js +105 -123
- package/umd/react-dom-unstable-fizz.browser.production.min.js +3 -3
- package/umd/react-dom-unstable-native-dependencies.development.js +1333 -1449
- package/umd/react-dom-unstable-native-dependencies.production.min.js +21 -22
- package/umd/react-dom.development.js +19953 -22713
- package/umd/react-dom.production.min.js +229 -232
- package/umd/react-dom.profiling.min.js +236 -239
- package/cjs/react-dom-unstable-flight-client.development.js +0 -357
- package/cjs/react-dom-unstable-flight-client.production.min.js +0 -16
- package/cjs/react-dom-unstable-flight-server.browser.development.js +0 -392
- package/cjs/react-dom-unstable-flight-server.browser.production.min.js +0 -16
- package/cjs/react-dom-unstable-flight-server.node.development.js +0 -415
- package/cjs/react-dom-unstable-flight-server.node.production.min.js +0 -16
- package/umd/react-dom-unstable-flight-client.development.js +0 -357
- package/umd/react-dom-unstable-flight-client.production.min.js +0 -14
- package/umd/react-dom-unstable-flight-server.browser.development.js +0 -390
- package/umd/react-dom-unstable-flight-server.browser.production.min.js +0 -14
- package/unstable-flight-client.js +0 -7
- package/unstable-flight-server.browser.js +0 -7
- package/unstable-flight-server.js +0 -3
- package/unstable-flight-server.node.js +0 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license React v16.
|
|
1
|
+
/** @license React v16.13.0
|
|
2
2
|
* react-dom-unstable-native-dependencies.development.js
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
@@ -10,1735 +10,1619 @@
|
|
|
10
10
|
'use strict';
|
|
11
11
|
|
|
12
12
|
(function (global, factory) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}(this, (function (ReactDOM,React) { 'use strict';
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* to provide information about what broke and what you were
|
|
27
|
-
* expecting.
|
|
28
|
-
*
|
|
29
|
-
* The invariant message will be stripped in production, but the invariant
|
|
30
|
-
* will remain to ensure logic does not differ in production.
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
// In DEV mode, we swap out invokeGuardedCallback for a special version
|
|
35
|
-
// that plays more nicely with the browser's DevTools. The idea is to preserve
|
|
36
|
-
// "Pause on exceptions" behavior. Because React wraps all user-provided
|
|
37
|
-
// functions in invokeGuardedCallback, and the production version of
|
|
38
|
-
// invokeGuardedCallback uses a try-catch, all user exceptions are treated
|
|
39
|
-
// like caught exceptions, and the DevTools won't pause unless the developer
|
|
40
|
-
// takes the extra step of enabling pause on caught exceptions. This is
|
|
41
|
-
// unintuitive, though, because even though React has caught the error, from
|
|
42
|
-
// the developer's perspective, the error is uncaught.
|
|
43
|
-
//
|
|
44
|
-
// To preserve the expected "Pause on exceptions" behavior, we don't use a
|
|
45
|
-
// try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake
|
|
46
|
-
// DOM node, and call the user-provided callback from inside an event handler
|
|
47
|
-
// for that fake event. If the callback throws, the error is "captured" using
|
|
48
|
-
// a global event handler. But because the error happens in a different
|
|
49
|
-
// event loop context, it does not interrupt the normal program flow.
|
|
50
|
-
// Effectively, this gives us try-catch behavior without actually using
|
|
51
|
-
// try-catch. Neat!
|
|
52
|
-
// Check that the browser supports the APIs we need to implement our special
|
|
53
|
-
// DEV version of invokeGuardedCallback
|
|
54
|
-
if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
|
|
55
|
-
var fakeNode = document.createElement('react');
|
|
56
|
-
|
|
57
|
-
|
|
13
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react-dom'), require('react')) :
|
|
14
|
+
typeof define === 'function' && define.amd ? define(['react-dom', 'react'], factory) :
|
|
15
|
+
(global = global || self, global.ReactDOMUnstableNativeDependencies = factory(global.ReactDOM, global.React));
|
|
16
|
+
}(this, (function (ReactDOM, React) { 'use strict';
|
|
17
|
+
|
|
18
|
+
var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Prevent newer renderers from RTE when used with older react package versions.
|
|
19
|
+
// Current owner and dispatcher used to share the same ref,
|
|
20
|
+
// but PR #14548 split them out to better support the react-debug-tools package.
|
|
21
|
+
|
|
22
|
+
if (!ReactSharedInternals.hasOwnProperty('ReactCurrentDispatcher')) {
|
|
23
|
+
ReactSharedInternals.ReactCurrentDispatcher = {
|
|
24
|
+
current: null
|
|
25
|
+
};
|
|
58
26
|
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Call a function while guarding against errors that happens within it.
|
|
63
|
-
* Returns an error if it throws, otherwise null.
|
|
64
|
-
*
|
|
65
|
-
* In production, this is implemented using a try-catch. The reason we don't
|
|
66
|
-
* use a try-catch directly is so that we can swap out a different
|
|
67
|
-
* implementation in DEV mode.
|
|
68
|
-
*
|
|
69
|
-
* @param {String} name of the guard to use for logging or debugging
|
|
70
|
-
* @param {Function} func The function to invoke
|
|
71
|
-
* @param {*} context The context to use when calling the function
|
|
72
|
-
* @param {...*} args Arguments for function
|
|
73
|
-
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Same as invokeGuardedCallback, but instead of returning an error, it stores
|
|
78
|
-
* it in a global so it can be rethrown by `rethrowCaughtError` later.
|
|
79
|
-
* TODO: See if caughtError and rethrowError can be unified.
|
|
80
|
-
*
|
|
81
|
-
* @param {String} name of the guard to use for logging or debugging
|
|
82
|
-
* @param {Function} func The function to invoke
|
|
83
|
-
* @param {*} context The context to use when calling the function
|
|
84
|
-
* @param {...*} args Arguments for function
|
|
85
|
-
*/
|
|
86
27
|
|
|
28
|
+
if (!ReactSharedInternals.hasOwnProperty('ReactCurrentBatchConfig')) {
|
|
29
|
+
ReactSharedInternals.ReactCurrentBatchConfig = {
|
|
30
|
+
suspense: null
|
|
31
|
+
};
|
|
32
|
+
}
|
|
87
33
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
34
|
+
// by calls to these methods by a Babel plugin.
|
|
35
|
+
//
|
|
36
|
+
// In PROD (or in packages without access to React internals),
|
|
37
|
+
// they are left as they are instead.
|
|
92
38
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
*/
|
|
99
|
-
var warningWithoutStack = function () {};
|
|
39
|
+
function warn(format) {
|
|
40
|
+
{
|
|
41
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
42
|
+
args[_key - 1] = arguments[_key];
|
|
43
|
+
}
|
|
100
44
|
|
|
101
|
-
|
|
102
|
-
warningWithoutStack = function (condition, format) {
|
|
103
|
-
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
104
|
-
args[_key - 2] = arguments[_key];
|
|
45
|
+
printWarning('warn', format, args);
|
|
105
46
|
}
|
|
47
|
+
}
|
|
48
|
+
function error(format) {
|
|
49
|
+
{
|
|
50
|
+
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
|
51
|
+
args[_key2 - 1] = arguments[_key2];
|
|
52
|
+
}
|
|
106
53
|
|
|
107
|
-
|
|
108
|
-
throw new Error('`warningWithoutStack(condition, format, ...args)` requires a warning ' + 'message argument');
|
|
54
|
+
printWarning('error', format, args);
|
|
109
55
|
}
|
|
56
|
+
}
|
|
110
57
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
58
|
+
function printWarning(level, format, args) {
|
|
59
|
+
// When changing this logic, you might want to also
|
|
60
|
+
// update consoleWithStackDev.www.js as well.
|
|
61
|
+
{
|
|
62
|
+
var hasExistingStack = args.length > 0 && typeof args[args.length - 1] === 'string' && args[args.length - 1].indexOf('\n in') === 0;
|
|
115
63
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
64
|
+
if (!hasExistingStack) {
|
|
65
|
+
var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
|
|
66
|
+
var stack = ReactDebugCurrentFrame.getStackAddendum();
|
|
67
|
+
|
|
68
|
+
if (stack !== '') {
|
|
69
|
+
format += '%s';
|
|
70
|
+
args = args.concat([stack]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
119
73
|
|
|
120
|
-
if (typeof console !== 'undefined') {
|
|
121
74
|
var argsWithFormat = args.map(function (item) {
|
|
122
75
|
return '' + item;
|
|
123
|
-
});
|
|
76
|
+
}); // Careful: RN currently depends on this prefix
|
|
77
|
+
|
|
124
78
|
argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
|
|
125
79
|
// breaks IE9: https://github.com/facebook/react/issues/13610
|
|
126
|
-
|
|
127
|
-
|
|
80
|
+
// eslint-disable-next-line react-internal/no-production-logging
|
|
81
|
+
|
|
82
|
+
Function.prototype.apply.call(console[level], console, argsWithFormat);
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
// --- Welcome to debugging React ---
|
|
86
|
+
// This error was thrown as a convenience so that you can use this stack
|
|
87
|
+
// to find the callsite that caused this warning to fire.
|
|
88
|
+
var argIndex = 0;
|
|
89
|
+
var message = 'Warning: ' + format.replace(/%s/g, function () {
|
|
90
|
+
return args[argIndex++];
|
|
91
|
+
});
|
|
92
|
+
throw new Error(message);
|
|
93
|
+
} catch (x) {}
|
|
128
94
|
}
|
|
95
|
+
}
|
|
129
96
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
97
|
+
{
|
|
98
|
+
// In DEV mode, we swap out invokeGuardedCallback for a special version
|
|
99
|
+
// that plays more nicely with the browser's DevTools. The idea is to preserve
|
|
100
|
+
// "Pause on exceptions" behavior. Because React wraps all user-provided
|
|
101
|
+
// functions in invokeGuardedCallback, and the production version of
|
|
102
|
+
// invokeGuardedCallback uses a try-catch, all user exceptions are treated
|
|
103
|
+
// like caught exceptions, and the DevTools won't pause unless the developer
|
|
104
|
+
// takes the extra step of enabling pause on caught exceptions. This is
|
|
105
|
+
// unintuitive, though, because even though React has caught the error, from
|
|
106
|
+
// the developer's perspective, the error is uncaught.
|
|
107
|
+
//
|
|
108
|
+
// To preserve the expected "Pause on exceptions" behavior, we don't use a
|
|
109
|
+
// try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake
|
|
110
|
+
// DOM node, and call the user-provided callback from inside an event handler
|
|
111
|
+
// for that fake event. If the callback throws, the error is "captured" using
|
|
112
|
+
// a global event handler. But because the error happens in a different
|
|
113
|
+
// event loop context, it does not interrupt the normal program flow.
|
|
114
|
+
// Effectively, this gives us try-catch behavior without actually using
|
|
115
|
+
// try-catch. Neat!
|
|
116
|
+
// Check that the browser supports the APIs we need to implement our special
|
|
117
|
+
// DEV version of invokeGuardedCallback
|
|
118
|
+
if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
|
|
119
|
+
var fakeNode = document.createElement('react');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
142
122
|
|
|
143
|
-
var
|
|
123
|
+
var getFiberCurrentPropsFromNode = null;
|
|
124
|
+
var getInstanceFromNode = null;
|
|
125
|
+
var getNodeFromInstance = null;
|
|
126
|
+
function setComponentTree(getFiberCurrentPropsFromNodeImpl, getInstanceFromNodeImpl, getNodeFromInstanceImpl) {
|
|
127
|
+
getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl;
|
|
128
|
+
getInstanceFromNode = getInstanceFromNodeImpl;
|
|
129
|
+
getNodeFromInstance = getNodeFromInstanceImpl;
|
|
144
130
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
131
|
+
{
|
|
132
|
+
if (!getNodeFromInstance || !getInstanceFromNode) {
|
|
133
|
+
error('EventPluginUtils.setComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
var validateEventDispatches;
|
|
152
138
|
|
|
153
139
|
{
|
|
154
|
-
|
|
140
|
+
validateEventDispatches = function (event) {
|
|
141
|
+
var dispatchListeners = event._dispatchListeners;
|
|
142
|
+
var dispatchInstances = event._dispatchInstances;
|
|
143
|
+
var listenersIsArr = Array.isArray(dispatchListeners);
|
|
144
|
+
var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
|
|
145
|
+
var instancesIsArr = Array.isArray(dispatchInstances);
|
|
146
|
+
var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
|
|
147
|
+
|
|
148
|
+
if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) {
|
|
149
|
+
error('EventPluginUtils: Invalid `event`.');
|
|
150
|
+
}
|
|
151
|
+
};
|
|
155
152
|
}
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Standard/simple iteration through an event's collected dispatches, but stops
|
|
155
|
+
* at the first dispatch execution returning true, and returns that id.
|
|
156
|
+
*
|
|
157
|
+
* @return {?string} id of the first dispatch execution who's listener returns
|
|
158
|
+
* true, or null if no listener returned true.
|
|
159
|
+
*/
|
|
158
160
|
|
|
159
|
-
{
|
|
160
|
-
validateEventDispatches = function (event) {
|
|
161
|
+
function executeDispatchesInOrderStopAtTrueImpl(event) {
|
|
161
162
|
var dispatchListeners = event._dispatchListeners;
|
|
162
163
|
var dispatchInstances = event._dispatchInstances;
|
|
163
|
-
var listenersIsArr = Array.isArray(dispatchListeners);
|
|
164
|
-
var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
|
|
165
|
-
var instancesIsArr = Array.isArray(dispatchInstances);
|
|
166
|
-
var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
|
|
167
|
-
!(instancesIsArr === listenersIsArr && instancesLen === listenersLen) ? warningWithoutStack$1(false, 'EventPluginUtils: Invalid `event`.') : void 0;
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Dispatch the event to the listener.
|
|
172
|
-
* @param {SyntheticEvent} event SyntheticEvent to handle
|
|
173
|
-
* @param {function} listener Application-level callback
|
|
174
|
-
* @param {*} inst Internal component instance
|
|
175
|
-
*/
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Standard/simple iteration through an event's collected dispatches.
|
|
181
|
-
*/
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Standard/simple iteration through an event's collected dispatches, but stops
|
|
186
|
-
* at the first dispatch execution returning true, and returns that id.
|
|
187
|
-
*
|
|
188
|
-
* @return {?string} id of the first dispatch execution who's listener returns
|
|
189
|
-
* true, or null if no listener returned true.
|
|
190
|
-
*/
|
|
191
|
-
|
|
192
|
-
function executeDispatchesInOrderStopAtTrueImpl(event) {
|
|
193
|
-
var dispatchListeners = event._dispatchListeners;
|
|
194
|
-
var dispatchInstances = event._dispatchInstances;
|
|
195
164
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
165
|
+
{
|
|
166
|
+
validateEventDispatches(event);
|
|
167
|
+
}
|
|
199
168
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
169
|
+
if (Array.isArray(dispatchListeners)) {
|
|
170
|
+
for (var i = 0; i < dispatchListeners.length; i++) {
|
|
171
|
+
if (event.isPropagationStopped()) {
|
|
172
|
+
break;
|
|
173
|
+
} // Listeners and Instances are two parallel arrays that are always in sync.
|
|
205
174
|
|
|
206
175
|
|
|
207
|
-
|
|
208
|
-
|
|
176
|
+
if (dispatchListeners[i](event, dispatchInstances[i])) {
|
|
177
|
+
return dispatchInstances[i];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} else if (dispatchListeners) {
|
|
181
|
+
if (dispatchListeners(event, dispatchInstances)) {
|
|
182
|
+
return dispatchInstances;
|
|
209
183
|
}
|
|
210
184
|
}
|
|
211
|
-
} else if (dispatchListeners) {
|
|
212
|
-
if (dispatchListeners(event, dispatchInstances)) {
|
|
213
|
-
return dispatchInstances;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return null;
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* @see executeDispatchesInOrderStopAtTrueImpl
|
|
221
|
-
*/
|
|
222
185
|
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* @see executeDispatchesInOrderStopAtTrueImpl
|
|
190
|
+
*/
|
|
223
191
|
|
|
224
|
-
function executeDispatchesInOrderStopAtTrue(event) {
|
|
225
|
-
var ret = executeDispatchesInOrderStopAtTrueImpl(event);
|
|
226
|
-
event._dispatchInstances = null;
|
|
227
|
-
event._dispatchListeners = null;
|
|
228
|
-
return ret;
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Execution of a "direct" dispatch - there must be at most one dispatch
|
|
232
|
-
* accumulated on the event or it is considered an error. It doesn't really make
|
|
233
|
-
* sense for an event with multiple dispatches (bubbled) to keep track of the
|
|
234
|
-
* return values at each dispatch execution, but it does tend to make sense when
|
|
235
|
-
* dealing with "direct" dispatches.
|
|
236
|
-
*
|
|
237
|
-
* @return {*} The return value of executing the single dispatch.
|
|
238
|
-
*/
|
|
239
192
|
|
|
240
|
-
function
|
|
241
|
-
|
|
242
|
-
|
|
193
|
+
function executeDispatchesInOrderStopAtTrue(event) {
|
|
194
|
+
var ret = executeDispatchesInOrderStopAtTrueImpl(event);
|
|
195
|
+
event._dispatchInstances = null;
|
|
196
|
+
event._dispatchListeners = null;
|
|
197
|
+
return ret;
|
|
243
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Execution of a "direct" dispatch - there must be at most one dispatch
|
|
201
|
+
* accumulated on the event or it is considered an error. It doesn't really make
|
|
202
|
+
* sense for an event with multiple dispatches (bubbled) to keep track of the
|
|
203
|
+
* return values at each dispatch execution, but it does tend to make sense when
|
|
204
|
+
* dealing with "direct" dispatches.
|
|
205
|
+
*
|
|
206
|
+
* @return {*} The return value of executing the single dispatch.
|
|
207
|
+
*/
|
|
244
208
|
|
|
245
|
-
|
|
246
|
-
var dispatchInstance = event._dispatchInstances;
|
|
247
|
-
|
|
248
|
-
if (!!Array.isArray(dispatchListener)) {
|
|
209
|
+
function executeDirectDispatch(event) {
|
|
249
210
|
{
|
|
250
|
-
|
|
211
|
+
validateEventDispatches(event);
|
|
251
212
|
}
|
|
252
|
-
}
|
|
253
213
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
event.currentTarget = null;
|
|
257
|
-
event._dispatchListeners = null;
|
|
258
|
-
event._dispatchInstances = null;
|
|
259
|
-
return res;
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* @param {SyntheticEvent} event
|
|
263
|
-
* @return {boolean} True iff number of dispatches accumulated is greater than 0.
|
|
264
|
-
*/
|
|
214
|
+
var dispatchListener = event._dispatchListeners;
|
|
215
|
+
var dispatchInstance = event._dispatchInstances;
|
|
265
216
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
217
|
+
if (!!Array.isArray(dispatchListener)) {
|
|
218
|
+
{
|
|
219
|
+
throw Error( "executeDirectDispatch(...): Invalid `event`." );
|
|
220
|
+
}
|
|
221
|
+
}
|
|
269
222
|
|
|
270
|
-
|
|
223
|
+
event.currentTarget = dispatchListener ? getNodeFromInstance(dispatchInstance) : null;
|
|
224
|
+
var res = dispatchListener ? dispatchListener(event) : null;
|
|
225
|
+
event.currentTarget = null;
|
|
226
|
+
event._dispatchListeners = null;
|
|
227
|
+
event._dispatchInstances = null;
|
|
228
|
+
return res;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* @param {SyntheticEvent} event
|
|
232
|
+
* @return {boolean} True iff number of dispatches accumulated is greater than 0.
|
|
233
|
+
*/
|
|
271
234
|
|
|
272
|
-
|
|
235
|
+
function hasDispatches(event) {
|
|
236
|
+
return !!event._dispatchListeners;
|
|
237
|
+
}
|
|
273
238
|
|
|
274
|
-
|
|
239
|
+
var HostComponent = 5;
|
|
275
240
|
|
|
276
|
-
|
|
241
|
+
function getParent(inst) {
|
|
242
|
+
do {
|
|
243
|
+
inst = inst.return; // TODO: If this is a HostRoot we might want to bail out.
|
|
244
|
+
// That is depending on if we want nested subtrees (layers) to bubble
|
|
245
|
+
// events to their parent. We could also go through parentNode on the
|
|
246
|
+
// host node but that wouldn't work for React Native and doesn't let us
|
|
247
|
+
// do the portal feature.
|
|
248
|
+
} while (inst && inst.tag !== HostComponent);
|
|
277
249
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// That is depending on if we want nested subtrees (layers) to bubble
|
|
282
|
-
// events to their parent. We could also go through parentNode on the
|
|
283
|
-
// host node but that wouldn't work for React Native and doesn't let us
|
|
284
|
-
// do the portal feature.
|
|
285
|
-
} while (inst && inst.tag !== HostComponent);
|
|
250
|
+
if (inst) {
|
|
251
|
+
return inst;
|
|
252
|
+
}
|
|
286
253
|
|
|
287
|
-
|
|
288
|
-
return inst;
|
|
254
|
+
return null;
|
|
289
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Return the lowest common ancestor of A and B, or null if they are in
|
|
258
|
+
* different trees.
|
|
259
|
+
*/
|
|
290
260
|
|
|
291
|
-
return null;
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Return the lowest common ancestor of A and B, or null if they are in
|
|
295
|
-
* different trees.
|
|
296
|
-
*/
|
|
297
261
|
|
|
262
|
+
function getLowestCommonAncestor(instA, instB) {
|
|
263
|
+
var depthA = 0;
|
|
298
264
|
|
|
299
|
-
|
|
300
|
-
|
|
265
|
+
for (var tempA = instA; tempA; tempA = getParent(tempA)) {
|
|
266
|
+
depthA++;
|
|
267
|
+
}
|
|
301
268
|
|
|
302
|
-
|
|
303
|
-
depthA++;
|
|
304
|
-
}
|
|
269
|
+
var depthB = 0;
|
|
305
270
|
|
|
306
|
-
|
|
271
|
+
for (var tempB = instB; tempB; tempB = getParent(tempB)) {
|
|
272
|
+
depthB++;
|
|
273
|
+
} // If A is deeper, crawl up.
|
|
307
274
|
|
|
308
|
-
for (var tempB = instB; tempB; tempB = getParent(tempB)) {
|
|
309
|
-
depthB++;
|
|
310
|
-
} // If A is deeper, crawl up.
|
|
311
275
|
|
|
276
|
+
while (depthA - depthB > 0) {
|
|
277
|
+
instA = getParent(instA);
|
|
278
|
+
depthA--;
|
|
279
|
+
} // If B is deeper, crawl up.
|
|
312
280
|
|
|
313
|
-
while (depthA - depthB > 0) {
|
|
314
|
-
instA = getParent(instA);
|
|
315
|
-
depthA--;
|
|
316
|
-
} // If B is deeper, crawl up.
|
|
317
281
|
|
|
282
|
+
while (depthB - depthA > 0) {
|
|
283
|
+
instB = getParent(instB);
|
|
284
|
+
depthB--;
|
|
285
|
+
} // Walk in lockstep until we find a match.
|
|
318
286
|
|
|
319
|
-
while (depthB - depthA > 0) {
|
|
320
|
-
instB = getParent(instB);
|
|
321
|
-
depthB--;
|
|
322
|
-
} // Walk in lockstep until we find a match.
|
|
323
287
|
|
|
288
|
+
var depth = depthA;
|
|
324
289
|
|
|
325
|
-
|
|
290
|
+
while (depth--) {
|
|
291
|
+
if (instA === instB || instA === instB.alternate) {
|
|
292
|
+
return instA;
|
|
293
|
+
}
|
|
326
294
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return instA;
|
|
295
|
+
instA = getParent(instA);
|
|
296
|
+
instB = getParent(instB);
|
|
330
297
|
}
|
|
331
298
|
|
|
332
|
-
|
|
333
|
-
instB = getParent(instB);
|
|
299
|
+
return null;
|
|
334
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Return if A is an ancestor of B.
|
|
303
|
+
*/
|
|
335
304
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
305
|
+
function isAncestor(instA, instB) {
|
|
306
|
+
while (instB) {
|
|
307
|
+
if (instA === instB || instA === instB.alternate) {
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
341
310
|
|
|
342
|
-
|
|
343
|
-
while (instB) {
|
|
344
|
-
if (instA === instB || instA === instB.alternate) {
|
|
345
|
-
return true;
|
|
311
|
+
instB = getParent(instB);
|
|
346
312
|
}
|
|
347
313
|
|
|
348
|
-
|
|
314
|
+
return false;
|
|
349
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Return the parent instance of the passed-in instance.
|
|
318
|
+
*/
|
|
350
319
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
320
|
+
function getParentInstance(inst) {
|
|
321
|
+
return getParent(inst);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Simulates the traversal of a two-phase, capture/bubble event dispatch.
|
|
325
|
+
*/
|
|
356
326
|
|
|
357
|
-
function
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* Simulates the traversal of a two-phase, capture/bubble event dispatch.
|
|
362
|
-
*/
|
|
327
|
+
function traverseTwoPhase(inst, fn, arg) {
|
|
328
|
+
var path = [];
|
|
363
329
|
|
|
364
|
-
|
|
365
|
-
|
|
330
|
+
while (inst) {
|
|
331
|
+
path.push(inst);
|
|
332
|
+
inst = getParent(inst);
|
|
333
|
+
}
|
|
366
334
|
|
|
367
|
-
|
|
368
|
-
path.push(inst);
|
|
369
|
-
inst = getParent(inst);
|
|
370
|
-
}
|
|
335
|
+
var i;
|
|
371
336
|
|
|
372
|
-
|
|
337
|
+
for (i = path.length; i-- > 0;) {
|
|
338
|
+
fn(path[i], 'captured', arg);
|
|
339
|
+
}
|
|
373
340
|
|
|
374
|
-
|
|
375
|
-
|
|
341
|
+
for (i = 0; i < path.length; i++) {
|
|
342
|
+
fn(path[i], 'bubbled', arg);
|
|
343
|
+
}
|
|
376
344
|
}
|
|
377
345
|
|
|
378
|
-
|
|
379
|
-
|
|
346
|
+
function isInteractive(tag) {
|
|
347
|
+
return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
|
|
380
348
|
}
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
|
|
384
|
-
* should would receive a `mouseEnter` or `mouseLeave` event.
|
|
385
|
-
*
|
|
386
|
-
* Does not invoke the callback on the nearest common ancestor because nothing
|
|
387
|
-
* "entered" or "left" that element.
|
|
388
|
-
*/
|
|
389
349
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
350
|
+
function shouldPreventMouseEvent(name, type, props) {
|
|
351
|
+
switch (name) {
|
|
352
|
+
case 'onClick':
|
|
353
|
+
case 'onClickCapture':
|
|
354
|
+
case 'onDoubleClick':
|
|
355
|
+
case 'onDoubleClickCapture':
|
|
356
|
+
case 'onMouseDown':
|
|
357
|
+
case 'onMouseDownCapture':
|
|
358
|
+
case 'onMouseMove':
|
|
359
|
+
case 'onMouseMoveCapture':
|
|
360
|
+
case 'onMouseUp':
|
|
361
|
+
case 'onMouseUpCapture':
|
|
362
|
+
case 'onMouseEnter':
|
|
363
|
+
return !!(props.disabled && isInteractive(type));
|
|
364
|
+
|
|
365
|
+
default:
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* @param {object} inst The instance, which is the source of events.
|
|
371
|
+
* @param {string} registrationName Name of listener (e.g. `onClick`).
|
|
372
|
+
* @return {?function} The stored callback.
|
|
373
|
+
*/
|
|
395
374
|
|
|
396
|
-
/**
|
|
397
|
-
* Ordered list of injected plugins.
|
|
398
|
-
*/
|
|
399
375
|
|
|
376
|
+
function getListener(inst, registrationName) {
|
|
377
|
+
var listener; // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
|
|
378
|
+
// live here; needs to be moved to a better place soon
|
|
400
379
|
|
|
380
|
+
var stateNode = inst.stateNode;
|
|
401
381
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
382
|
+
if (!stateNode) {
|
|
383
|
+
// Work in progress (ex: onload events in incremental mode).
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
405
386
|
|
|
387
|
+
var props = getFiberCurrentPropsFromNode(stateNode);
|
|
406
388
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
389
|
+
if (!props) {
|
|
390
|
+
// Work in progress.
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
410
393
|
|
|
394
|
+
listener = props[registrationName];
|
|
411
395
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
396
|
+
if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
415
399
|
|
|
400
|
+
if (!(!listener || typeof listener === 'function')) {
|
|
401
|
+
{
|
|
402
|
+
throw Error( "Expected `" + registrationName + "` listener to be a function, instead got a value of `" + typeof listener + "` type." );
|
|
403
|
+
}
|
|
404
|
+
}
|
|
416
405
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
* used to warn in the case of missing event handlers. Available
|
|
420
|
-
* only in true.
|
|
421
|
-
* @type {Object}
|
|
422
|
-
*/
|
|
406
|
+
return listener;
|
|
407
|
+
}
|
|
423
408
|
|
|
424
|
-
|
|
409
|
+
/**
|
|
410
|
+
* Accumulates items that must not be null or undefined into the first one. This
|
|
411
|
+
* is used to conserve memory by avoiding array allocations, and thus sacrifices
|
|
412
|
+
* API cleanness. Since `current` can be null before being passed in and not
|
|
413
|
+
* null after this function, make sure to assign it back to `current`:
|
|
414
|
+
*
|
|
415
|
+
* `a = accumulateInto(a, b);`
|
|
416
|
+
*
|
|
417
|
+
* This API should be sparingly used. Try `accumulate` for something cleaner.
|
|
418
|
+
*
|
|
419
|
+
* @return {*|array<*>} An accumulation of items.
|
|
420
|
+
*/
|
|
425
421
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
* @internal
|
|
433
|
-
* @see {EventPluginHub.injection.injectEventPluginOrder}
|
|
434
|
-
*/
|
|
422
|
+
function accumulateInto(current, next) {
|
|
423
|
+
if (!(next != null)) {
|
|
424
|
+
{
|
|
425
|
+
throw Error( "accumulateInto(...): Accumulated items must not be null or undefined." );
|
|
426
|
+
}
|
|
427
|
+
}
|
|
435
428
|
|
|
429
|
+
if (current == null) {
|
|
430
|
+
return next;
|
|
431
|
+
} // Both are not empty. Warning: Never call x.concat(y) when you are not
|
|
432
|
+
// certain that x is an Array (x could be a string with concat method).
|
|
436
433
|
|
|
437
|
-
/**
|
|
438
|
-
* Injects plugins to be used by `EventPluginHub`. The plugin names must be
|
|
439
|
-
* in the ordering injected by `injectEventPluginOrder`.
|
|
440
|
-
*
|
|
441
|
-
* Plugins can be injected as part of page initialization or on-the-fly.
|
|
442
|
-
*
|
|
443
|
-
* @param {object} injectedNamesToPlugins Map from names to plugin modules.
|
|
444
|
-
* @internal
|
|
445
|
-
* @see {EventPluginHub.injection.injectEventPluginsByName}
|
|
446
|
-
*/
|
|
447
434
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
*
|
|
454
|
-
* `a = accumulateInto(a, b);`
|
|
455
|
-
*
|
|
456
|
-
* This API should be sparingly used. Try `accumulate` for something cleaner.
|
|
457
|
-
*
|
|
458
|
-
* @return {*|array<*>} An accumulation of items.
|
|
459
|
-
*/
|
|
435
|
+
if (Array.isArray(current)) {
|
|
436
|
+
if (Array.isArray(next)) {
|
|
437
|
+
current.push.apply(current, next);
|
|
438
|
+
return current;
|
|
439
|
+
}
|
|
460
440
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
{
|
|
464
|
-
throw Error("accumulateInto(...): Accumulated items must not be null or undefined.");
|
|
441
|
+
current.push(next);
|
|
442
|
+
return current;
|
|
465
443
|
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
if (current == null) {
|
|
469
|
-
return next;
|
|
470
|
-
} // Both are not empty. Warning: Never call x.concat(y) when you are not
|
|
471
|
-
// certain that x is an Array (x could be a string with concat method).
|
|
472
444
|
|
|
473
|
-
|
|
474
|
-
if (Array.isArray(current)) {
|
|
475
445
|
if (Array.isArray(next)) {
|
|
476
|
-
|
|
477
|
-
return current;
|
|
446
|
+
// A bit too dangerous to mutate `next`.
|
|
447
|
+
return [current].concat(next);
|
|
478
448
|
}
|
|
479
449
|
|
|
480
|
-
current
|
|
481
|
-
return current;
|
|
450
|
+
return [current, next];
|
|
482
451
|
}
|
|
483
452
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
453
|
+
/**
|
|
454
|
+
* @param {array} arr an "accumulation" of items which is either an Array or
|
|
455
|
+
* a single item. Useful when paired with the `accumulate` module. This is a
|
|
456
|
+
* simple utility that allows us to reason about a collection of items, but
|
|
457
|
+
* handling the case when there is exactly one item (and we do not need to
|
|
458
|
+
* allocate an array).
|
|
459
|
+
* @param {function} cb Callback invoked with each element or a collection.
|
|
460
|
+
* @param {?} [scope] Scope used as `this` in a callback.
|
|
461
|
+
*/
|
|
462
|
+
function forEachAccumulated(arr, cb, scope) {
|
|
463
|
+
if (Array.isArray(arr)) {
|
|
464
|
+
arr.forEach(cb, scope);
|
|
465
|
+
} else if (arr) {
|
|
466
|
+
cb.call(scope, arr);
|
|
467
|
+
}
|
|
487
468
|
}
|
|
488
469
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
* handling the case when there is exactly one item (and we do not need to
|
|
497
|
-
* allocate an array).
|
|
498
|
-
* @param {function} cb Callback invoked with each element or a collection.
|
|
499
|
-
* @param {?} [scope] Scope used as `this` in a callback.
|
|
500
|
-
*/
|
|
501
|
-
function forEachAccumulated(arr, cb, scope) {
|
|
502
|
-
if (Array.isArray(arr)) {
|
|
503
|
-
arr.forEach(cb, scope);
|
|
504
|
-
} else if (arr) {
|
|
505
|
-
cb.call(scope, arr);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
function isInteractive(tag) {
|
|
510
|
-
return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
function shouldPreventMouseEvent(name, type, props) {
|
|
514
|
-
switch (name) {
|
|
515
|
-
case 'onClick':
|
|
516
|
-
case 'onClickCapture':
|
|
517
|
-
case 'onDoubleClick':
|
|
518
|
-
case 'onDoubleClickCapture':
|
|
519
|
-
case 'onMouseDown':
|
|
520
|
-
case 'onMouseDownCapture':
|
|
521
|
-
case 'onMouseMove':
|
|
522
|
-
case 'onMouseMoveCapture':
|
|
523
|
-
case 'onMouseUp':
|
|
524
|
-
case 'onMouseUpCapture':
|
|
525
|
-
return !!(props.disabled && isInteractive(type));
|
|
526
|
-
|
|
527
|
-
default:
|
|
528
|
-
return false;
|
|
470
|
+
/**
|
|
471
|
+
* Some event types have a notion of different registration names for different
|
|
472
|
+
* "phases" of propagation. This finds listeners by a given phase.
|
|
473
|
+
*/
|
|
474
|
+
function listenerAtPhase(inst, event, propagationPhase) {
|
|
475
|
+
var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
|
|
476
|
+
return getListener(inst, registrationName);
|
|
529
477
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
*
|
|
540
|
-
* `eventTypes` {object}
|
|
541
|
-
* Optional, plugins that fire events must publish a mapping of registration
|
|
542
|
-
* names that are used to register listeners. Values of this mapping must
|
|
543
|
-
* be objects that contain `registrationName` or `phasedRegistrationNames`.
|
|
544
|
-
*
|
|
545
|
-
* `executeDispatch` {function(object, function, string)}
|
|
546
|
-
* Optional, allows plugins to override how an event gets dispatched. By
|
|
547
|
-
* default, the listener is simply invoked.
|
|
548
|
-
*
|
|
549
|
-
* Each plugin that is injected into `EventsPluginHub` is immediately operable.
|
|
550
|
-
*
|
|
551
|
-
* @public
|
|
552
|
-
*/
|
|
553
|
-
|
|
554
|
-
/**
|
|
555
|
-
* Methods for injecting dependencies.
|
|
556
|
-
*/
|
|
557
|
-
|
|
478
|
+
/**
|
|
479
|
+
* A small set of propagation patterns, each of which will accept a small amount
|
|
480
|
+
* of information, and generate a set of "dispatch ready event objects" - which
|
|
481
|
+
* are sets of events that have already been annotated with a set of dispatched
|
|
482
|
+
* listener functions/ids. The API is designed this way to discourage these
|
|
483
|
+
* propagation strategies from actually executing the dispatches, since we
|
|
484
|
+
* always want to collect the entire set of dispatches before executing even a
|
|
485
|
+
* single one.
|
|
486
|
+
*/
|
|
558
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Tags a `SyntheticEvent` with dispatched listeners. Creating this function
|
|
490
|
+
* here, allows us to not have to bind or create functions for each event.
|
|
491
|
+
* Mutating the event's members allows us to not have to create a wrapping
|
|
492
|
+
* "dispatch" object that pairs the event with the listener.
|
|
493
|
+
*/
|
|
559
494
|
|
|
560
|
-
/**
|
|
561
|
-
* @param {object} inst The instance, which is the source of events.
|
|
562
|
-
* @param {string} registrationName Name of listener (e.g. `onClick`).
|
|
563
|
-
* @return {?function} The stored callback.
|
|
564
|
-
*/
|
|
565
495
|
|
|
566
|
-
function
|
|
567
|
-
|
|
568
|
-
|
|
496
|
+
function accumulateDirectionalDispatches(inst, phase, event) {
|
|
497
|
+
{
|
|
498
|
+
if (!inst) {
|
|
499
|
+
error('Dispatching inst must not be null');
|
|
500
|
+
}
|
|
501
|
+
}
|
|
569
502
|
|
|
570
|
-
|
|
503
|
+
var listener = listenerAtPhase(inst, event, phase);
|
|
571
504
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
505
|
+
if (listener) {
|
|
506
|
+
event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
|
|
507
|
+
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
|
|
508
|
+
}
|
|
575
509
|
}
|
|
510
|
+
/**
|
|
511
|
+
* Collect dispatches (must be entirely collected before dispatching - see unit
|
|
512
|
+
* tests). Lazily allocate the array to conserve memory. We must loop through
|
|
513
|
+
* each event and perform the traversal for each one. We cannot perform a
|
|
514
|
+
* single traversal for the entire collection of events because each event may
|
|
515
|
+
* have a different target.
|
|
516
|
+
*/
|
|
576
517
|
|
|
577
|
-
var props = getFiberCurrentPropsFromNode$1(stateNode);
|
|
578
518
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
519
|
+
function accumulateTwoPhaseDispatchesSingle(event) {
|
|
520
|
+
if (event && event.dispatchConfig.phasedRegistrationNames) {
|
|
521
|
+
traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
|
|
522
|
+
}
|
|
582
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
|
|
526
|
+
*/
|
|
583
527
|
|
|
584
|
-
listener = props[registrationName];
|
|
585
|
-
|
|
586
|
-
if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
|
|
587
|
-
return null;
|
|
588
|
-
}
|
|
589
528
|
|
|
590
|
-
|
|
591
|
-
{
|
|
592
|
-
|
|
529
|
+
function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
|
|
530
|
+
if (event && event.dispatchConfig.phasedRegistrationNames) {
|
|
531
|
+
var targetInst = event._targetInst;
|
|
532
|
+
var parentInst = targetInst ? getParentInstance(targetInst) : null;
|
|
533
|
+
traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
|
|
593
534
|
}
|
|
594
535
|
}
|
|
536
|
+
/**
|
|
537
|
+
* Accumulates without regard to direction, does not look for phased
|
|
538
|
+
* registration names. Same as `accumulateDirectDispatchesSingle` but without
|
|
539
|
+
* requiring that the `dispatchMarker` be the same as the dispatched ID.
|
|
540
|
+
*/
|
|
595
541
|
|
|
596
|
-
return listener;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
/**
|
|
600
|
-
* Some event types have a notion of different registration names for different
|
|
601
|
-
* "phases" of propagation. This finds listeners by a given phase.
|
|
602
|
-
*/
|
|
603
|
-
function listenerAtPhase(inst, event, propagationPhase) {
|
|
604
|
-
var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
|
|
605
|
-
return getListener(inst, registrationName);
|
|
606
|
-
}
|
|
607
|
-
/**
|
|
608
|
-
* A small set of propagation patterns, each of which will accept a small amount
|
|
609
|
-
* of information, and generate a set of "dispatch ready event objects" - which
|
|
610
|
-
* are sets of events that have already been annotated with a set of dispatched
|
|
611
|
-
* listener functions/ids. The API is designed this way to discourage these
|
|
612
|
-
* propagation strategies from actually executing the dispatches, since we
|
|
613
|
-
* always want to collect the entire set of dispatches before executing even a
|
|
614
|
-
* single one.
|
|
615
|
-
*/
|
|
616
|
-
|
|
617
|
-
/**
|
|
618
|
-
* Tags a `SyntheticEvent` with dispatched listeners. Creating this function
|
|
619
|
-
* here, allows us to not have to bind or create functions for each event.
|
|
620
|
-
* Mutating the event's members allows us to not have to create a wrapping
|
|
621
|
-
* "dispatch" object that pairs the event with the listener.
|
|
622
|
-
*/
|
|
623
542
|
|
|
543
|
+
function accumulateDispatches(inst, ignoredDirection, event) {
|
|
544
|
+
if (inst && event && event.dispatchConfig.registrationName) {
|
|
545
|
+
var registrationName = event.dispatchConfig.registrationName;
|
|
546
|
+
var listener = getListener(inst, registrationName);
|
|
624
547
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
548
|
+
if (listener) {
|
|
549
|
+
event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
|
|
550
|
+
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
628
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* Accumulates dispatches on an `SyntheticEvent`, but only for the
|
|
556
|
+
* `dispatchMarker`.
|
|
557
|
+
* @param {SyntheticEvent} event
|
|
558
|
+
*/
|
|
629
559
|
|
|
630
|
-
var listener = listenerAtPhase(inst, event, phase);
|
|
631
560
|
|
|
632
|
-
|
|
633
|
-
event
|
|
634
|
-
|
|
561
|
+
function accumulateDirectDispatchesSingle(event) {
|
|
562
|
+
if (event && event.dispatchConfig.registrationName) {
|
|
563
|
+
accumulateDispatches(event._targetInst, null, event);
|
|
564
|
+
}
|
|
635
565
|
}
|
|
636
|
-
}
|
|
637
|
-
/**
|
|
638
|
-
* Collect dispatches (must be entirely collected before dispatching - see unit
|
|
639
|
-
* tests). Lazily allocate the array to conserve memory. We must loop through
|
|
640
|
-
* each event and perform the traversal for each one. We cannot perform a
|
|
641
|
-
* single traversal for the entire collection of events because each event may
|
|
642
|
-
* have a different target.
|
|
643
|
-
*/
|
|
644
566
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
if (event && event.dispatchConfig.phasedRegistrationNames) {
|
|
648
|
-
traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
|
|
567
|
+
function accumulateTwoPhaseDispatches(events) {
|
|
568
|
+
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
|
|
649
569
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
* Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
|
|
653
|
-
*/
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
|
|
657
|
-
if (event && event.dispatchConfig.phasedRegistrationNames) {
|
|
658
|
-
var targetInst = event._targetInst;
|
|
659
|
-
var parentInst = targetInst ? getParentInstance(targetInst) : null;
|
|
660
|
-
traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
|
|
570
|
+
function accumulateTwoPhaseDispatchesSkipTarget(events) {
|
|
571
|
+
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
|
|
661
572
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
* Accumulates without regard to direction, does not look for phased
|
|
665
|
-
* registration names. Same as `accumulateDirectDispatchesSingle` but without
|
|
666
|
-
* requiring that the `dispatchMarker` be the same as the dispatched ID.
|
|
667
|
-
*/
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
function accumulateDispatches(inst, ignoredDirection, event) {
|
|
671
|
-
if (inst && event && event.dispatchConfig.registrationName) {
|
|
672
|
-
var registrationName = event.dispatchConfig.registrationName;
|
|
673
|
-
var listener = getListener(inst, registrationName);
|
|
674
|
-
|
|
675
|
-
if (listener) {
|
|
676
|
-
event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
|
|
677
|
-
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
|
|
678
|
-
}
|
|
573
|
+
function accumulateDirectDispatches(events) {
|
|
574
|
+
forEachAccumulated(events, accumulateDirectDispatchesSingle);
|
|
679
575
|
}
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
|
-
* Accumulates dispatches on an `SyntheticEvent`, but only for the
|
|
683
|
-
* `dispatchMarker`.
|
|
684
|
-
* @param {SyntheticEvent} event
|
|
685
|
-
*/
|
|
686
|
-
|
|
687
576
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
accumulateDispatches(event._targetInst, null, event);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
function accumulateTwoPhaseDispatches(events) {
|
|
695
|
-
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
|
|
696
|
-
}
|
|
697
|
-
function accumulateTwoPhaseDispatchesSkipTarget(events) {
|
|
698
|
-
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
function accumulateDirectDispatches(events) {
|
|
702
|
-
forEachAccumulated(events, accumulateDirectDispatchesSingle);
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
|
|
706
|
-
var _assign = ReactInternals.assign;
|
|
707
|
-
|
|
708
|
-
/* eslint valid-typeof: 0 */
|
|
709
|
-
var EVENT_POOL_SIZE = 10;
|
|
710
|
-
/**
|
|
711
|
-
* @interface Event
|
|
712
|
-
* @see http://www.w3.org/TR/DOM-Level-3-Events/
|
|
713
|
-
*/
|
|
577
|
+
var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
|
|
578
|
+
var _assign = ReactInternals.assign;
|
|
714
579
|
|
|
715
|
-
var
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
return null;
|
|
721
|
-
},
|
|
722
|
-
eventPhase: null,
|
|
723
|
-
bubbles: null,
|
|
724
|
-
cancelable: null,
|
|
725
|
-
timeStamp: function (event) {
|
|
726
|
-
return event.timeStamp || Date.now();
|
|
727
|
-
},
|
|
728
|
-
defaultPrevented: null,
|
|
729
|
-
isTrusted: null
|
|
730
|
-
};
|
|
731
|
-
|
|
732
|
-
function functionThatReturnsTrue() {
|
|
733
|
-
return true;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
function functionThatReturnsFalse() {
|
|
737
|
-
return false;
|
|
738
|
-
}
|
|
739
|
-
/**
|
|
740
|
-
* Synthetic events are dispatched by event plugins, typically in response to a
|
|
741
|
-
* top-level event delegation handler.
|
|
742
|
-
*
|
|
743
|
-
* These systems should generally use pooling to reduce the frequency of garbage
|
|
744
|
-
* collection. The system should check `isPersistent` to determine whether the
|
|
745
|
-
* event should be released into the pool after being dispatched. Users that
|
|
746
|
-
* need a persisted event should invoke `persist`.
|
|
747
|
-
*
|
|
748
|
-
* Synthetic events (and subclasses) implement the DOM Level 3 Events API by
|
|
749
|
-
* normalizing browser quirks. Subclasses do not necessarily have to implement a
|
|
750
|
-
* DOM interface; custom application-specific events can also subclass this.
|
|
751
|
-
*
|
|
752
|
-
* @param {object} dispatchConfig Configuration used to dispatch this event.
|
|
753
|
-
* @param {*} targetInst Marker identifying the event target.
|
|
754
|
-
* @param {object} nativeEvent Native browser event.
|
|
755
|
-
* @param {DOMEventTarget} nativeEventTarget Target node.
|
|
756
|
-
*/
|
|
580
|
+
var EVENT_POOL_SIZE = 10;
|
|
581
|
+
/**
|
|
582
|
+
* @interface Event
|
|
583
|
+
* @see http://www.w3.org/TR/DOM-Level-3-Events/
|
|
584
|
+
*/
|
|
757
585
|
|
|
586
|
+
var EventInterface = {
|
|
587
|
+
type: null,
|
|
588
|
+
target: null,
|
|
589
|
+
// currentTarget is set when dispatching; no use in copying it here
|
|
590
|
+
currentTarget: function () {
|
|
591
|
+
return null;
|
|
592
|
+
},
|
|
593
|
+
eventPhase: null,
|
|
594
|
+
bubbles: null,
|
|
595
|
+
cancelable: null,
|
|
596
|
+
timeStamp: function (event) {
|
|
597
|
+
return event.timeStamp || Date.now();
|
|
598
|
+
},
|
|
599
|
+
defaultPrevented: null,
|
|
600
|
+
isTrusted: null
|
|
601
|
+
};
|
|
758
602
|
|
|
759
|
-
function
|
|
760
|
-
|
|
761
|
-
// these have a getter/setter for warnings
|
|
762
|
-
delete this.nativeEvent;
|
|
763
|
-
delete this.preventDefault;
|
|
764
|
-
delete this.stopPropagation;
|
|
765
|
-
delete this.isDefaultPrevented;
|
|
766
|
-
delete this.isPropagationStopped;
|
|
603
|
+
function functionThatReturnsTrue() {
|
|
604
|
+
return true;
|
|
767
605
|
}
|
|
768
606
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
607
|
+
function functionThatReturnsFalse() {
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Synthetic events are dispatched by event plugins, typically in response to a
|
|
612
|
+
* top-level event delegation handler.
|
|
613
|
+
*
|
|
614
|
+
* These systems should generally use pooling to reduce the frequency of garbage
|
|
615
|
+
* collection. The system should check `isPersistent` to determine whether the
|
|
616
|
+
* event should be released into the pool after being dispatched. Users that
|
|
617
|
+
* need a persisted event should invoke `persist`.
|
|
618
|
+
*
|
|
619
|
+
* Synthetic events (and subclasses) implement the DOM Level 3 Events API by
|
|
620
|
+
* normalizing browser quirks. Subclasses do not necessarily have to implement a
|
|
621
|
+
* DOM interface; custom application-specific events can also subclass this.
|
|
622
|
+
*
|
|
623
|
+
* @param {object} dispatchConfig Configuration used to dispatch this event.
|
|
624
|
+
* @param {*} targetInst Marker identifying the event target.
|
|
625
|
+
* @param {object} nativeEvent Native browser event.
|
|
626
|
+
* @param {DOMEventTarget} nativeEventTarget Target node.
|
|
627
|
+
*/
|
|
773
628
|
|
|
774
|
-
for (var propName in Interface) {
|
|
775
|
-
if (!Interface.hasOwnProperty(propName)) {
|
|
776
|
-
continue;
|
|
777
|
-
}
|
|
778
629
|
|
|
630
|
+
function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
|
|
779
631
|
{
|
|
780
|
-
|
|
632
|
+
// these have a getter/setter for warnings
|
|
633
|
+
delete this.nativeEvent;
|
|
634
|
+
delete this.preventDefault;
|
|
635
|
+
delete this.stopPropagation;
|
|
636
|
+
delete this.isDefaultPrevented;
|
|
637
|
+
delete this.isPropagationStopped;
|
|
781
638
|
}
|
|
782
639
|
|
|
783
|
-
|
|
640
|
+
this.dispatchConfig = dispatchConfig;
|
|
641
|
+
this._targetInst = targetInst;
|
|
642
|
+
this.nativeEvent = nativeEvent;
|
|
643
|
+
var Interface = this.constructor.Interface;
|
|
784
644
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
if (propName === 'target') {
|
|
789
|
-
this.target = nativeEventTarget;
|
|
790
|
-
} else {
|
|
791
|
-
this[propName] = nativeEvent[propName];
|
|
645
|
+
for (var propName in Interface) {
|
|
646
|
+
if (!Interface.hasOwnProperty(propName)) {
|
|
647
|
+
continue;
|
|
792
648
|
}
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
649
|
|
|
796
|
-
|
|
650
|
+
{
|
|
651
|
+
delete this[propName]; // this has a getter/setter for warnings
|
|
652
|
+
}
|
|
797
653
|
|
|
798
|
-
|
|
799
|
-
this.isDefaultPrevented = functionThatReturnsTrue;
|
|
800
|
-
} else {
|
|
801
|
-
this.isDefaultPrevented = functionThatReturnsFalse;
|
|
802
|
-
}
|
|
654
|
+
var normalize = Interface[propName];
|
|
803
655
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}
|
|
656
|
+
if (normalize) {
|
|
657
|
+
this[propName] = normalize(nativeEvent);
|
|
658
|
+
} else {
|
|
659
|
+
if (propName === 'target') {
|
|
660
|
+
this.target = nativeEventTarget;
|
|
661
|
+
} else {
|
|
662
|
+
this[propName] = nativeEvent[propName];
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
807
666
|
|
|
808
|
-
|
|
809
|
-
preventDefault: function () {
|
|
810
|
-
this.defaultPrevented = true;
|
|
811
|
-
var event = this.nativeEvent;
|
|
667
|
+
var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
|
|
812
668
|
|
|
813
|
-
if (
|
|
814
|
-
|
|
669
|
+
if (defaultPrevented) {
|
|
670
|
+
this.isDefaultPrevented = functionThatReturnsTrue;
|
|
671
|
+
} else {
|
|
672
|
+
this.isDefaultPrevented = functionThatReturnsFalse;
|
|
815
673
|
}
|
|
816
674
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
event.returnValue = false;
|
|
821
|
-
}
|
|
675
|
+
this.isPropagationStopped = functionThatReturnsFalse;
|
|
676
|
+
return this;
|
|
677
|
+
}
|
|
822
678
|
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
679
|
+
_assign(SyntheticEvent.prototype, {
|
|
680
|
+
preventDefault: function () {
|
|
681
|
+
this.defaultPrevented = true;
|
|
682
|
+
var event = this.nativeEvent;
|
|
827
683
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
684
|
+
if (!event) {
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
831
687
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
// any references to cancelBubble throw "Member not found". A
|
|
838
|
-
// typeof check of "unknown" circumvents this issue (and is also
|
|
839
|
-
// IE specific).
|
|
840
|
-
event.cancelBubble = true;
|
|
841
|
-
}
|
|
688
|
+
if (event.preventDefault) {
|
|
689
|
+
event.preventDefault();
|
|
690
|
+
} else if (typeof event.returnValue !== 'unknown') {
|
|
691
|
+
event.returnValue = false;
|
|
692
|
+
}
|
|
842
693
|
|
|
843
|
-
|
|
844
|
-
|
|
694
|
+
this.isDefaultPrevented = functionThatReturnsTrue;
|
|
695
|
+
},
|
|
696
|
+
stopPropagation: function () {
|
|
697
|
+
var event = this.nativeEvent;
|
|
845
698
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
* won't be added back into the pool.
|
|
850
|
-
*/
|
|
851
|
-
persist: function () {
|
|
852
|
-
this.isPersistent = functionThatReturnsTrue;
|
|
853
|
-
},
|
|
699
|
+
if (!event) {
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
854
702
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
703
|
+
if (event.stopPropagation) {
|
|
704
|
+
event.stopPropagation();
|
|
705
|
+
} else if (typeof event.cancelBubble !== 'unknown') {
|
|
706
|
+
// The ChangeEventPlugin registers a "propertychange" event for
|
|
707
|
+
// IE. This event does not support bubbling or cancelling, and
|
|
708
|
+
// any references to cancelBubble throw "Member not found". A
|
|
709
|
+
// typeof check of "unknown" circumvents this issue (and is also
|
|
710
|
+
// IE specific).
|
|
711
|
+
event.cancelBubble = true;
|
|
712
|
+
}
|
|
861
713
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
*/
|
|
865
|
-
destructor: function () {
|
|
866
|
-
var Interface = this.constructor.Interface;
|
|
714
|
+
this.isPropagationStopped = functionThatReturnsTrue;
|
|
715
|
+
},
|
|
867
716
|
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
717
|
+
/**
|
|
718
|
+
* We release all dispatched `SyntheticEvent`s after each event loop, adding
|
|
719
|
+
* them back into the pool. This allows a way to hold onto a reference that
|
|
720
|
+
* won't be added back into the pool.
|
|
721
|
+
*/
|
|
722
|
+
persist: function () {
|
|
723
|
+
this.isPersistent = functionThatReturnsTrue;
|
|
724
|
+
},
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Checks if this event should be released back into the pool.
|
|
728
|
+
*
|
|
729
|
+
* @return {boolean} True if this should not be released, false otherwise.
|
|
730
|
+
*/
|
|
731
|
+
isPersistent: functionThatReturnsFalse,
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* `PooledClass` looks for `destructor` on each instance it releases.
|
|
735
|
+
*/
|
|
736
|
+
destructor: function () {
|
|
737
|
+
var Interface = this.constructor.Interface;
|
|
738
|
+
|
|
739
|
+
for (var propName in Interface) {
|
|
740
|
+
{
|
|
741
|
+
Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));
|
|
742
|
+
}
|
|
871
743
|
}
|
|
872
|
-
}
|
|
873
744
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
745
|
+
this.dispatchConfig = null;
|
|
746
|
+
this._targetInst = null;
|
|
747
|
+
this.nativeEvent = null;
|
|
748
|
+
this.isDefaultPrevented = functionThatReturnsFalse;
|
|
749
|
+
this.isPropagationStopped = functionThatReturnsFalse;
|
|
750
|
+
this._dispatchListeners = null;
|
|
751
|
+
this._dispatchInstances = null;
|
|
881
752
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
753
|
+
{
|
|
754
|
+
Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));
|
|
755
|
+
Object.defineProperty(this, 'isDefaultPrevented', getPooledWarningPropertyDefinition('isDefaultPrevented', functionThatReturnsFalse));
|
|
756
|
+
Object.defineProperty(this, 'isPropagationStopped', getPooledWarningPropertyDefinition('isPropagationStopped', functionThatReturnsFalse));
|
|
757
|
+
Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', function () {}));
|
|
758
|
+
Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', function () {}));
|
|
759
|
+
}
|
|
888
760
|
}
|
|
889
|
-
}
|
|
890
|
-
});
|
|
761
|
+
});
|
|
891
762
|
|
|
892
|
-
SyntheticEvent.Interface = EventInterface;
|
|
893
|
-
/**
|
|
894
|
-
|
|
895
|
-
|
|
763
|
+
SyntheticEvent.Interface = EventInterface;
|
|
764
|
+
/**
|
|
765
|
+
* Helper to reduce boilerplate when creating subclasses.
|
|
766
|
+
*/
|
|
896
767
|
|
|
897
|
-
SyntheticEvent.extend = function (Interface) {
|
|
898
|
-
|
|
768
|
+
SyntheticEvent.extend = function (Interface) {
|
|
769
|
+
var Super = this;
|
|
899
770
|
|
|
900
|
-
|
|
771
|
+
var E = function () {};
|
|
901
772
|
|
|
902
|
-
|
|
903
|
-
|
|
773
|
+
E.prototype = Super.prototype;
|
|
774
|
+
var prototype = new E();
|
|
904
775
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
776
|
+
function Class() {
|
|
777
|
+
return Super.apply(this, arguments);
|
|
778
|
+
}
|
|
908
779
|
|
|
909
|
-
|
|
780
|
+
_assign(prototype, Class.prototype);
|
|
910
781
|
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
};
|
|
782
|
+
Class.prototype = prototype;
|
|
783
|
+
Class.prototype.constructor = Class;
|
|
784
|
+
Class.Interface = _assign({}, Super.Interface, Interface);
|
|
785
|
+
Class.extend = Super.extend;
|
|
786
|
+
addEventPoolingTo(Class);
|
|
787
|
+
return Class;
|
|
788
|
+
};
|
|
918
789
|
|
|
919
|
-
addEventPoolingTo(SyntheticEvent);
|
|
920
|
-
/**
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
790
|
+
addEventPoolingTo(SyntheticEvent);
|
|
791
|
+
/**
|
|
792
|
+
* Helper to nullify syntheticEvent instance properties when destructing
|
|
793
|
+
*
|
|
794
|
+
* @param {String} propName
|
|
795
|
+
* @param {?object} getVal
|
|
796
|
+
* @return {object} defineProperty object
|
|
797
|
+
*/
|
|
927
798
|
|
|
928
|
-
function getPooledWarningPropertyDefinition(propName, getVal) {
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
799
|
+
function getPooledWarningPropertyDefinition(propName, getVal) {
|
|
800
|
+
var isFunction = typeof getVal === 'function';
|
|
801
|
+
return {
|
|
802
|
+
configurable: true,
|
|
803
|
+
set: set,
|
|
804
|
+
get: get
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
function set(val) {
|
|
808
|
+
var action = isFunction ? 'setting the method' : 'setting the property';
|
|
809
|
+
warn(action, 'This is effectively a no-op');
|
|
810
|
+
return val;
|
|
811
|
+
}
|
|
935
812
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
813
|
+
function get() {
|
|
814
|
+
var action = isFunction ? 'accessing the method' : 'accessing the property';
|
|
815
|
+
var result = isFunction ? 'This is a no-op function' : 'This is set to null';
|
|
816
|
+
warn(action, result);
|
|
817
|
+
return getVal;
|
|
818
|
+
}
|
|
941
819
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
820
|
+
function warn(action, result) {
|
|
821
|
+
{
|
|
822
|
+
error("This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
947
825
|
}
|
|
948
826
|
|
|
949
|
-
function
|
|
950
|
-
var
|
|
951
|
-
!warningCondition ? warningWithoutStack$1(false, "This synthetic event is reused for performance reasons. If you're seeing this, " + "you're %s `%s` on a released/nullified synthetic event. %s. " + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0;
|
|
952
|
-
}
|
|
953
|
-
}
|
|
827
|
+
function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {
|
|
828
|
+
var EventConstructor = this;
|
|
954
829
|
|
|
955
|
-
|
|
956
|
-
|
|
830
|
+
if (EventConstructor.eventPool.length) {
|
|
831
|
+
var instance = EventConstructor.eventPool.pop();
|
|
832
|
+
EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst);
|
|
833
|
+
return instance;
|
|
834
|
+
}
|
|
957
835
|
|
|
958
|
-
|
|
959
|
-
var instance = EventConstructor.eventPool.pop();
|
|
960
|
-
EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst);
|
|
961
|
-
return instance;
|
|
836
|
+
return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst);
|
|
962
837
|
}
|
|
963
838
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
function releasePooledEvent(event) {
|
|
968
|
-
var EventConstructor = this;
|
|
839
|
+
function releasePooledEvent(event) {
|
|
840
|
+
var EventConstructor = this;
|
|
969
841
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
842
|
+
if (!(event instanceof EventConstructor)) {
|
|
843
|
+
{
|
|
844
|
+
throw Error( "Trying to release an event instance into a pool of a different type." );
|
|
845
|
+
}
|
|
973
846
|
}
|
|
974
|
-
}
|
|
975
847
|
|
|
976
|
-
|
|
848
|
+
event.destructor();
|
|
977
849
|
|
|
978
|
-
|
|
979
|
-
|
|
850
|
+
if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
|
|
851
|
+
EventConstructor.eventPool.push(event);
|
|
852
|
+
}
|
|
980
853
|
}
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
function addEventPoolingTo(EventConstructor) {
|
|
984
|
-
EventConstructor.eventPool = [];
|
|
985
|
-
EventConstructor.getPooled = getPooledEvent;
|
|
986
|
-
EventConstructor.release = releasePooledEvent;
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
/**
|
|
990
|
-
* `touchHistory` isn't actually on the native event, but putting it in the
|
|
991
|
-
* interface will ensure that it is cleaned up when pooled/destroyed. The
|
|
992
|
-
* `ResponderEventPlugin` will populate it appropriately.
|
|
993
|
-
*/
|
|
994
854
|
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
855
|
+
function addEventPoolingTo(EventConstructor) {
|
|
856
|
+
EventConstructor.eventPool = [];
|
|
857
|
+
EventConstructor.getPooled = getPooledEvent;
|
|
858
|
+
EventConstructor.release = releasePooledEvent;
|
|
998
859
|
}
|
|
999
|
-
});
|
|
1000
|
-
|
|
1001
|
-
// Note: ideally these would be imported from DOMTopLevelEventTypes,
|
|
1002
|
-
// but our build system currently doesn't let us do that from a fork.
|
|
1003
|
-
var TOP_TOUCH_START = 'touchstart';
|
|
1004
|
-
var TOP_TOUCH_MOVE = 'touchmove';
|
|
1005
|
-
var TOP_TOUCH_END = 'touchend';
|
|
1006
|
-
var TOP_TOUCH_CANCEL = 'touchcancel';
|
|
1007
|
-
var TOP_SCROLL = 'scroll';
|
|
1008
|
-
var TOP_SELECTION_CHANGE = 'selectionchange';
|
|
1009
|
-
var TOP_MOUSE_DOWN = 'mousedown';
|
|
1010
|
-
var TOP_MOUSE_MOVE = 'mousemove';
|
|
1011
|
-
var TOP_MOUSE_UP = 'mouseup';
|
|
1012
|
-
function isStartish(topLevelType) {
|
|
1013
|
-
return topLevelType === TOP_TOUCH_START || topLevelType === TOP_MOUSE_DOWN;
|
|
1014
|
-
}
|
|
1015
|
-
function isMoveish(topLevelType) {
|
|
1016
|
-
return topLevelType === TOP_TOUCH_MOVE || topLevelType === TOP_MOUSE_MOVE;
|
|
1017
|
-
}
|
|
1018
|
-
function isEndish(topLevelType) {
|
|
1019
|
-
return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL || topLevelType === TOP_MOUSE_UP;
|
|
1020
|
-
}
|
|
1021
|
-
var startDependencies = [TOP_TOUCH_START, TOP_MOUSE_DOWN];
|
|
1022
|
-
var moveDependencies = [TOP_TOUCH_MOVE, TOP_MOUSE_MOVE];
|
|
1023
|
-
var endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END, TOP_MOUSE_UP];
|
|
1024
|
-
|
|
1025
|
-
/**
|
|
1026
|
-
* Tracks the position and time of each active touch by `touch.identifier`. We
|
|
1027
|
-
* should typically only see IDs in the range of 1-20 because IDs get recycled
|
|
1028
|
-
* when touches end and start again.
|
|
1029
|
-
*/
|
|
1030
|
-
|
|
1031
|
-
var MAX_TOUCH_BANK = 20;
|
|
1032
|
-
var touchBank = [];
|
|
1033
|
-
var touchHistory = {
|
|
1034
|
-
touchBank: touchBank,
|
|
1035
|
-
numberActiveTouches: 0,
|
|
1036
|
-
// If there is only one active touch, we remember its location. This prevents
|
|
1037
|
-
// us having to loop through all of the touches all the time in the most
|
|
1038
|
-
// common case.
|
|
1039
|
-
indexOfSingleActiveTouch: -1,
|
|
1040
|
-
mostRecentTimeStamp: 0
|
|
1041
|
-
};
|
|
1042
|
-
|
|
1043
|
-
function timestampForTouch(touch) {
|
|
1044
|
-
// The legacy internal implementation provides "timeStamp", which has been
|
|
1045
|
-
// renamed to "timestamp". Let both work for now while we iron it out
|
|
1046
|
-
// TODO (evv): rename timeStamp to timestamp in internal code
|
|
1047
|
-
return touch.timeStamp || touch.timestamp;
|
|
1048
|
-
}
|
|
1049
|
-
/**
|
|
1050
|
-
* TODO: Instead of making gestures recompute filtered velocity, we could
|
|
1051
|
-
* include a built in velocity computation that can be reused globally.
|
|
1052
|
-
*/
|
|
1053
860
|
|
|
861
|
+
/**
|
|
862
|
+
* `touchHistory` isn't actually on the native event, but putting it in the
|
|
863
|
+
* interface will ensure that it is cleaned up when pooled/destroyed. The
|
|
864
|
+
* `ResponderEventPlugin` will populate it appropriately.
|
|
865
|
+
*/
|
|
1054
866
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
startPageX: touch.pageX,
|
|
1059
|
-
startPageY: touch.pageY,
|
|
1060
|
-
startTimeStamp: timestampForTouch(touch),
|
|
1061
|
-
currentPageX: touch.pageX,
|
|
1062
|
-
currentPageY: touch.pageY,
|
|
1063
|
-
currentTimeStamp: timestampForTouch(touch),
|
|
1064
|
-
previousPageX: touch.pageX,
|
|
1065
|
-
previousPageY: touch.pageY,
|
|
1066
|
-
previousTimeStamp: timestampForTouch(touch)
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
function resetTouchRecord(touchRecord, touch) {
|
|
1071
|
-
touchRecord.touchActive = true;
|
|
1072
|
-
touchRecord.startPageX = touch.pageX;
|
|
1073
|
-
touchRecord.startPageY = touch.pageY;
|
|
1074
|
-
touchRecord.startTimeStamp = timestampForTouch(touch);
|
|
1075
|
-
touchRecord.currentPageX = touch.pageX;
|
|
1076
|
-
touchRecord.currentPageY = touch.pageY;
|
|
1077
|
-
touchRecord.currentTimeStamp = timestampForTouch(touch);
|
|
1078
|
-
touchRecord.previousPageX = touch.pageX;
|
|
1079
|
-
touchRecord.previousPageY = touch.pageY;
|
|
1080
|
-
touchRecord.previousTimeStamp = timestampForTouch(touch);
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
function getTouchIdentifier(_ref) {
|
|
1084
|
-
var identifier = _ref.identifier;
|
|
1085
|
-
|
|
1086
|
-
if (!(identifier != null)) {
|
|
1087
|
-
{
|
|
1088
|
-
throw Error("Touch object is missing identifier.");
|
|
867
|
+
var ResponderSyntheticEvent = SyntheticEvent.extend({
|
|
868
|
+
touchHistory: function (nativeEvent) {
|
|
869
|
+
return null; // Actually doesn't even look at the native event.
|
|
1089
870
|
}
|
|
1090
|
-
}
|
|
871
|
+
});
|
|
1091
872
|
|
|
1092
|
-
|
|
1093
|
-
|
|
873
|
+
// Note: ideally these would be imported from DOMTopLevelEventTypes,
|
|
874
|
+
// but our build system currently doesn't let us do that from a fork.
|
|
875
|
+
var TOP_TOUCH_START = 'touchstart';
|
|
876
|
+
var TOP_TOUCH_MOVE = 'touchmove';
|
|
877
|
+
var TOP_TOUCH_END = 'touchend';
|
|
878
|
+
var TOP_TOUCH_CANCEL = 'touchcancel';
|
|
879
|
+
var TOP_SCROLL = 'scroll';
|
|
880
|
+
var TOP_SELECTION_CHANGE = 'selectionchange';
|
|
881
|
+
var TOP_MOUSE_DOWN = 'mousedown';
|
|
882
|
+
var TOP_MOUSE_MOVE = 'mousemove';
|
|
883
|
+
var TOP_MOUSE_UP = 'mouseup';
|
|
884
|
+
function isStartish(topLevelType) {
|
|
885
|
+
return topLevelType === TOP_TOUCH_START || topLevelType === TOP_MOUSE_DOWN;
|
|
886
|
+
}
|
|
887
|
+
function isMoveish(topLevelType) {
|
|
888
|
+
return topLevelType === TOP_TOUCH_MOVE || topLevelType === TOP_MOUSE_MOVE;
|
|
889
|
+
}
|
|
890
|
+
function isEndish(topLevelType) {
|
|
891
|
+
return topLevelType === TOP_TOUCH_END || topLevelType === TOP_TOUCH_CANCEL || topLevelType === TOP_MOUSE_UP;
|
|
1094
892
|
}
|
|
893
|
+
var startDependencies = [TOP_TOUCH_START, TOP_MOUSE_DOWN];
|
|
894
|
+
var moveDependencies = [TOP_TOUCH_MOVE, TOP_MOUSE_MOVE];
|
|
895
|
+
var endDependencies = [TOP_TOUCH_CANCEL, TOP_TOUCH_END, TOP_MOUSE_UP];
|
|
1095
896
|
|
|
1096
|
-
|
|
1097
|
-
|
|
897
|
+
/**
|
|
898
|
+
* Tracks the position and time of each active touch by `touch.identifier`. We
|
|
899
|
+
* should typically only see IDs in the range of 1-20 because IDs get recycled
|
|
900
|
+
* when touches end and start again.
|
|
901
|
+
*/
|
|
1098
902
|
|
|
1099
|
-
|
|
1100
|
-
var
|
|
1101
|
-
var
|
|
903
|
+
var MAX_TOUCH_BANK = 20;
|
|
904
|
+
var touchBank = [];
|
|
905
|
+
var touchHistory = {
|
|
906
|
+
touchBank: touchBank,
|
|
907
|
+
numberActiveTouches: 0,
|
|
908
|
+
// If there is only one active touch, we remember its location. This prevents
|
|
909
|
+
// us having to loop through all of the touches all the time in the most
|
|
910
|
+
// common case.
|
|
911
|
+
indexOfSingleActiveTouch: -1,
|
|
912
|
+
mostRecentTimeStamp: 0
|
|
913
|
+
};
|
|
1102
914
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
915
|
+
function timestampForTouch(touch) {
|
|
916
|
+
// The legacy internal implementation provides "timeStamp", which has been
|
|
917
|
+
// renamed to "timestamp". Let both work for now while we iron it out
|
|
918
|
+
// TODO (evv): rename timeStamp to timestamp in internal code
|
|
919
|
+
return touch.timeStamp || touch.timestamp;
|
|
1107
920
|
}
|
|
921
|
+
/**
|
|
922
|
+
* TODO: Instead of making gestures recompute filtered velocity, we could
|
|
923
|
+
* include a built in velocity computation that can be reused globally.
|
|
924
|
+
*/
|
|
1108
925
|
|
|
1109
|
-
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
|
|
1110
|
-
}
|
|
1111
926
|
|
|
1112
|
-
function
|
|
1113
|
-
|
|
927
|
+
function createTouchRecord(touch) {
|
|
928
|
+
return {
|
|
929
|
+
touchActive: true,
|
|
930
|
+
startPageX: touch.pageX,
|
|
931
|
+
startPageY: touch.pageY,
|
|
932
|
+
startTimeStamp: timestampForTouch(touch),
|
|
933
|
+
currentPageX: touch.pageX,
|
|
934
|
+
currentPageY: touch.pageY,
|
|
935
|
+
currentTimeStamp: timestampForTouch(touch),
|
|
936
|
+
previousPageX: touch.pageX,
|
|
937
|
+
previousPageY: touch.pageY,
|
|
938
|
+
previousTimeStamp: timestampForTouch(touch)
|
|
939
|
+
};
|
|
940
|
+
}
|
|
1114
941
|
|
|
1115
|
-
|
|
942
|
+
function resetTouchRecord(touchRecord, touch) {
|
|
1116
943
|
touchRecord.touchActive = true;
|
|
1117
|
-
touchRecord.
|
|
1118
|
-
touchRecord.
|
|
1119
|
-
touchRecord.
|
|
944
|
+
touchRecord.startPageX = touch.pageX;
|
|
945
|
+
touchRecord.startPageY = touch.pageY;
|
|
946
|
+
touchRecord.startTimeStamp = timestampForTouch(touch);
|
|
1120
947
|
touchRecord.currentPageX = touch.pageX;
|
|
1121
948
|
touchRecord.currentPageY = touch.pageY;
|
|
1122
949
|
touchRecord.currentTimeStamp = timestampForTouch(touch);
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
950
|
+
touchRecord.previousPageX = touch.pageX;
|
|
951
|
+
touchRecord.previousPageY = touch.pageY;
|
|
952
|
+
touchRecord.previousTimeStamp = timestampForTouch(touch);
|
|
1126
953
|
}
|
|
1127
|
-
}
|
|
1128
954
|
|
|
1129
|
-
function
|
|
1130
|
-
|
|
955
|
+
function getTouchIdentifier(_ref) {
|
|
956
|
+
var identifier = _ref.identifier;
|
|
1131
957
|
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
touchRecord.currentPageX = touch.pageX;
|
|
1138
|
-
touchRecord.currentPageY = touch.pageY;
|
|
1139
|
-
touchRecord.currentTimeStamp = timestampForTouch(touch);
|
|
1140
|
-
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
|
|
1141
|
-
} else {
|
|
1142
|
-
console.warn('Cannot record touch end without a touch start.\n' + 'Touch End: %s\n', 'Touch Bank: %s', printTouch(touch), printTouchBank());
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
function printTouch(touch) {
|
|
1147
|
-
return JSON.stringify({
|
|
1148
|
-
identifier: touch.identifier,
|
|
1149
|
-
pageX: touch.pageX,
|
|
1150
|
-
pageY: touch.pageY,
|
|
1151
|
-
timestamp: timestampForTouch(touch)
|
|
1152
|
-
});
|
|
1153
|
-
}
|
|
958
|
+
if (!(identifier != null)) {
|
|
959
|
+
{
|
|
960
|
+
throw Error( "Touch object is missing identifier." );
|
|
961
|
+
}
|
|
962
|
+
}
|
|
1154
963
|
|
|
1155
|
-
|
|
1156
|
-
|
|
964
|
+
{
|
|
965
|
+
if (identifier > MAX_TOUCH_BANK) {
|
|
966
|
+
error('Touch identifier %s is greater than maximum supported %s which causes ' + 'performance issues backfilling array locations for all of the indices.', identifier, MAX_TOUCH_BANK);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
1157
969
|
|
|
1158
|
-
|
|
1159
|
-
printed += ' (original size: ' + touchBank.length + ')';
|
|
970
|
+
return identifier;
|
|
1160
971
|
}
|
|
1161
972
|
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
var ResponderTouchHistoryStore = {
|
|
1166
|
-
recordTouchTrack: function (topLevelType, nativeEvent) {
|
|
1167
|
-
if (isMoveish(topLevelType)) {
|
|
1168
|
-
nativeEvent.changedTouches.forEach(recordTouchMove);
|
|
1169
|
-
} else if (isStartish(topLevelType)) {
|
|
1170
|
-
nativeEvent.changedTouches.forEach(recordTouchStart);
|
|
1171
|
-
touchHistory.numberActiveTouches = nativeEvent.touches.length;
|
|
973
|
+
function recordTouchStart(touch) {
|
|
974
|
+
var identifier = getTouchIdentifier(touch);
|
|
975
|
+
var touchRecord = touchBank[identifier];
|
|
1172
976
|
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
touchHistory.numberActiveTouches = nativeEvent.touches.length;
|
|
977
|
+
if (touchRecord) {
|
|
978
|
+
resetTouchRecord(touchRecord, touch);
|
|
979
|
+
} else {
|
|
980
|
+
touchBank[identifier] = createTouchRecord(touch);
|
|
981
|
+
}
|
|
1179
982
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
var touchTrackToCheck = touchBank[i];
|
|
983
|
+
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
|
|
984
|
+
}
|
|
1183
985
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
986
|
+
function recordTouchMove(touch) {
|
|
987
|
+
var touchRecord = touchBank[getTouchIdentifier(touch)];
|
|
988
|
+
|
|
989
|
+
if (touchRecord) {
|
|
990
|
+
touchRecord.touchActive = true;
|
|
991
|
+
touchRecord.previousPageX = touchRecord.currentPageX;
|
|
992
|
+
touchRecord.previousPageY = touchRecord.currentPageY;
|
|
993
|
+
touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
|
|
994
|
+
touchRecord.currentPageX = touch.pageX;
|
|
995
|
+
touchRecord.currentPageY = touch.pageY;
|
|
996
|
+
touchRecord.currentTimeStamp = timestampForTouch(touch);
|
|
997
|
+
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
|
|
998
|
+
} else {
|
|
999
|
+
{
|
|
1000
|
+
warn('Cannot record touch move without a touch start.\n' + 'Touch Move: %s\n' + 'Touch Bank: %s', printTouch(touch), printTouchBank());
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1189
1004
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1005
|
+
function recordTouchEnd(touch) {
|
|
1006
|
+
var touchRecord = touchBank[getTouchIdentifier(touch)];
|
|
1007
|
+
|
|
1008
|
+
if (touchRecord) {
|
|
1009
|
+
touchRecord.touchActive = false;
|
|
1010
|
+
touchRecord.previousPageX = touchRecord.currentPageX;
|
|
1011
|
+
touchRecord.previousPageY = touchRecord.currentPageY;
|
|
1012
|
+
touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
|
|
1013
|
+
touchRecord.currentPageX = touch.pageX;
|
|
1014
|
+
touchRecord.currentPageY = touch.pageY;
|
|
1015
|
+
touchRecord.currentTimeStamp = timestampForTouch(touch);
|
|
1016
|
+
touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
|
|
1017
|
+
} else {
|
|
1018
|
+
{
|
|
1019
|
+
warn('Cannot record touch end without a touch start.\n' + 'Touch End: %s\n' + 'Touch Bank: %s', printTouch(touch), printTouchBank());
|
|
1194
1020
|
}
|
|
1195
1021
|
}
|
|
1196
|
-
}
|
|
1197
|
-
touchHistory: touchHistory
|
|
1198
|
-
};
|
|
1022
|
+
}
|
|
1199
1023
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1024
|
+
function printTouch(touch) {
|
|
1025
|
+
return JSON.stringify({
|
|
1026
|
+
identifier: touch.identifier,
|
|
1027
|
+
pageX: touch.pageX,
|
|
1028
|
+
pageY: touch.pageY,
|
|
1029
|
+
timestamp: timestampForTouch(touch)
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1207
1032
|
|
|
1208
|
-
function
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1033
|
+
function printTouchBank() {
|
|
1034
|
+
var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK));
|
|
1035
|
+
|
|
1036
|
+
if (touchBank.length > MAX_TOUCH_BANK) {
|
|
1037
|
+
printed += ' (original size: ' + touchBank.length + ')';
|
|
1212
1038
|
}
|
|
1039
|
+
|
|
1040
|
+
return printed;
|
|
1213
1041
|
}
|
|
1214
1042
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1043
|
+
var ResponderTouchHistoryStore = {
|
|
1044
|
+
recordTouchTrack: function (topLevelType, nativeEvent) {
|
|
1045
|
+
if (isMoveish(topLevelType)) {
|
|
1046
|
+
nativeEvent.changedTouches.forEach(recordTouchMove);
|
|
1047
|
+
} else if (isStartish(topLevelType)) {
|
|
1048
|
+
nativeEvent.changedTouches.forEach(recordTouchStart);
|
|
1049
|
+
touchHistory.numberActiveTouches = nativeEvent.touches.length;
|
|
1219
1050
|
|
|
1051
|
+
if (touchHistory.numberActiveTouches === 1) {
|
|
1052
|
+
touchHistory.indexOfSingleActiveTouch = nativeEvent.touches[0].identifier;
|
|
1053
|
+
}
|
|
1054
|
+
} else if (isEndish(topLevelType)) {
|
|
1055
|
+
nativeEvent.changedTouches.forEach(recordTouchEnd);
|
|
1056
|
+
touchHistory.numberActiveTouches = nativeEvent.touches.length;
|
|
1057
|
+
|
|
1058
|
+
if (touchHistory.numberActiveTouches === 1) {
|
|
1059
|
+
for (var i = 0; i < touchBank.length; i++) {
|
|
1060
|
+
var touchTrackToCheck = touchBank[i];
|
|
1061
|
+
|
|
1062
|
+
if (touchTrackToCheck != null && touchTrackToCheck.touchActive) {
|
|
1063
|
+
touchHistory.indexOfSingleActiveTouch = i;
|
|
1064
|
+
break;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1220
1067
|
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
}
|
|
1068
|
+
{
|
|
1069
|
+
var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch];
|
|
1224
1070
|
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1071
|
+
if (activeRecord == null || !activeRecord.touchActive) {
|
|
1072
|
+
error('Cannot find single active touch.');
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
},
|
|
1078
|
+
touchHistory: touchHistory
|
|
1079
|
+
};
|
|
1228
1080
|
|
|
1229
|
-
|
|
1230
|
-
|
|
1081
|
+
/**
|
|
1082
|
+
* Accumulates items that must not be null or undefined.
|
|
1083
|
+
*
|
|
1084
|
+
* This is used to conserve memory by avoiding array allocations.
|
|
1085
|
+
*
|
|
1086
|
+
* @return {*|array<*>} An accumulation of items.
|
|
1087
|
+
*/
|
|
1231
1088
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1089
|
+
function accumulate(current, next) {
|
|
1090
|
+
if (!(next != null)) {
|
|
1091
|
+
{
|
|
1092
|
+
throw Error( "accumulate(...): Accumulated items must not be null or undefined." );
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1236
1095
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
*/
|
|
1096
|
+
if (current == null) {
|
|
1097
|
+
return next;
|
|
1098
|
+
} // Both are not empty. Warning: Never call x.concat(y) when you are not
|
|
1099
|
+
// certain that x is an Array (x could be a string with concat method).
|
|
1242
1100
|
|
|
1243
|
-
var trackedTouchCount = 0;
|
|
1244
1101
|
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1102
|
+
if (Array.isArray(current)) {
|
|
1103
|
+
return current.concat(next);
|
|
1104
|
+
}
|
|
1248
1105
|
|
|
1249
|
-
|
|
1250
|
-
|
|
1106
|
+
if (Array.isArray(next)) {
|
|
1107
|
+
return [current].concat(next);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
return [current, next];
|
|
1251
1111
|
}
|
|
1252
|
-
};
|
|
1253
1112
|
|
|
1254
|
-
var eventTypes = {
|
|
1255
1113
|
/**
|
|
1256
|
-
*
|
|
1257
|
-
*
|
|
1114
|
+
* Instance of element that should respond to touch/move types of interactions,
|
|
1115
|
+
* as indicated explicitly by relevant callbacks.
|
|
1258
1116
|
*/
|
|
1259
|
-
startShouldSetResponder: {
|
|
1260
|
-
phasedRegistrationNames: {
|
|
1261
|
-
bubbled: 'onStartShouldSetResponder',
|
|
1262
|
-
captured: 'onStartShouldSetResponderCapture'
|
|
1263
|
-
},
|
|
1264
|
-
dependencies: startDependencies
|
|
1265
|
-
},
|
|
1266
1117
|
|
|
1118
|
+
var responderInst = null;
|
|
1267
1119
|
/**
|
|
1268
|
-
*
|
|
1269
|
-
*
|
|
1270
|
-
* `touchStart` had occurred during momentum scroll. During a momentum scroll,
|
|
1271
|
-
* a touch start will be immediately followed by a scroll event if the view is
|
|
1272
|
-
* currently scrolling.
|
|
1273
|
-
*
|
|
1274
|
-
* TODO: This shouldn't bubble.
|
|
1120
|
+
* Count of current touches. A textInput should become responder iff the
|
|
1121
|
+
* selection changes while there is a touch on the screen.
|
|
1275
1122
|
*/
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1123
|
+
|
|
1124
|
+
var trackedTouchCount = 0;
|
|
1125
|
+
|
|
1126
|
+
var changeResponder = function (nextResponderInst, blockHostResponder) {
|
|
1127
|
+
var oldResponderInst = responderInst;
|
|
1128
|
+
responderInst = nextResponderInst;
|
|
1129
|
+
|
|
1130
|
+
if (ResponderEventPlugin.GlobalResponderHandler !== null) {
|
|
1131
|
+
ResponderEventPlugin.GlobalResponderHandler.onChange(oldResponderInst, nextResponderInst, blockHostResponder);
|
|
1132
|
+
}
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
var eventTypes = {
|
|
1136
|
+
/**
|
|
1137
|
+
* On a `touchStart`/`mouseDown`, is it desired that this element become the
|
|
1138
|
+
* responder?
|
|
1139
|
+
*/
|
|
1140
|
+
startShouldSetResponder: {
|
|
1141
|
+
phasedRegistrationNames: {
|
|
1142
|
+
bubbled: 'onStartShouldSetResponder',
|
|
1143
|
+
captured: 'onStartShouldSetResponderCapture'
|
|
1144
|
+
},
|
|
1145
|
+
dependencies: startDependencies
|
|
1280
1146
|
},
|
|
1281
|
-
dependencies: [TOP_SCROLL]
|
|
1282
|
-
},
|
|
1283
1147
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1148
|
+
/**
|
|
1149
|
+
* On a `scroll`, is it desired that this element become the responder? This
|
|
1150
|
+
* is usually not needed, but should be used to retroactively infer that a
|
|
1151
|
+
* `touchStart` had occurred during momentum scroll. During a momentum scroll,
|
|
1152
|
+
* a touch start will be immediately followed by a scroll event if the view is
|
|
1153
|
+
* currently scrolling.
|
|
1154
|
+
*
|
|
1155
|
+
* TODO: This shouldn't bubble.
|
|
1156
|
+
*/
|
|
1157
|
+
scrollShouldSetResponder: {
|
|
1158
|
+
phasedRegistrationNames: {
|
|
1159
|
+
bubbled: 'onScrollShouldSetResponder',
|
|
1160
|
+
captured: 'onScrollShouldSetResponderCapture'
|
|
1161
|
+
},
|
|
1162
|
+
dependencies: [TOP_SCROLL]
|
|
1295
1163
|
},
|
|
1296
|
-
dependencies: [TOP_SELECTION_CHANGE]
|
|
1297
|
-
},
|
|
1298
1164
|
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1165
|
+
/**
|
|
1166
|
+
* On text selection change, should this element become the responder? This
|
|
1167
|
+
* is needed for text inputs or other views with native selection, so the
|
|
1168
|
+
* JS view can claim the responder.
|
|
1169
|
+
*
|
|
1170
|
+
* TODO: This shouldn't bubble.
|
|
1171
|
+
*/
|
|
1172
|
+
selectionChangeShouldSetResponder: {
|
|
1173
|
+
phasedRegistrationNames: {
|
|
1174
|
+
bubbled: 'onSelectionChangeShouldSetResponder',
|
|
1175
|
+
captured: 'onSelectionChangeShouldSetResponderCapture'
|
|
1176
|
+
},
|
|
1177
|
+
dependencies: [TOP_SELECTION_CHANGE]
|
|
1178
|
+
},
|
|
1179
|
+
|
|
1180
|
+
/**
|
|
1181
|
+
* On a `touchMove`/`mouseMove`, is it desired that this element become the
|
|
1182
|
+
* responder?
|
|
1183
|
+
*/
|
|
1184
|
+
moveShouldSetResponder: {
|
|
1185
|
+
phasedRegistrationNames: {
|
|
1186
|
+
bubbled: 'onMoveShouldSetResponder',
|
|
1187
|
+
captured: 'onMoveShouldSetResponderCapture'
|
|
1188
|
+
},
|
|
1189
|
+
dependencies: moveDependencies
|
|
1307
1190
|
},
|
|
1308
|
-
dependencies: moveDependencies
|
|
1309
|
-
},
|
|
1310
1191
|
|
|
1192
|
+
/**
|
|
1193
|
+
* Direct responder events dispatched directly to responder. Do not bubble.
|
|
1194
|
+
*/
|
|
1195
|
+
responderStart: {
|
|
1196
|
+
registrationName: 'onResponderStart',
|
|
1197
|
+
dependencies: startDependencies
|
|
1198
|
+
},
|
|
1199
|
+
responderMove: {
|
|
1200
|
+
registrationName: 'onResponderMove',
|
|
1201
|
+
dependencies: moveDependencies
|
|
1202
|
+
},
|
|
1203
|
+
responderEnd: {
|
|
1204
|
+
registrationName: 'onResponderEnd',
|
|
1205
|
+
dependencies: endDependencies
|
|
1206
|
+
},
|
|
1207
|
+
responderRelease: {
|
|
1208
|
+
registrationName: 'onResponderRelease',
|
|
1209
|
+
dependencies: endDependencies
|
|
1210
|
+
},
|
|
1211
|
+
responderTerminationRequest: {
|
|
1212
|
+
registrationName: 'onResponderTerminationRequest',
|
|
1213
|
+
dependencies: []
|
|
1214
|
+
},
|
|
1215
|
+
responderGrant: {
|
|
1216
|
+
registrationName: 'onResponderGrant',
|
|
1217
|
+
dependencies: []
|
|
1218
|
+
},
|
|
1219
|
+
responderReject: {
|
|
1220
|
+
registrationName: 'onResponderReject',
|
|
1221
|
+
dependencies: []
|
|
1222
|
+
},
|
|
1223
|
+
responderTerminate: {
|
|
1224
|
+
registrationName: 'onResponderTerminate',
|
|
1225
|
+
dependencies: []
|
|
1226
|
+
}
|
|
1227
|
+
};
|
|
1311
1228
|
/**
|
|
1312
|
-
*
|
|
1229
|
+
*
|
|
1230
|
+
* Responder System:
|
|
1231
|
+
* ----------------
|
|
1232
|
+
*
|
|
1233
|
+
* - A global, solitary "interaction lock" on a view.
|
|
1234
|
+
* - If a node becomes the responder, it should convey visual feedback
|
|
1235
|
+
* immediately to indicate so, either by highlighting or moving accordingly.
|
|
1236
|
+
* - To be the responder means, that touches are exclusively important to that
|
|
1237
|
+
* responder view, and no other view.
|
|
1238
|
+
* - While touches are still occurring, the responder lock can be transferred to
|
|
1239
|
+
* a new view, but only to increasingly "higher" views (meaning ancestors of
|
|
1240
|
+
* the current responder).
|
|
1241
|
+
*
|
|
1242
|
+
* Responder being granted:
|
|
1243
|
+
* ------------------------
|
|
1244
|
+
*
|
|
1245
|
+
* - Touch starts, moves, and scrolls can cause an ID to become the responder.
|
|
1246
|
+
* - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to
|
|
1247
|
+
* the "appropriate place".
|
|
1248
|
+
* - If nothing is currently the responder, the "appropriate place" is the
|
|
1249
|
+
* initiating event's `targetID`.
|
|
1250
|
+
* - If something *is* already the responder, the "appropriate place" is the
|
|
1251
|
+
* first common ancestor of the event target and the current `responderInst`.
|
|
1252
|
+
* - Some negotiation happens: See the timing diagram below.
|
|
1253
|
+
* - Scrolled views automatically become responder. The reasoning is that a
|
|
1254
|
+
* platform scroll view that isn't built on top of the responder system has
|
|
1255
|
+
* began scrolling, and the active responder must now be notified that the
|
|
1256
|
+
* interaction is no longer locked to it - the system has taken over.
|
|
1257
|
+
*
|
|
1258
|
+
* - Responder being released:
|
|
1259
|
+
* As soon as no more touches that *started* inside of descendants of the
|
|
1260
|
+
* *current* responderInst, an `onResponderRelease` event is dispatched to the
|
|
1261
|
+
* current responder, and the responder lock is released.
|
|
1262
|
+
*
|
|
1263
|
+
* TODO:
|
|
1264
|
+
* - on "end", a callback hook for `onResponderEndShouldRemainResponder` that
|
|
1265
|
+
* determines if the responder lock should remain.
|
|
1266
|
+
* - If a view shouldn't "remain" the responder, any active touches should by
|
|
1267
|
+
* default be considered "dead" and do not influence future negotiations or
|
|
1268
|
+
* bubble paths. It should be as if those touches do not exist.
|
|
1269
|
+
* -- For multitouch: Usually a translate-z will choose to "remain" responder
|
|
1270
|
+
* after one out of many touches ended. For translate-y, usually the view
|
|
1271
|
+
* doesn't wish to "remain" responder after one of many touches end.
|
|
1272
|
+
* - Consider building this on top of a `stopPropagation` model similar to
|
|
1273
|
+
* `W3C` events.
|
|
1274
|
+
* - Ensure that `onResponderTerminate` is called on touch cancels, whether or
|
|
1275
|
+
* not `onResponderTerminationRequest` returns `true` or `false`.
|
|
1276
|
+
*
|
|
1313
1277
|
*/
|
|
1314
|
-
responderStart: {
|
|
1315
|
-
registrationName: 'onResponderStart',
|
|
1316
|
-
dependencies: startDependencies
|
|
1317
|
-
},
|
|
1318
|
-
responderMove: {
|
|
1319
|
-
registrationName: 'onResponderMove',
|
|
1320
|
-
dependencies: moveDependencies
|
|
1321
|
-
},
|
|
1322
|
-
responderEnd: {
|
|
1323
|
-
registrationName: 'onResponderEnd',
|
|
1324
|
-
dependencies: endDependencies
|
|
1325
|
-
},
|
|
1326
|
-
responderRelease: {
|
|
1327
|
-
registrationName: 'onResponderRelease',
|
|
1328
|
-
dependencies: endDependencies
|
|
1329
|
-
},
|
|
1330
|
-
responderTerminationRequest: {
|
|
1331
|
-
registrationName: 'onResponderTerminationRequest',
|
|
1332
|
-
dependencies: []
|
|
1333
|
-
},
|
|
1334
|
-
responderGrant: {
|
|
1335
|
-
registrationName: 'onResponderGrant',
|
|
1336
|
-
dependencies: []
|
|
1337
|
-
},
|
|
1338
|
-
responderReject: {
|
|
1339
|
-
registrationName: 'onResponderReject',
|
|
1340
|
-
dependencies: []
|
|
1341
|
-
},
|
|
1342
|
-
responderTerminate: {
|
|
1343
|
-
registrationName: 'onResponderTerminate',
|
|
1344
|
-
dependencies: []
|
|
1345
|
-
}
|
|
1346
|
-
};
|
|
1347
|
-
/**
|
|
1348
|
-
*
|
|
1349
|
-
* Responder System:
|
|
1350
|
-
* ----------------
|
|
1351
|
-
*
|
|
1352
|
-
* - A global, solitary "interaction lock" on a view.
|
|
1353
|
-
* - If a node becomes the responder, it should convey visual feedback
|
|
1354
|
-
* immediately to indicate so, either by highlighting or moving accordingly.
|
|
1355
|
-
* - To be the responder means, that touches are exclusively important to that
|
|
1356
|
-
* responder view, and no other view.
|
|
1357
|
-
* - While touches are still occurring, the responder lock can be transferred to
|
|
1358
|
-
* a new view, but only to increasingly "higher" views (meaning ancestors of
|
|
1359
|
-
* the current responder).
|
|
1360
|
-
*
|
|
1361
|
-
* Responder being granted:
|
|
1362
|
-
* ------------------------
|
|
1363
|
-
*
|
|
1364
|
-
* - Touch starts, moves, and scrolls can cause an ID to become the responder.
|
|
1365
|
-
* - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to
|
|
1366
|
-
* the "appropriate place".
|
|
1367
|
-
* - If nothing is currently the responder, the "appropriate place" is the
|
|
1368
|
-
* initiating event's `targetID`.
|
|
1369
|
-
* - If something *is* already the responder, the "appropriate place" is the
|
|
1370
|
-
* first common ancestor of the event target and the current `responderInst`.
|
|
1371
|
-
* - Some negotiation happens: See the timing diagram below.
|
|
1372
|
-
* - Scrolled views automatically become responder. The reasoning is that a
|
|
1373
|
-
* platform scroll view that isn't built on top of the responder system has
|
|
1374
|
-
* began scrolling, and the active responder must now be notified that the
|
|
1375
|
-
* interaction is no longer locked to it - the system has taken over.
|
|
1376
|
-
*
|
|
1377
|
-
* - Responder being released:
|
|
1378
|
-
* As soon as no more touches that *started* inside of descendants of the
|
|
1379
|
-
* *current* responderInst, an `onResponderRelease` event is dispatched to the
|
|
1380
|
-
* current responder, and the responder lock is released.
|
|
1381
|
-
*
|
|
1382
|
-
* TODO:
|
|
1383
|
-
* - on "end", a callback hook for `onResponderEndShouldRemainResponder` that
|
|
1384
|
-
* determines if the responder lock should remain.
|
|
1385
|
-
* - If a view shouldn't "remain" the responder, any active touches should by
|
|
1386
|
-
* default be considered "dead" and do not influence future negotiations or
|
|
1387
|
-
* bubble paths. It should be as if those touches do not exist.
|
|
1388
|
-
* -- For multitouch: Usually a translate-z will choose to "remain" responder
|
|
1389
|
-
* after one out of many touches ended. For translate-y, usually the view
|
|
1390
|
-
* doesn't wish to "remain" responder after one of many touches end.
|
|
1391
|
-
* - Consider building this on top of a `stopPropagation` model similar to
|
|
1392
|
-
* `W3C` events.
|
|
1393
|
-
* - Ensure that `onResponderTerminate` is called on touch cancels, whether or
|
|
1394
|
-
* not `onResponderTerminationRequest` returns `true` or `false`.
|
|
1395
|
-
*
|
|
1396
|
-
*/
|
|
1397
1278
|
|
|
1398
|
-
/* Negotiation Performed
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
Process low level events to + Current Responder + wantsResponderID
|
|
1402
|
-
determine who to perform negot-| (if any exists at all) |
|
|
1403
|
-
iation/transition | Otherwise just pass through|
|
|
1404
|
-
-------------------------------+----------------------------+------------------+
|
|
1405
|
-
Bubble to find first ID | |
|
|
1406
|
-
to return true:wantsResponderID| |
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
+-----------v-------------+true| +------------------------+ |
|
|
1413
|
-
|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+
|
|
1414
|
-
+-----------+-------------+ | +------------------------+ | |
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
Bubble to find first ID | |
|
|
1432
|
-
to return true:wantsResponderID| |
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
+-----------v-------------+true| +------------------------+ |
|
|
1439
|
-
|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+
|
|
1440
|
-
+-----------+-------------+ | +------------------------+ | |
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
/**
|
|
1478
|
-
* A note about event ordering in the `EventPluginHub`.
|
|
1479
|
-
*
|
|
1480
|
-
* Suppose plugins are injected in the following order:
|
|
1481
|
-
*
|
|
1482
|
-
* `[R, S, C]`
|
|
1483
|
-
*
|
|
1484
|
-
* To help illustrate the example, assume `S` is `SimpleEventPlugin` (for
|
|
1485
|
-
* `onClick` etc) and `R` is `ResponderEventPlugin`.
|
|
1486
|
-
*
|
|
1487
|
-
* "Deferred-Dispatched Events":
|
|
1488
|
-
*
|
|
1489
|
-
* - The current event plugin system will traverse the list of injected plugins,
|
|
1490
|
-
* in order, and extract events by collecting the plugin's return value of
|
|
1491
|
-
* `extractEvents()`.
|
|
1492
|
-
* - These events that are returned from `extractEvents` are "deferred
|
|
1493
|
-
* dispatched events".
|
|
1494
|
-
* - When returned from `extractEvents`, deferred-dispatched events contain an
|
|
1495
|
-
* "accumulation" of deferred dispatches.
|
|
1496
|
-
* - These deferred dispatches are accumulated/collected before they are
|
|
1497
|
-
* returned, but processed at a later time by the `EventPluginHub` (hence the
|
|
1498
|
-
* name deferred).
|
|
1499
|
-
*
|
|
1500
|
-
* In the process of returning their deferred-dispatched events, event plugins
|
|
1501
|
-
* themselves can dispatch events on-demand without returning them from
|
|
1502
|
-
* `extractEvents`. Plugins might want to do this, so that they can use event
|
|
1503
|
-
* dispatching as a tool that helps them decide which events should be extracted
|
|
1504
|
-
* in the first place.
|
|
1505
|
-
*
|
|
1506
|
-
* "On-Demand-Dispatched Events":
|
|
1507
|
-
*
|
|
1508
|
-
* - On-demand-dispatched events are not returned from `extractEvents`.
|
|
1509
|
-
* - On-demand-dispatched events are dispatched during the process of returning
|
|
1510
|
-
* the deferred-dispatched events.
|
|
1511
|
-
* - They should not have side effects.
|
|
1512
|
-
* - They should be avoided, and/or eventually be replaced with another
|
|
1513
|
-
* abstraction that allows event plugins to perform multiple "rounds" of event
|
|
1514
|
-
* extraction.
|
|
1515
|
-
*
|
|
1516
|
-
* Therefore, the sequence of event dispatches becomes:
|
|
1517
|
-
*
|
|
1518
|
-
* - `R`s on-demand events (if any) (dispatched by `R` on-demand)
|
|
1519
|
-
* - `S`s on-demand events (if any) (dispatched by `S` on-demand)
|
|
1520
|
-
* - `C`s on-demand events (if any) (dispatched by `C` on-demand)
|
|
1521
|
-
* - `R`s extracted events (if any) (dispatched by `EventPluginHub`)
|
|
1522
|
-
* - `S`s extracted events (if any) (dispatched by `EventPluginHub`)
|
|
1523
|
-
* - `C`s extracted events (if any) (dispatched by `EventPluginHub`)
|
|
1524
|
-
*
|
|
1525
|
-
* In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`
|
|
1526
|
-
* on-demand dispatch returns `true` (and some other details are satisfied) the
|
|
1527
|
-
* `onResponderGrant` deferred dispatched event is returned from
|
|
1528
|
-
* `extractEvents`. The sequence of dispatch executions in this case
|
|
1529
|
-
* will appear as follows:
|
|
1530
|
-
*
|
|
1531
|
-
* - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)
|
|
1532
|
-
* - `touchStartCapture` (`EventPluginHub` dispatches as usual)
|
|
1533
|
-
* - `touchStart` (`EventPluginHub` dispatches as usual)
|
|
1534
|
-
* - `responderGrant/Reject` (`EventPluginHub` dispatches as usual)
|
|
1535
|
-
*/
|
|
1279
|
+
/* Negotiation Performed
|
|
1280
|
+
+-----------------------+
|
|
1281
|
+
/ \
|
|
1282
|
+
Process low level events to + Current Responder + wantsResponderID
|
|
1283
|
+
determine who to perform negot-| (if any exists at all) |
|
|
1284
|
+
iation/transition | Otherwise just pass through|
|
|
1285
|
+
-------------------------------+----------------------------+------------------+
|
|
1286
|
+
Bubble to find first ID | |
|
|
1287
|
+
to return true:wantsResponderID| |
|
|
1288
|
+
| |
|
|
1289
|
+
+-------------+ | |
|
|
1290
|
+
| onTouchStart| | |
|
|
1291
|
+
+------+------+ none | |
|
|
1292
|
+
| return| |
|
|
1293
|
+
+-----------v-------------+true| +------------------------+ |
|
|
1294
|
+
|onStartShouldSetResponder|----->|onResponderStart (cur) |<-----------+
|
|
1295
|
+
+-----------+-------------+ | +------------------------+ | |
|
|
1296
|
+
| | | +--------+-------+
|
|
1297
|
+
| returned true for| false:REJECT +-------->|onResponderReject
|
|
1298
|
+
| wantsResponderID | | | +----------------+
|
|
1299
|
+
| (now attempt | +------------------+-----+ |
|
|
1300
|
+
| handoff) | | onResponder | |
|
|
1301
|
+
+------------------->| TerminationRequest| |
|
|
1302
|
+
| +------------------+-----+ |
|
|
1303
|
+
| | | +----------------+
|
|
1304
|
+
| true:GRANT +-------->|onResponderGrant|
|
|
1305
|
+
| | +--------+-------+
|
|
1306
|
+
| +------------------------+ | |
|
|
1307
|
+
| | onResponderTerminate |<-----------+
|
|
1308
|
+
| +------------------+-----+ |
|
|
1309
|
+
| | | +----------------+
|
|
1310
|
+
| +-------->|onResponderStart|
|
|
1311
|
+
| | +----------------+
|
|
1312
|
+
Bubble to find first ID | |
|
|
1313
|
+
to return true:wantsResponderID| |
|
|
1314
|
+
| |
|
|
1315
|
+
+-------------+ | |
|
|
1316
|
+
| onTouchMove | | |
|
|
1317
|
+
+------+------+ none | |
|
|
1318
|
+
| return| |
|
|
1319
|
+
+-----------v-------------+true| +------------------------+ |
|
|
1320
|
+
|onMoveShouldSetResponder |----->|onResponderMove (cur) |<-----------+
|
|
1321
|
+
+-----------+-------------+ | +------------------------+ | |
|
|
1322
|
+
| | | +--------+-------+
|
|
1323
|
+
| returned true for| false:REJECT +-------->|onResponderRejec|
|
|
1324
|
+
| wantsResponderID | | | +----------------+
|
|
1325
|
+
| (now attempt | +------------------+-----+ |
|
|
1326
|
+
| handoff) | | onResponder | |
|
|
1327
|
+
+------------------->| TerminationRequest| |
|
|
1328
|
+
| +------------------+-----+ |
|
|
1329
|
+
| | | +----------------+
|
|
1330
|
+
| true:GRANT +-------->|onResponderGrant|
|
|
1331
|
+
| | +--------+-------+
|
|
1332
|
+
| +------------------------+ | |
|
|
1333
|
+
| | onResponderTerminate |<-----------+
|
|
1334
|
+
| +------------------+-----+ |
|
|
1335
|
+
| | | +----------------+
|
|
1336
|
+
| +-------->|onResponderMove |
|
|
1337
|
+
| | +----------------+
|
|
1338
|
+
| |
|
|
1339
|
+
| |
|
|
1340
|
+
Some active touch started| |
|
|
1341
|
+
inside current responder | +------------------------+ |
|
|
1342
|
+
+------------------------->| onResponderEnd | |
|
|
1343
|
+
| | +------------------------+ |
|
|
1344
|
+
+---+---------+ | |
|
|
1345
|
+
| onTouchEnd | | |
|
|
1346
|
+
+---+---------+ | |
|
|
1347
|
+
| | +------------------------+ |
|
|
1348
|
+
+------------------------->| onResponderEnd | |
|
|
1349
|
+
No active touches started| +-----------+------------+ |
|
|
1350
|
+
inside current responder | | |
|
|
1351
|
+
| v |
|
|
1352
|
+
| +------------------------+ |
|
|
1353
|
+
| | onResponderRelease | |
|
|
1354
|
+
| +------------------------+ |
|
|
1355
|
+
| |
|
|
1356
|
+
+ + */
|
|
1536
1357
|
|
|
1537
|
-
|
|
1538
|
-
|
|
1358
|
+
/**
|
|
1359
|
+
* A note about event ordering in the `EventPluginRegistry`.
|
|
1360
|
+
*
|
|
1361
|
+
* Suppose plugins are injected in the following order:
|
|
1362
|
+
*
|
|
1363
|
+
* `[R, S, C]`
|
|
1364
|
+
*
|
|
1365
|
+
* To help illustrate the example, assume `S` is `SimpleEventPlugin` (for
|
|
1366
|
+
* `onClick` etc) and `R` is `ResponderEventPlugin`.
|
|
1367
|
+
*
|
|
1368
|
+
* "Deferred-Dispatched Events":
|
|
1369
|
+
*
|
|
1370
|
+
* - The current event plugin system will traverse the list of injected plugins,
|
|
1371
|
+
* in order, and extract events by collecting the plugin's return value of
|
|
1372
|
+
* `extractEvents()`.
|
|
1373
|
+
* - These events that are returned from `extractEvents` are "deferred
|
|
1374
|
+
* dispatched events".
|
|
1375
|
+
* - When returned from `extractEvents`, deferred-dispatched events contain an
|
|
1376
|
+
* "accumulation" of deferred dispatches.
|
|
1377
|
+
* - These deferred dispatches are accumulated/collected before they are
|
|
1378
|
+
* returned, but processed at a later time by the `EventPluginRegistry` (hence the
|
|
1379
|
+
* name deferred).
|
|
1380
|
+
*
|
|
1381
|
+
* In the process of returning their deferred-dispatched events, event plugins
|
|
1382
|
+
* themselves can dispatch events on-demand without returning them from
|
|
1383
|
+
* `extractEvents`. Plugins might want to do this, so that they can use event
|
|
1384
|
+
* dispatching as a tool that helps them decide which events should be extracted
|
|
1385
|
+
* in the first place.
|
|
1386
|
+
*
|
|
1387
|
+
* "On-Demand-Dispatched Events":
|
|
1388
|
+
*
|
|
1389
|
+
* - On-demand-dispatched events are not returned from `extractEvents`.
|
|
1390
|
+
* - On-demand-dispatched events are dispatched during the process of returning
|
|
1391
|
+
* the deferred-dispatched events.
|
|
1392
|
+
* - They should not have side effects.
|
|
1393
|
+
* - They should be avoided, and/or eventually be replaced with another
|
|
1394
|
+
* abstraction that allows event plugins to perform multiple "rounds" of event
|
|
1395
|
+
* extraction.
|
|
1396
|
+
*
|
|
1397
|
+
* Therefore, the sequence of event dispatches becomes:
|
|
1398
|
+
*
|
|
1399
|
+
* - `R`s on-demand events (if any) (dispatched by `R` on-demand)
|
|
1400
|
+
* - `S`s on-demand events (if any) (dispatched by `S` on-demand)
|
|
1401
|
+
* - `C`s on-demand events (if any) (dispatched by `C` on-demand)
|
|
1402
|
+
* - `R`s extracted events (if any) (dispatched by `EventPluginRegistry`)
|
|
1403
|
+
* - `S`s extracted events (if any) (dispatched by `EventPluginRegistry`)
|
|
1404
|
+
* - `C`s extracted events (if any) (dispatched by `EventPluginRegistry`)
|
|
1405
|
+
*
|
|
1406
|
+
* In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`
|
|
1407
|
+
* on-demand dispatch returns `true` (and some other details are satisfied) the
|
|
1408
|
+
* `onResponderGrant` deferred dispatched event is returned from
|
|
1409
|
+
* `extractEvents`. The sequence of dispatch executions in this case
|
|
1410
|
+
* will appear as follows:
|
|
1411
|
+
*
|
|
1412
|
+
* - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)
|
|
1413
|
+
* - `touchStartCapture` (`EventPluginRegistry` dispatches as usual)
|
|
1414
|
+
* - `touchStart` (`EventPluginRegistry` dispatches as usual)
|
|
1415
|
+
* - `responderGrant/Reject` (`EventPluginRegistry` dispatches as usual)
|
|
1416
|
+
*/
|
|
1539
1417
|
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
// It's strange to get an `onMoveShouldSetResponder` when you're *already*
|
|
1543
|
-
// the responder.
|
|
1418
|
+
function setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
|
|
1419
|
+
var shouldSetEventType = isStartish(topLevelType) ? eventTypes.startShouldSetResponder : isMoveish(topLevelType) ? eventTypes.moveShouldSetResponder : topLevelType === TOP_SELECTION_CHANGE ? eventTypes.selectionChangeShouldSetResponder : eventTypes.scrollShouldSetResponder; // TODO: stop one short of the current responder.
|
|
1544
1420
|
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1421
|
+
var bubbleShouldSetFrom = !responderInst ? targetInst : getLowestCommonAncestor(responderInst, targetInst); // When capturing/bubbling the "shouldSet" event, we want to skip the target
|
|
1422
|
+
// (deepest ID) if it happens to be the current responder. The reasoning:
|
|
1423
|
+
// It's strange to get an `onMoveShouldSetResponder` when you're *already*
|
|
1424
|
+
// the responder.
|
|
1548
1425
|
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
accumulateTwoPhaseDispatches(shouldSetEvent);
|
|
1553
|
-
}
|
|
1426
|
+
var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst;
|
|
1427
|
+
var shouldSetEvent = ResponderSyntheticEvent.getPooled(shouldSetEventType, bubbleShouldSetFrom, nativeEvent, nativeEventTarget);
|
|
1428
|
+
shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
1554
1429
|
|
|
1555
|
-
|
|
1430
|
+
if (skipOverBubbleShouldSetFrom) {
|
|
1431
|
+
accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);
|
|
1432
|
+
} else {
|
|
1433
|
+
accumulateTwoPhaseDispatches(shouldSetEvent);
|
|
1434
|
+
}
|
|
1556
1435
|
|
|
1557
|
-
|
|
1558
|
-
shouldSetEvent.constructor.release(shouldSetEvent);
|
|
1559
|
-
}
|
|
1436
|
+
var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent);
|
|
1560
1437
|
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1438
|
+
if (!shouldSetEvent.isPersistent()) {
|
|
1439
|
+
shouldSetEvent.constructor.release(shouldSetEvent);
|
|
1440
|
+
}
|
|
1564
1441
|
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
accumulateDirectDispatches(grantEvent);
|
|
1569
|
-
var blockHostResponder = executeDirectDispatch(grantEvent) === true;
|
|
1442
|
+
if (!wantsResponderInst || wantsResponderInst === responderInst) {
|
|
1443
|
+
return null;
|
|
1444
|
+
}
|
|
1570
1445
|
|
|
1571
|
-
|
|
1572
|
-
var
|
|
1573
|
-
|
|
1574
|
-
accumulateDirectDispatches(
|
|
1575
|
-
var
|
|
1446
|
+
var extracted;
|
|
1447
|
+
var grantEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderGrant, wantsResponderInst, nativeEvent, nativeEventTarget);
|
|
1448
|
+
grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
1449
|
+
accumulateDirectDispatches(grantEvent);
|
|
1450
|
+
var blockHostResponder = executeDirectDispatch(grantEvent) === true;
|
|
1576
1451
|
|
|
1577
|
-
if (
|
|
1578
|
-
terminationRequestEvent.
|
|
1579
|
-
|
|
1452
|
+
if (responderInst) {
|
|
1453
|
+
var terminationRequestEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderTerminationRequest, responderInst, nativeEvent, nativeEventTarget);
|
|
1454
|
+
terminationRequestEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
1455
|
+
accumulateDirectDispatches(terminationRequestEvent);
|
|
1456
|
+
var shouldSwitch = !hasDispatches(terminationRequestEvent) || executeDirectDispatch(terminationRequestEvent);
|
|
1580
1457
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1458
|
+
if (!terminationRequestEvent.isPersistent()) {
|
|
1459
|
+
terminationRequestEvent.constructor.release(terminationRequestEvent);
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
if (shouldSwitch) {
|
|
1463
|
+
var terminateEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderTerminate, responderInst, nativeEvent, nativeEventTarget);
|
|
1464
|
+
terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
1465
|
+
accumulateDirectDispatches(terminateEvent);
|
|
1466
|
+
extracted = accumulate(extracted, [grantEvent, terminateEvent]);
|
|
1467
|
+
changeResponder(wantsResponderInst, blockHostResponder);
|
|
1468
|
+
} else {
|
|
1469
|
+
var rejectEvent = ResponderSyntheticEvent.getPooled(eventTypes.responderReject, wantsResponderInst, nativeEvent, nativeEventTarget);
|
|
1470
|
+
rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
1471
|
+
accumulateDirectDispatches(rejectEvent);
|
|
1472
|
+
extracted = accumulate(extracted, rejectEvent);
|
|
1473
|
+
}
|
|
1587
1474
|
} else {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
accumulateDirectDispatches(rejectEvent);
|
|
1591
|
-
extracted = accumulate(extracted, rejectEvent);
|
|
1475
|
+
extracted = accumulate(extracted, grantEvent);
|
|
1476
|
+
changeResponder(wantsResponderInst, blockHostResponder);
|
|
1592
1477
|
}
|
|
1593
|
-
} else {
|
|
1594
|
-
extracted = accumulate(extracted, grantEvent);
|
|
1595
|
-
changeResponder(wantsResponderInst, blockHostResponder);
|
|
1596
|
-
}
|
|
1597
1478
|
|
|
1598
|
-
|
|
1599
|
-
}
|
|
1600
|
-
/**
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1479
|
+
return extracted;
|
|
1480
|
+
}
|
|
1481
|
+
/**
|
|
1482
|
+
* A transfer is a negotiation between a currently set responder and the next
|
|
1483
|
+
* element to claim responder status. Any start event could trigger a transfer
|
|
1484
|
+
* of responderInst. Any move event could trigger a transfer.
|
|
1485
|
+
*
|
|
1486
|
+
* @param {string} topLevelType Record from `BrowserEventConstants`.
|
|
1487
|
+
* @return {boolean} True if a transfer of responder could possibly occur.
|
|
1488
|
+
*/
|
|
1608
1489
|
|
|
1609
1490
|
|
|
1610
|
-
function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) {
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
}
|
|
1616
|
-
/**
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1491
|
+
function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) {
|
|
1492
|
+
return topLevelInst && ( // responderIgnoreScroll: We are trying to migrate away from specifically
|
|
1493
|
+
// tracking native scroll events here and responderIgnoreScroll indicates we
|
|
1494
|
+
// will send topTouchCancel to handle canceling touch events instead
|
|
1495
|
+
topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll || trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE || isStartish(topLevelType) || isMoveish(topLevelType));
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Returns whether or not this touch end event makes it such that there are no
|
|
1499
|
+
* longer any touches that started inside of the current `responderInst`.
|
|
1500
|
+
*
|
|
1501
|
+
* @param {NativeEvent} nativeEvent Native touch end event.
|
|
1502
|
+
* @return {boolean} Whether or not this touch end event ends the responder.
|
|
1503
|
+
*/
|
|
1623
1504
|
|
|
1624
1505
|
|
|
1625
|
-
function noResponderTouches(nativeEvent) {
|
|
1626
|
-
|
|
1506
|
+
function noResponderTouches(nativeEvent) {
|
|
1507
|
+
var touches = nativeEvent.touches;
|
|
1627
1508
|
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1509
|
+
if (!touches || touches.length === 0) {
|
|
1510
|
+
return true;
|
|
1511
|
+
}
|
|
1631
1512
|
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1513
|
+
for (var i = 0; i < touches.length; i++) {
|
|
1514
|
+
var activeTouch = touches[i];
|
|
1515
|
+
var target = activeTouch.target;
|
|
1635
1516
|
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1517
|
+
if (target !== null && target !== undefined && target !== 0) {
|
|
1518
|
+
// Is the original touch location inside of the current responder?
|
|
1519
|
+
var targetInst = getInstanceFromNode(target);
|
|
1639
1520
|
|
|
1640
|
-
|
|
1641
|
-
|
|
1521
|
+
if (isAncestor(responderInst, targetInst)) {
|
|
1522
|
+
return false;
|
|
1523
|
+
}
|
|
1642
1524
|
}
|
|
1643
1525
|
}
|
|
1526
|
+
|
|
1527
|
+
return true;
|
|
1644
1528
|
}
|
|
1645
1529
|
|
|
1646
|
-
|
|
1647
|
-
|
|
1530
|
+
var ResponderEventPlugin = {
|
|
1531
|
+
/* For unit testing only */
|
|
1532
|
+
_getResponder: function () {
|
|
1533
|
+
return responderInst;
|
|
1534
|
+
},
|
|
1535
|
+
eventTypes: eventTypes,
|
|
1648
1536
|
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1537
|
+
/**
|
|
1538
|
+
* We must be resilient to `targetInst` being `null` on `touchMove` or
|
|
1539
|
+
* `touchEnd`. On certain platforms, this means that a native scroll has
|
|
1540
|
+
* assumed control and the original touch targets are destroyed.
|
|
1541
|
+
*/
|
|
1542
|
+
extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags) {
|
|
1543
|
+
if (isStartish(topLevelType)) {
|
|
1544
|
+
trackedTouchCount += 1;
|
|
1545
|
+
} else if (isEndish(topLevelType)) {
|
|
1546
|
+
if (trackedTouchCount >= 0) {
|
|
1547
|
+
trackedTouchCount -= 1;
|
|
1548
|
+
} else {
|
|
1549
|
+
{
|
|
1550
|
+
warn('Ended a touch event which was not counted in `trackedTouchCount`.');
|
|
1551
|
+
}
|
|
1655
1552
|
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
* `touchEnd`. On certain platforms, this means that a native scroll has
|
|
1659
|
-
* assumed control and the original touch targets are destroyed.
|
|
1660
|
-
*/
|
|
1661
|
-
extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags) {
|
|
1662
|
-
if (isStartish(topLevelType)) {
|
|
1663
|
-
trackedTouchCount += 1;
|
|
1664
|
-
} else if (isEndish(topLevelType)) {
|
|
1665
|
-
if (trackedTouchCount >= 0) {
|
|
1666
|
-
trackedTouchCount -= 1;
|
|
1667
|
-
} else {
|
|
1668
|
-
console.warn('Ended a touch event which was not counted in `trackedTouchCount`.');
|
|
1669
|
-
return null;
|
|
1553
|
+
return null;
|
|
1554
|
+
}
|
|
1670
1555
|
}
|
|
1671
|
-
}
|
|
1672
1556
|
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1557
|
+
ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent);
|
|
1558
|
+
var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent) ? setResponderAndExtractTransfer(topLevelType, targetInst, nativeEvent, nativeEventTarget) : null; // Responder may or may not have transferred on a new touch start/move.
|
|
1559
|
+
// Regardless, whoever is the responder after any potential transfer, we
|
|
1560
|
+
// direct all touch start/move/ends to them in the form of
|
|
1561
|
+
// `onResponderMove/Start/End`. These will be called for *every* additional
|
|
1562
|
+
// finger that move/start/end, dispatched directly to whoever is the
|
|
1563
|
+
// current responder at that moment, until the responder is "released".
|
|
1564
|
+
//
|
|
1565
|
+
// These multiple individual change touch events are are always bookended
|
|
1566
|
+
// by `onResponderGrant`, and one of
|
|
1567
|
+
// (`onResponderRelease/onResponderTerminate`).
|
|
1568
|
+
|
|
1569
|
+
var isResponderTouchStart = responderInst && isStartish(topLevelType);
|
|
1570
|
+
var isResponderTouchMove = responderInst && isMoveish(topLevelType);
|
|
1571
|
+
var isResponderTouchEnd = responderInst && isEndish(topLevelType);
|
|
1572
|
+
var incrementalTouch = isResponderTouchStart ? eventTypes.responderStart : isResponderTouchMove ? eventTypes.responderMove : isResponderTouchEnd ? eventTypes.responderEnd : null;
|
|
1573
|
+
|
|
1574
|
+
if (incrementalTouch) {
|
|
1575
|
+
var gesture = ResponderSyntheticEvent.getPooled(incrementalTouch, responderInst, nativeEvent, nativeEventTarget);
|
|
1576
|
+
gesture.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
1577
|
+
accumulateDirectDispatches(gesture);
|
|
1578
|
+
extracted = accumulate(extracted, gesture);
|
|
1579
|
+
}
|
|
1696
1580
|
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1581
|
+
var isResponderTerminate = responderInst && topLevelType === TOP_TOUCH_CANCEL;
|
|
1582
|
+
var isResponderRelease = responderInst && !isResponderTerminate && isEndish(topLevelType) && noResponderTouches(nativeEvent);
|
|
1583
|
+
var finalTouch = isResponderTerminate ? eventTypes.responderTerminate : isResponderRelease ? eventTypes.responderRelease : null;
|
|
1700
1584
|
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1585
|
+
if (finalTouch) {
|
|
1586
|
+
var finalEvent = ResponderSyntheticEvent.getPooled(finalTouch, responderInst, nativeEvent, nativeEventTarget);
|
|
1587
|
+
finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
|
|
1588
|
+
accumulateDirectDispatches(finalEvent);
|
|
1589
|
+
extracted = accumulate(extracted, finalEvent);
|
|
1590
|
+
changeResponder(null);
|
|
1591
|
+
}
|
|
1708
1592
|
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1593
|
+
return extracted;
|
|
1594
|
+
},
|
|
1595
|
+
GlobalResponderHandler: null,
|
|
1596
|
+
injection: {
|
|
1597
|
+
/**
|
|
1598
|
+
* @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler
|
|
1599
|
+
* Object that handles any change in responder. Use this to inject
|
|
1600
|
+
* integration with an existing touch handling system etc.
|
|
1601
|
+
*/
|
|
1602
|
+
injectGlobalResponderHandler: function (GlobalResponderHandler) {
|
|
1603
|
+
ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler;
|
|
1604
|
+
}
|
|
1720
1605
|
}
|
|
1721
|
-
}
|
|
1722
|
-
};
|
|
1723
|
-
|
|
1724
|
-
// Keep in sync with ReactDOM.js, ReactTestUtils.js, and ReactTestUtilsAct.js:
|
|
1606
|
+
};
|
|
1725
1607
|
|
|
1726
|
-
|
|
1727
|
-
var getInstanceFromNode = _ReactDOM$__SECRET_IN[0];
|
|
1728
|
-
var getNodeFromInstance = _ReactDOM$__SECRET_IN[1];
|
|
1729
|
-
var getFiberCurrentPropsFromNode = _ReactDOM$__SECRET_IN[2];
|
|
1730
|
-
var injectEventPluginsByName = _ReactDOM$__SECRET_IN[3];
|
|
1731
|
-
setComponentTree(getFiberCurrentPropsFromNode, getInstanceFromNode, getNodeFromInstance);
|
|
1608
|
+
// Keep in sync with ReactDOM.js, ReactTestUtils.js, and ReactTestUtilsAct.js:
|
|
1732
1609
|
|
|
1610
|
+
var _ReactDOM$__SECRET_IN = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Events,
|
|
1611
|
+
getInstanceFromNode$1 = _ReactDOM$__SECRET_IN[0],
|
|
1612
|
+
getNodeFromInstance$1 = _ReactDOM$__SECRET_IN[1],
|
|
1613
|
+
getFiberCurrentPropsFromNode$1 = _ReactDOM$__SECRET_IN[2],
|
|
1614
|
+
injectEventPluginsByName = _ReactDOM$__SECRET_IN[3];
|
|
1615
|
+
setComponentTree(getFiberCurrentPropsFromNode$1, getInstanceFromNode$1, getNodeFromInstance$1);
|
|
1733
1616
|
|
|
1734
|
-
var ReactDOMUnstableNativeDependencies = Object.freeze({
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1617
|
+
var ReactDOMUnstableNativeDependencies = /*#__PURE__*/Object.freeze({
|
|
1618
|
+
__proto__: null,
|
|
1619
|
+
ResponderEventPlugin: ResponderEventPlugin,
|
|
1620
|
+
ResponderTouchHistoryStore: ResponderTouchHistoryStore,
|
|
1621
|
+
injectEventPluginsByName: injectEventPluginsByName
|
|
1622
|
+
});
|
|
1739
1623
|
|
|
1740
|
-
var unstableNativeDependencies = ReactDOMUnstableNativeDependencies;
|
|
1624
|
+
var unstableNativeDependencies = ReactDOMUnstableNativeDependencies;
|
|
1741
1625
|
|
|
1742
|
-
return unstableNativeDependencies;
|
|
1626
|
+
return unstableNativeDependencies;
|
|
1743
1627
|
|
|
1744
1628
|
})));
|