1
+diff --git a/static_upstream/react/core/ReactEventEmitter.js b/static_upstream/react/core/ReactEventEmitter.js
2
+index 0f392c1..b028ad4 100644
3
+--- a/static_upstream/react/core/ReactEventEmitter.js
4
++++ b/static_upstream/react/core/ReactEventEmitter.js
5
+@@ -1,32 +1,43 @@
6
+ /**
7
+ * @providesModule ReactEventEmitter
8
++ * @typechecks
9
+ */
10
+
11
+ "use strict";
12
+
13
+ var BrowserEnv = require('BrowserEnv');
14
+ var EventConstants = require('EventConstants');
15
++var EventListener = require('EventListener');
16
+ var EventPluginHub = require('EventPluginHub');
17
+ var ExecutionEnvironment = require('ExecutionEnvironment');
18
+-var NormalizedEventListener = require('NormalizedEventListener');
19
+
20
+ var invariant = require('invariant');
21
+ var isEventSupported = require('isEventSupported');
22
+
23
+-var registrationNames = EventPluginHub.registrationNames;
24
+-var topLevelTypes = EventConstants.topLevelTypes;
25
+-var listen = NormalizedEventListener.listen;
26
+-var capture = NormalizedEventListener.capture;
27
+-
28
+ /**
29
+- * `ReactEventEmitter` is used to attach top-level event listeners. For example:
30
++ * Summary of `ReactEventEmitter` event handling:
31
+ *
32
+- * ReactEventEmitter.putListener('myID', 'onClick', myFunction);
33
++ * - We trap low level 'top-level' events.
34
++ *
35
++ * - We dedupe cross-browser event names into these 'top-level types' so that
36
++ * `DOMMouseScroll` or `mouseWheel` both become `topMouseWheel`.
37
++ *
38
++ * - At this point we have native browser events with the top-level type that
39
++ * was used to catch it at the top-level.
40
++ *
41
++ * - We continuously stream these native events (and their respective top-level
42
++ * types) to the event plugin system `EventPluginHub` and ask the plugin
43
++ * system if it was able to extract `AbstractEvent` objects. `AbstractEvent`
44
++ * objects are the events that applications actually deal with - they are not
45
++ * native browser events but cross-browser wrappers.
46
++ *
47
++ * - When returning the `AbstractEvent` objects, `EventPluginHub` will make
48
++ * sure each abstract event is annotated with "dispatches", which are the
49
++ * sequence of listeners (and IDs) that care about the event.
50
++ *
51
++ * - These `AbstractEvent` objects are fed back into the event plugin system,
52
++ * which in turn executes these dispatches.
53
+ *
54
+- * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
55
+- */
56
+-
57
+-/**
58
+ * Overview of React and the event system:
59
+ *
60
+ * .
61
+@@ -58,36 +69,23 @@ var capture = NormalizedEventListener.capture;
62
+ */
63
+
64
+ /**
65
+- * We listen for bubbled touch events on the document object.
66
+- *
67
+- * Firefox v8.01 (and possibly others) exhibited strange behavior when mounting
68
+- * `onmousemove` events at some node that was not the document element. The
69
+- * symptoms were that if your mouse is not moving over something contained
70
+- * within that mount point (for example on the background) the top-level
71
+- * listeners for `onmousemove` won't be called. However, if you register the
72
+- * `mousemove` on the document object, then it will of course catch all
73
+- * `mousemove`s. This along with iOS quirks, justifies restricting top-level
74
+- * listeners to the document object only, at least for these movement types of
75
+- * events and possibly all events.
76
+- *
77
+- * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
78
+- *
79
+- * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
80
+- * they bubble to document.
81
+- *
82
+- * @see http://www.quirksmode.org/dom/events/keys.html.
83
++ * Whether or not `ensureListening` has been invoked.
84
++ * @type {boolean}
85
++ * @private
86
+ */
87
+-
88
+ var _isListening = false;
89
+
90
+ /**
91
+- * Traps top-level events that bubble. Delegates to the main dispatcher
92
+- * `handleTopLevel` after performing some basic normalization via
93
+- * `TopLevelCallbackCreator.createTopLevelCallback`.
94
++ * Traps top-level events by using event bubbling.
95
++ *
96
++ * @param {string} topLevelType Record from `EventConstants`.
97
++ * @param {string} handlerBaseName Event name (e.g. "click").
98
++ * @param {DOMEventTarget} element Element on which to attach listener.
99
++ * @internal
100
+ */
101
+-function trapBubbledEvent(topLevelType, handlerBaseName, onWhat) {
102
+- listen(
103
+- onWhat,
104
++function trapBubbledEvent(topLevelType, handlerBaseName, element) {
105
++ EventListener.listen(
106
++ element,
107
+ handlerBaseName,
108
+ ReactEventEmitter.TopLevelCallbackCreator.createTopLevelCallback(
109
+ topLevelType
110
+@@ -97,10 +95,15 @@ function trapBubbledEvent(topLevelType, handlerBaseName, onWhat) {
111
+
112
+ /**
113
+ * Traps a top-level event by using event capturing.
114
++ *
115
++ * @param {string} topLevelType Record from `EventConstants`.
116
++ * @param {string} handlerBaseName Event name (e.g. "click").
117
++ * @param {DOMEventTarget} element Element on which to attach listener.
118
++ * @internal
119
+ */
120
+-function trapCapturedEvent(topLevelType, handlerBaseName, onWhat) {
121
+- capture(
122
+- onWhat,
123
++function trapCapturedEvent(topLevelType, handlerBaseName, element) {
124
++ EventListener.capture(
125
++ element,
126
+ handlerBaseName,
127
+ ReactEventEmitter.TopLevelCallbackCreator.createTopLevelCallback(
128
+ topLevelType
129
+@@ -109,62 +112,51 @@ function trapCapturedEvent(topLevelType, handlerBaseName, onWhat) {
130
+ }
131
+
132
+ /**
133
+- * Listens to document scroll and window resize events that may change the
134
+- * document scroll values. We store those results so as to discourage
135
+- * application code from asking the DOM itself which could trigger additional
136
+- * reflows.
137
++ * Listens to window scroll and resize events. We cache scroll values so that
138
++ * application code can access them without triggering reflows.
139
++ *
140
++ * NOTE: Scroll events do not bubble.
141
++ *
142
++ * @private
143
++ * @see http://www.quirksmode.org/dom/events/scroll.html
144
+ */
145
+-function registerDocumentScrollListener() {
146
+- listen(window, 'scroll', function(nativeEvent) {
147
+- if (nativeEvent.target === window) {
148
+- BrowserEnv.refreshAuthoritativeScrollValues();
149
+- }
150
+- });
151
+-}
152
+-
153
+-function registerDocumentResizeListener() {
154
+- listen(window, 'resize', function(nativeEvent) {
155
+- if (nativeEvent.target === window) {
156
+- BrowserEnv.refreshAuthoritativeScrollValues();
157
+- }
158
+- });
159
++function registerScrollValueMonitoring() {
160
++ var refresh = BrowserEnv.refreshAuthoritativeScrollValues;
161
++ EventListener.listen(window, 'scroll', refresh);
162
++ EventListener.listen(window, 'resize', refresh);
163
+ }
164
+
165
+ /**
166
+- * Summary of `ReactEventEmitter` event handling:
167
+- *
168
+- * - We trap low level 'top-level' events.
169
+- *
170
+- * - We dedupe cross-browser event names into these 'top-level types' so that
171
+- * `DOMMouseScroll` or `mouseWheel` both become `topMouseWheel`.
172
+- *
173
+- * - At this point we have native browser events with the top-level type that
174
+- * was used to catch it at the top-level.
175
++ * We listen for bubbled touch events on the document object.
176
+ *
177
+- * - We continuously stream these native events (and their respective top-level
178
+- * types) to the event plugin system `EventPluginHub` and ask the plugin
179
+- * system if it was able to extract `AbstractEvent` objects. `AbstractEvent`
180
+- * objects are the events that applications actually deal with - they are not
181
+- * native browser events but cross-browser wrappers.
182
++ * Firefox v8.01 (and possibly others) exhibited strange behavior when mounting
183
++ * `onmousemove` events at some node that was not the document element. The
184
++ * symptoms were that if your mouse is not moving over something contained
185
++ * within that mount point (for example on the background) the top-level
186
++ * listeners for `onmousemove` won't be called. However, if you register the
187
++ * `mousemove` on the document object, then it will of course catch all
188
++ * `mousemove`s. This along with iOS quirks, justifies restricting top-level
189
++ * listeners to the document object only, at least for these movement types of
190
++ * events and possibly all events.
191
+ *
192
+- * - When returning the `AbstractEvent` objects, `EventPluginHub` will make
193
+- * sure each abstract event is annotated with "dispatches", which are the
194
+- * sequence of listeners (and IDs) that care about the event.
195
++ * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
196
+ *
197
+- * - These `AbstractEvent` objects are fed back into the event plugin system,
198
+- * which in turn executes these dispatches.
199
++ * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
200
++ * they bubble to document.
201
+ *
202
++ * @param {boolean} touchNotMouse Listen to touch events instead of mouse.
203
+ * @private
204
++ * @see http://www.quirksmode.org/dom/events/keys.html.
205
+ */
206
+ function listenAtTopLevel(touchNotMouse) {
207
+ invariant(
208
+ !_isListening,
209
+ 'listenAtTopLevel(...): Cannot setup top-level listener more than once.'
210
+ );
211
++ var topLevelTypes = EventConstants.topLevelTypes;
212
+ var mountAt = document;
213
+
214
+- registerDocumentScrollListener();
215
+- registerDocumentResizeListener();
216
++ registerScrollValueMonitoring();
217
+ trapBubbledEvent(topLevelTypes.topMouseOver, 'mouseover', mountAt);
218
+ trapBubbledEvent(topLevelTypes.topMouseDown, 'mousedown', mountAt);
219
+ trapBubbledEvent(topLevelTypes.topMouseUp, 'mouseup', mountAt);
220
+@@ -212,82 +204,111 @@ function listenAtTopLevel(touchNotMouse) {
221
+ }
222
+
223
+ /**
224
+- * This is the heart of `ReactEventEmitter`. It simply streams the top-level
225
+- * native events to `EventPluginHub`.
226
++ * `ReactEventEmitter` is used to attach top-level event listeners. For example:
227
++ *
228
++ * ReactEventEmitter.putListener('myID', 'onClick', myFunction);
229
++ *
230
++ * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
231
+ *
232
+- * @param {object} topLevelType Record from `EventConstants`.
233
+- * @param {Event} nativeEvent A Standard Event with fixed `target` property.
234
+- * @param {DOMElement} renderedTarget Element of interest to the framework.
235
+- * @param {string} renderedTargetID string ID of `renderedTarget`.
236
+ * @internal
237
+ */
238
+-function handleTopLevel(
239
+- topLevelType,
240
+- nativeEvent,
241
+- renderedTargetID,
242
+- renderedTarget) {
243
+- var abstractEvents = EventPluginHub.extractAbstractEvents(
244
+- topLevelType,
245
+- nativeEvent,
246
+- renderedTargetID,
247
+- renderedTarget
248
+- );
249
++var ReactEventEmitter = {
250
+
251
+- // The event queue being processed in the same cycle allows preventDefault.
252
+- EventPluginHub.enqueueAbstractEvents(abstractEvents);
253
+- EventPluginHub.processAbstractEventQueue();
254
+-}
255
++ /**
256
++ * React references `ReactEventTopLevelCallback` using this property in order
257
++ * to allow dependency injection via `ensureListening`.
258
++ */
259
++ TopLevelCallbackCreator: null,
260
+
261
+-function setEnabled(enabled) {
262
+- invariant(
263
+- ExecutionEnvironment.canUseDOM,
264
+- 'setEnabled(...): Cannot toggle event listening in a Worker thread. This ' +
265
+- 'is likely a bug in the framework. Please report immediately.'
266
+- );
267
+- ReactEventEmitter.TopLevelCallbackCreator.setEnabled(enabled);
268
+-}
269
++ /**
270
++ * Ensures that top-level event delegation listeners are installed.
271
++ *
272
++ * There are issues with listening to both touch events and mouse events on
273
++ * the top-level, so we make the caller choose which one to listen to. (If
274
++ * there's a touch top-level listeners, anchors don't receive clicks for some
275
++ * reason, and only in some cases).
276
++ *
277
++ * @param {boolean} touchNotMouse Listen to touch events instead of mouse.
278
++ * @param {object} TopLevelCallbackCreator
279
++ */
280
++ ensureListening: function(touchNotMouse, TopLevelCallbackCreator) {
281
++ invariant(
282
++ ExecutionEnvironment.canUseDOM,
283
++ 'ensureListening(...): Cannot toggle event listening in a Worker ' +
284
++ 'thread. This is likely a bug in the framework. Please report ' +
285
++ 'immediately.'
286
++ );
287
++ if (!_isListening) {
288
++ ReactEventEmitter.TopLevelCallbackCreator = TopLevelCallbackCreator;
289
++ listenAtTopLevel(touchNotMouse);
290
++ _isListening = true;
291
++ }
292
++ },
293
+
294
+-function isEnabled() {
295
+- return ReactEventEmitter.TopLevelCallbackCreator.isEnabled();
296
+-}
297
++ /**
298
++ * Sets whether or not any created callbacks should be enabled.
299
++ *
300
++ * @param {boolean} enabled True if callbacks should be enabled.
301
++ */
302
++ setEnabled: function(enabled) {
303
++ invariant(
304
++ ExecutionEnvironment.canUseDOM,
305
++ 'setEnabled(...): Cannot toggle event listening in a Worker thread. ' +
306
++ 'This is likely a bug in the framework. Please report immediately.'
307
++ );
308
++ if (ReactEventEmitter.TopLevelCallbackCreator) {
309
++ ReactEventEmitter.TopLevelCallbackCreator.setEnabled(enabled);
310
++ }
311
++ },
312
+
313
+-/**
314
+- * Ensures that top-level event delegation listeners are listening at `mountAt`.
315
+- * There are issues with listening to both touch events and mouse events on the
316
+- * top-level, so we make the caller choose which one to listen to. (If there's a
317
+- * touch top-level listeners, anchors don't receive clicks for some reason, and
318
+- * only in some cases).
319
+- *
320
+- * @param {boolean} touchNotMouse Listen to touch events instead of mouse.
321
+- * @param {object} TopLevelCallbackCreator Module that can create top-level
322
+- * callback handlers.
323
+- * @internal
324
+- */
325
+-function ensureListening(touchNotMouse, TopLevelCallbackCreator) {
326
+- invariant(
327
+- ExecutionEnvironment.canUseDOM,
328
+- 'ensureListening(...): Cannot toggle event listening in a Worker thread. ' +
329
+- 'This is likely a bug in the framework. Please report immediately.'
330
+- );
331
+- if (!_isListening) {
332
+- ReactEventEmitter.TopLevelCallbackCreator = TopLevelCallbackCreator;
333
+- listenAtTopLevel(touchNotMouse);
334
+- _isListening = true;
335
+- }
336
+-}
337
++ /**
338
++ * @return {boolean} True if callbacks are enabled.
339
++ */
340
++ isEnabled: function() {
341
++ return !!(
342
++ ReactEventEmitter.TopLevelCallbackCreator &&
343
++ ReactEventEmitter.TopLevelCallbackCreator.isEnabled()
344
++ );
345
++ },
346
++
347
++ /**
348
++ * Streams a fired top-level event to `EventPluginHub` where plugins have the
349
++ * opportunity to create `ReactEvent`s to be dispatched.
350
++ *
351
++ * @param {string} topLevelType Record from `EventConstants`.
352
++ * @param {DOMEventTarget} topLevelTarget The listening component root node.
353
++ * @param {string} topLevelTargetID ID of `topLevelTarget`.
354
++ * @param {object} nativeEvent Native browser event.
355
++ */
356
++ handleTopLevel: function(
357
++ topLevelType,
358
++ topLevelTarget,
359
++ topLevelTargetID,
360
++ nativeEvent) {
361
++ var abstractEvents = EventPluginHub.extractAbstractEvents(
362
++ topLevelType,
363
++ topLevelTarget,
364
++ topLevelTargetID,
365
++ nativeEvent
366
++ );
367
++
368
++ // Event queue being processed in the same cycle allows `preventDefault`.
369
++ EventPluginHub.enqueueAbstractEvents(abstractEvents);
370
++ EventPluginHub.processAbstractEventQueue();
371
++ },
372
++
373
++ registrationNames: EventPluginHub.registrationNames,
374
+
375
+-var ReactEventEmitter = {
376
+- TopLevelCallbackCreator: null, // Injectable callback creator.
377
+- handleTopLevel: handleTopLevel,
378
+- setEnabled: setEnabled,
379
+- isEnabled: isEnabled,
380
+- ensureListening: ensureListening,
381
+- registrationNames: registrationNames,
382
+ putListener: EventPluginHub.putListener,
383
++
384
+ getListener: EventPluginHub.getListener,
385
++
386
+ deleteAllListeners: EventPluginHub.deleteAllListeners,
387
++
388
+ trapBubbledEvent: trapBubbledEvent,
389
++
390
+ trapCapturedEvent: trapCapturedEvent
391
++
392
+ };
393
+
394
+ module.exports = ReactEventEmitter;
395
+diff --git a/static_upstream/react/core/ReactEventTopLevelCallback.js b/static_upstream/react/core/ReactEventTopLevelCallback.js
396
+index e3e3c52..f60e30f 100644
397
+--- a/static_upstream/react/core/ReactEventTopLevelCallback.js
398
++++ b/static_upstream/react/core/ReactEventTopLevelCallback.js
399
+@@ -1,5 +1,6 @@
400
+ /**
401
+ * @providesModule ReactEventTopLevelCallback
402
++ * @typechecks
403
+ */
404
+
405
+ "use strict";
406
+@@ -9,51 +10,59 @@ var ReactEventEmitter = require('ReactEventEmitter');
407
+ var ReactInstanceHandles = require('ReactInstanceHandles');
408
+
409
+ var getDOMNodeID = require('getDOMNodeID');
410
++var getEventTarget = require('getEventTarget');
411
+
412
++/**
413
++ * @type {boolean}
414
++ * @private
415
++ */
416
+ var _topLevelListenersEnabled = true;
417
+
418
++/**
419
++ * Top-level callback creator used to implement event handling using delegation.
420
++ * This is used via dependency injection in `ReactEventEmitter.ensureListening`.
421
++ */
422
+ var ReactEventTopLevelCallback = {
423
+
424
+ /**
425
+- * @param {boolean} enabled Whether or not all callbacks that have ever been
426
+- * created with this module should be enabled.
427
++ * Sets whether or not any created callbacks should be enabled.
428
++ *
429
++ * @param {boolean} enabled True if callbacks should be enabled.
430
+ */
431
+ setEnabled: function(enabled) {
432
+ _topLevelListenersEnabled = !!enabled;
433
+ },
434
+
435
++ /**
436
++ * @return {boolean} True if callbacks are enabled.
437
++ */
438
+ isEnabled: function() {
439
+ return _topLevelListenersEnabled;
440
+ },
441
+
442
+ /**
443
+- * For a given `topLevelType`, creates a callback that could be added as a
444
+- * listener to the document. That top level callback will simply fix the
445
+- * native events before invoking `handleTopLevel`.
446
++ * Creates a callback for the supplied `topLevelType` that could be added as
447
++ * a listener to the document. The callback computes a `topLevelTarget` which
448
++ * should be the root node of a mounted React component where the listener
449
++ * is attached.
450
+ *
451
+- * - Raw native events cannot be trusted to describe their targets correctly
452
+- * so we expect that the argument to the nested function has already been
453
+- * fixed. But the `target` property may not be something of interest to
454
+- * React, so we find the most suitable target. But even at that point, DOM
455
+- * Elements (the target ) can't be trusted to describe their IDs correctly
456
+- * so we obtain the ID in a reliable manner and pass it to
457
+- * `handleTopLevel`. The target/id that we found to be relevant to our
458
+- * framework are called `renderedTarget`/`renderedTargetID` respectively.
459
++ * @param {string} topLevelType Record from `EventConstants`.
460
++ * @return {function} Callback for handling top-level events.
461
+ */
462
+ createTopLevelCallback: function(topLevelType) {
463
+- return function(fixedNativeEvent) {
464
++ return function(nativeEvent) {
465
+ if (!_topLevelListenersEnabled) {
466
+ return;
467
+ }
468
+- var renderedTarget = ReactInstanceHandles.getFirstReactDOM(
469
+- fixedNativeEvent.target
470
++ var topLevelTarget = ReactInstanceHandles.getFirstReactDOM(
471
++ getEventTarget(nativeEvent)
472
+ ) || ExecutionEnvironment.global;
473
+- var renderedTargetID = getDOMNodeID(renderedTarget);
474
++ var topLevelTargetID = getDOMNodeID(topLevelTarget) || '';
475
+ ReactEventEmitter.handleTopLevel(
476
+ topLevelType,
477
+- fixedNativeEvent,
478
+- renderedTargetID,
479
+- renderedTarget
480
++ topLevelTarget,
481
++ topLevelTargetID,
482
++ nativeEvent
483
+ );
484
+ };
485
+ }
486
+diff --git a/static_upstream/react/core/ReactInstanceHandles.js b/static_upstream/react/core/ReactInstanceHandles.js
487
+index 4eaf0e3..948ebcb 100644
488
+--- a/static_upstream/react/core/ReactInstanceHandles.js
489
++++ b/static_upstream/react/core/ReactInstanceHandles.js
490
+@@ -1,5 +1,6 @@
491
+ /**
492
+ * @providesModule ReactInstanceHandles
493
++ * @typechecks
494
+ */
495
+
496
+ "use strict";
497
+@@ -43,13 +44,13 @@ function isValidID(id) {
498
+ /**
499
+ * True if the supplied `node` is rendered by React.
500
+ *
501
+- * @param {DOMElement} node DOM Element to check.
502
++ * @param {DOMEventTarget} node DOM Element to check.
503
+ * @return {boolean} True if the DOM Element appears to be rendered by React.
504
+ * @private
505
+ */
506
+ function isRenderedByReact(node) {
507
+ var id = getDOMNodeID(node);
508
+- return id && id.charAt(0) === SEPARATOR;
509
++ return id ? id.charAt(0) === SEPARATOR : false;
510
+ }
511
+
512
+ /**
513
+@@ -126,8 +127,8 @@ var ReactInstanceHandles = {
514
+ * Traverses up the ancestors of the supplied node to find a node that is a
515
+ * DOM representation of a React component.
516
+ *
517
+- * @param {DOMElement} node
518
+- * @return {?DOMElement}
519
++ * @param {?DOMEventTarget} node
520
++ * @return {?DOMEventTarget}
521
+ * @internal
522
+ */
523
+ getFirstReactDOM: function(node) {
524
+@@ -145,9 +146,9 @@ var ReactInstanceHandles = {
525
+ * Finds a node with the supplied `id` inside of the supplied `ancestorNode`.
526
+ * Exploits the ID naming scheme to perform the search quickly.
527
+ *
528
+- * @param {DOMElement} ancestorNode Search from this root.
529
++ * @param {DOMEventTarget} ancestorNode Search from this root.
530
+ * @pararm {string} id ID of the DOM representation of the component.
531
+- * @return {?DOMElement} DOM element with the supplied `id`, if one exists.
532
++ * @return {?DOMEventTarget} DOM node with the supplied `id`, if one exists.
533
+ * @internal
534
+ */
535
+ findComponentRoot: function(ancestorNode, id) {
536
+@@ -214,7 +215,7 @@ var ReactInstanceHandles = {
537
+ * contains the React component with the supplied DOM ID.
538
+ *
539
+ * @param {string} id DOM ID of a React component.
540
+- * @return {string} DOM ID of the React component that is the root.
541
++ * @return {?string} DOM ID of the React component that is the root.
542
+ * @internal
543
+ */
544
+ getReactRootIDFromNodeID: function(id) {
545
+diff --git a/static_upstream/react/dom/getDOMNodeID.js b/static_upstream/react/dom/getDOMNodeID.js
546
+index 503f752..738239a 100644
547
+--- a/static_upstream/react/dom/getDOMNodeID.js
548
++++ b/static_upstream/react/dom/getDOMNodeID.js
549
+@@ -1,5 +1,6 @@
550
+ /**
551
+ * @providesModule getDOMNodeID
552
++ * @typechecks
553
+ */
554
+
555
+ "use strict";
556
+@@ -9,8 +10,8 @@
557
+ * control whose name or ID is "id". However, not all DOM nodes support
558
+ * `getAttributeNode` (document - which is not a form) so that is checked first.
559
+ *
560
+- * @param {Element} domNode DOM node element to return ID of.
561
+- * @returns {string} The ID of `domNode`.
562
++ * @param {DOMElement|DOMWindow|DOMDocument} domNode DOM node.
563
++ * @returns {string} ID of the supplied `domNode`.
564
+ */
565
+ function getDOMNodeID(domNode) {
566
+ if (domNode.getAttributeNode) {
567
+diff --git a/static_upstream/react/dom/getEventTarget.js b/static_upstream/react/dom/getEventTarget.js
568
+new file mode 100644
569
+index 0000000..d9337fd
570
+--- /dev/null
571
++++ b/static_upstream/react/dom/getEventTarget.js
572
+@@ -0,0 +1,25 @@
573
++/**
574
++ * @providesModule getEventTarget
575
++ * @typechecks
576
++ */
577
++
578
++var ExecutionEnvironment = require('ExecutionEnvironment');
579
++
580
++/**
581
++ * Gets the target node from a native browser event by accounting for
582
++ * inconsistencies in browser DOM APIs.
583
++ *
584
++ * @param {object} nativeEvent Native browser event.
585
++ * @return {DOMEventTarget} Target node.
586
++ */
587
++function getEventTarget(nativeEvent) {
588
++ var target =
589
++ nativeEvent.target ||
590
++ nativeEvent.srcElement ||
591
++ ExecutionEnvironment.global;
592
++ // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
593
++ // @see http://www.quirksmode.org/js/events_properties.html
594
++ return target.nodeType === 3 ? target.parentNode : target;
595
++}
596
++
597
++module.exports = getEventTarget;
598
+diff --git a/static_upstream/react/event/AbstractEvent.js b/static_upstream/react/event/AbstractEvent.js
599
+index 444031f..3e59b9f 100644
600
+--- a/static_upstream/react/event/AbstractEvent.js
601
++++ b/static_upstream/react/event/AbstractEvent.js
602
+@@ -30,14 +30,12 @@ var MAX_POOL_SIZE = 20;
603
+ * unreliable native event.
604
+ */
605
+ function AbstractEvent(
606
+- abstractEventType,
607
+- abstractTargetID, // Allows the abstract target to differ from native.
608
+- originatingTopLevelEventType,
609
++ reactEventType,
610
++ reactTargetID, // Allows the abstract target to differ from native.
611
+ nativeEvent,
612
+ data) {
613
+- this.type = abstractEventType;
614
+- this.abstractTargetID = abstractTargetID || '';
615
+- this.originatingTopLevelEventType = originatingTopLevelEventType;
616
++ this.reactEventType = reactEventType;
617
++ this.reactTargetID = reactTargetID || '';
618
+ this.nativeEvent = nativeEvent;
619
+ this.data = data;
620
+ // TODO: Deprecate storing target - doesn't always make sense for some types
621
+@@ -249,12 +247,10 @@ AbstractEvent.persistentCloneOf = function(abstractEvent) {
622
+ throwIf(!(abstractEvent instanceof AbstractEvent), CLONE_TYPE_ERR);
623
+ }
624
+ return new AbstractEvent(
625
+- abstractEvent.type,
626
+- abstractEvent.abstractTargetID,
627
+- abstractEvent.originatingTopLevelEventType,
628
++ abstractEvent.reactEventType,
629
++ abstractEvent.reactTargetID,
630
+ abstractEvent.nativeEvent,
631
+- abstractEvent.data,
632
+- abstractEvent.target
633
++ abstractEvent.data
634
+ );
635
+ };
636
+
637
+diff --git a/static_upstream/react/event/EventPluginHub.js b/static_upstream/react/event/EventPluginHub.js
638
+index 85cd51e..7092947 100644
639
+--- a/static_upstream/react/event/EventPluginHub.js
640
++++ b/static_upstream/react/event/EventPluginHub.js
641
+@@ -180,15 +180,16 @@ function recordAllRegistrationNames(eventType, PluginModule) {
642
+ * @param {AbstractEvent} abstractEvent to look at
643
+ */
644
+ function getPluginModuleForAbstractEvent(abstractEvent) {
645
+- if (abstractEvent.type.registrationName) {
646
+- return registrationNames[abstractEvent.type.registrationName];
647
++ var reactEventType = abstractEvent.reactEventType;
648
++ if (reactEventType.registrationName) {
649
++ return registrationNames[reactEventType.registrationName];
650
+ } else {
651
+- for (var phase in abstractEvent.type.phasedRegistrationNames) {
652
+- if (!abstractEvent.type.phasedRegistrationNames.hasOwnProperty(phase)) {
653
++ for (var phase in reactEventType.phasedRegistrationNames) {
654
++ if (!reactEventType.phasedRegistrationNames.hasOwnProperty(phase)) {
655
+ continue;
656
+ }
657
+ var PluginModule = registrationNames[
658
+- abstractEvent.type.phasedRegistrationNames[phase]
659
++ reactEventType.phasedRegistrationNames[phase]
660
+ ];
661
+ if (PluginModule) {
662
+ return PluginModule;
663
+@@ -209,36 +210,36 @@ var deleteAllListeners = function(domID) {
664
+ * Accepts the stream of top level native events, and gives every registered
665
+ * plugin an opportunity to extract `AbstractEvent`s with annotated dispatches.
666
+ *
667
+- * @param {Enum} topLevelType Record from `EventConstants`.
668
+- * @param {Event} nativeEvent A Standard Event with fixed `target` property.
669
+- * @param {Element} renderedTarget Element of interest to the framework, usually
670
+- * the same as `nativeEvent.target` but occasionally an element immediately
671
+- * above `nativeEvent.target` (the first DOM node recognized as one "rendered"
672
+- * by the framework at hand.)
673
+- * @param {string} renderedTargetID string ID of `renderedTarget`.
674
++ * @param {string} topLevelType Record from `EventConstants`.
675
++ * @param {DOMEventTarget} topLevelTarget The listening component root node.
676
++ * @param {string} topLevelTargetID ID of `topLevelTarget`.
677
++ * @param {object} nativeEvent Native browser event.
678
++ * @return {*} An accumulation of `AbstractEvent`s.
679
+ */
680
+-var extractAbstractEvents =
681
+- function(topLevelType, nativeEvent, renderedTargetID, renderedTarget) {
682
+- var abstractEvents;
683
+- var plugins = injection.plugins;
684
+- var len = plugins.length;
685
+- for (var i = 0; i < len; i++) {
686
+- // Not every plugin in the ordering may be loaded at runtime.
687
+- var possiblePlugin = plugins[i];
688
+- var extractedAbstractEvents =
689
+- possiblePlugin &&
690
+- possiblePlugin.extractAbstractEvents(
691
+- topLevelType,
692
+- nativeEvent,
693
+- renderedTargetID,
694
+- renderedTarget
695
+- );
696
++var extractAbstractEvents = function(
697
++ topLevelType,
698
++ topLevelTarget,
699
++ topLevelTargetID,
700
++ nativeEvent) {
701
++ var abstractEvents;
702
++ var plugins = injection.plugins;
703
++ for (var i = 0, l = plugins.length; i < l; i++) {
704
++ // Not every plugin in the ordering may be loaded at runtime.
705
++ var possiblePlugin = plugins[i];
706
++ if (possiblePlugin) {
707
++ var extractedAbstractEvents = possiblePlugin.extractAbstractEvents(
708
++ topLevelType,
709
++ topLevelTarget,
710
++ topLevelTargetID,
711
++ nativeEvent
712
++ );
713
+ if (extractedAbstractEvents) {
714
+ abstractEvents = accumulate(abstractEvents, extractedAbstractEvents);
715
+ }
716
+ }
717
+- return abstractEvents;
718
+- };
719
++ }
720
++ return abstractEvents;
721
++};
722
+
723
+ var enqueueAbstractEvents = function(abstractEvents) {
724
+ if (abstractEvents) {
725
+diff --git a/static_upstream/react/event/EventPropagators.js b/static_upstream/react/event/EventPropagators.js
726
+index 17c80f4..3d9103c 100644
727
+--- a/static_upstream/react/event/EventPropagators.js
728
++++ b/static_upstream/react/event/EventPropagators.js
729
+@@ -44,7 +44,7 @@ var injection = {
730
+ */
731
+ function listenerAtPhase(id, abstractEvent, propagationPhase) {
732
+ var registrationName =
733
+- abstractEvent.type.phasedRegistrationNames[propagationPhase];
734
++ abstractEvent.reactEventType.phasedRegistrationNames[propagationPhase];
735
+ return getListener(id, registrationName);
736
+ }
737
+
738
+@@ -78,9 +78,9 @@ function accumulateDirectionalDispatches(domID, upwards, abstractEvent) {
739
+ * have a different target.
740
+ */
741
+ function accumulateTwoPhaseDispatchesSingle(abstractEvent) {
742
+- if (abstractEvent && abstractEvent.type.phasedRegistrationNames) {
743
++ if (abstractEvent && abstractEvent.reactEventType.phasedRegistrationNames) {
744
+ injection.InstanceHandle.traverseTwoPhase(
745
+- abstractEvent.abstractTargetID,
746
++ abstractEvent.reactTargetID,
747
+ accumulateDirectionalDispatches,
748
+ abstractEvent
749
+ );
750
+@@ -91,11 +91,12 @@ function accumulateTwoPhaseDispatchesSingle(abstractEvent) {
751
+ /**
752
+ * Accumulates without regard to direction, does not look for phased
753
+ * registration names. Same as `accumulateDirectDispatchesSingle` but without
754
+- * requiring that the `abstractTargetID` be the same as the dispatched ID.
755
++ * requiring that the `reactTargetID` be the same as the dispatched ID.
756
+ */
757
+ function accumulateDispatches(id, ignoredDirection, abstractEvent) {
758
+- if (abstractEvent && abstractEvent.type.registrationName) {
759
+- var listener = getListener(id, abstractEvent.type.registrationName);
760
++ if (abstractEvent && abstractEvent.reactEventType.registrationName) {
761
++ var registrationName = abstractEvent.reactEventType.registrationName;
762
++ var listener = getListener(id, registrationName);
763
+ if (listener) {
764
+ abstractEvent._dispatchListeners =
765
+ accumulate(abstractEvent._dispatchListeners, listener);
766
+@@ -106,12 +107,12 @@ function accumulateDispatches(id, ignoredDirection, abstractEvent) {
767
+
768
+ /**
769
+ * Accumulates dispatches on an `AbstractEvent`, but only for the
770
+- * `abstractTargetID`.
771
++ * `reactTargetID`.
772
+ * @param {AbstractEvent} abstractEvent
773
+ */
774
+ function accumulateDirectDispatchesSingle(abstractEvent) {
775
+- if (abstractEvent && abstractEvent.type.registrationName) {
776
+- accumulateDispatches(abstractEvent.abstractTargetID, null, abstractEvent);
777
++ if (abstractEvent && abstractEvent.reactEventType.registrationName) {
778
++ accumulateDispatches(abstractEvent.reactTargetID, null, abstractEvent);
779
+ }
780
+ }
781
+
782
+diff --git a/static_upstream/react/event/NormalizedEventListener.js b/static_upstream/react/event/NormalizedEventListener.js
783
+deleted file mode 100644
784
+index 5506fe7..0000000
785
+--- a/static_upstream/react/event/NormalizedEventListener.js
786
++++ /dev/null
787
+@@ -1,70 +0,0 @@
788
+-/**
789
+- * @providesModule NormalizedEventListener
790
+- */
791
+-
792
+-var EventListener = require('EventListener');
793
+-
794
+-/**
795
+- * @param {?Event} eventParam Event parameter from an attached listener.
796
+- * @return {Event} Normalized event object.
797
+- * @private
798
+- */
799
+-function normalizeEvent(eventParam) {
800
+- var nativeEvent = eventParam || window.event;
801
+- // In some browsers (OLD FF), setting the target throws an error. A good way
802
+- // to tell if setting the target will throw an error, is to check if the event
803
+- // has a `target` property. Safari events have a `target` but it's not always
804
+- // normalized. Even if a `target` property exists, it's good to only set the
805
+- // target property if we realize that a change will actually take place.
806
+- var hasTargetProperty = 'target' in nativeEvent;
807
+- var eventTarget = nativeEvent.target || nativeEvent.srcElement || window;
808
+- // Safari may fire events on text nodes (Node.TEXT_NODE is 3)
809
+- // @see http://www.quirksmode.org/js/events_properties.html
810
+- var textNodeNormalizedTarget =
811
+- (eventTarget.nodeType === 3) ? eventTarget.parentNode : eventTarget;
812
+- if (!hasTargetProperty || nativeEvent.target !== textNodeNormalizedTarget) {
813
+- // TODO: Normalize the object via `merge()` to work with strict mode.
814
+- nativeEvent.target = textNodeNormalizedTarget;
815
+- }
816
+- return nativeEvent;
817
+-}
818
+-
819
+-function createNormalizedCallback(cb) {
820
+- return function(unfixedNativeEvent) {
821
+- cb(normalizeEvent(unfixedNativeEvent));
822
+- };
823
+-}
824
+-
825
+-var NormalizedEventListener = {
826
+-
827
+- /**
828
+- * Listens to bubbled events on a DOM node.
829
+- *
830
+- * NOTE: The listener will be invoked with a normalized event object.
831
+- *
832
+- * @param {DOMElement} el DOM element to register listener on.
833
+- * @param {string} handlerBaseName Event name, e.g. "click".
834
+- * @param {function} cb Callback function.
835
+- * @public
836
+- */
837
+- listen: function(el, handlerBaseName, cb) {
838
+- EventListener.listen(el, handlerBaseName, createNormalizedCallback(cb));
839
+- },
840
+-
841
+- /**
842
+- * Listens to captured events on a DOM node.
843
+- *
844
+- * NOTE: The listener will be invoked with a normalized event object.
845
+- *
846
+- * @param {DOMElement} el DOM element to register listener on.
847
+- * @param {string} handlerBaseName Event name, e.g. "click".
848
+- * @param {function} cb Callback function.
849
+- * @public
850
+- */
851
+- capture: function(el, handlerBaseName, cb) {
852
+- EventListener.capture(el, handlerBaseName, createNormalizedCallback(cb));
853
+- }
854
+-
855
+-};
856
+-
857
+-module.exports = NormalizedEventListener;
858
+diff --git a/static_upstream/react/eventPlugins/AnalyticsEventPluginFactory.js b/static_upstream/react/eventPlugins/AnalyticsEventPluginFactory.js
859
+index e1c4f38..8508047 100644
860
+--- a/static_upstream/react/eventPlugins/AnalyticsEventPluginFactory.js
861
++++ b/static_upstream/react/eventPlugins/AnalyticsEventPluginFactory.js
862
+@@ -122,20 +122,25 @@ if (__DEV__) {
863
+ * This plugin does not really extract any abstract events. Rather it just looks
864
+ * at the top level event and bumps up counters as appropriate
865
+ *
866
+- * @see EventPluginHub.extractAbstractEvents
867
++ * @param {string} topLevelType Record from `EventConstants`.
868
++ * @param {DOMEventTarget} topLevelTarget The listening component root node.
869
++ * @param {string} topLevelTargetID ID of `topLevelTarget`.
870
++ * @param {object} nativeEvent Native browser event.
871
++ * @return {*} An accumulation of `AbstractEvent`s.
872
++ * @see {EventPluginHub.extractAbstractEvents}
873
+ */
874
+ function extractAbstractEvents(
875
+ topLevelType,
876
+- nativeEvent,
877
+- renderedTargetID,
878
+- renderedTarget) {
879
++ topLevelTarget,
880
++ topLevelTargetID,
881
++ nativeEvent) {
882
+ var currentEvent = topLevelTypesToAnalyticsEvent[topLevelType];
883
+- if (!currentEvent || !renderedTarget || !renderedTarget.attributes) {
884
++ if (!currentEvent || !topLevelTarget || !topLevelTarget.attributes) {
885
+ return null;
886
+ }
887
+
888
+- var analyticsIDAttribute = renderedTarget.attributes[ANALYTICS_ID];
889
+- var analyticsEventsAttribute = renderedTarget.attributes[ANALYTICS_EVENTS];
890
++ var analyticsIDAttribute = topLevelTarget.attributes[ANALYTICS_ID];
891
++ var analyticsEventsAttribute = topLevelTarget.attributes[ANALYTICS_EVENTS];
892
+ if(!analyticsIDAttribute || !analyticsEventsAttribute) {
893
+ return null;
894
+ }
895
+diff --git a/static_upstream/react/eventPlugins/EnterLeaveEventPlugin.js b/static_upstream/react/eventPlugins/EnterLeaveEventPlugin.js
896
+index 856b1d7..7a00e71 100644
897
+--- a/static_upstream/react/eventPlugins/EnterLeaveEventPlugin.js
898
++++ b/static_upstream/react/eventPlugins/EnterLeaveEventPlugin.js
899
+@@ -1,5 +1,6 @@
900
+ /**
901
+ * @providesModule EnterLeaveEventPlugin
902
++ * @typechecks
903
+ */
904
+
905
+ "use strict";
906
+@@ -22,28 +23,32 @@ var abstractEventTypes = {
907
+ };
908
+
909
+ /**
910
+- * For almost every interaction we care about, there will be a top level
911
+- * `mouseOver` and `mouseOut` event that occur so we can usually only pay
912
+- * attention to one of the two (we'll pay attention to the `mouseOut` event) to
913
+- * avoid extracting a duplicate event. However, there's one interaction where
914
+- * there will be no `mouseOut` event to rely on - mousing from outside the
915
+- * browser *into* the chrome. We detect this scenario and only in that case, we
916
+- * use the `mouseOver` event.
917
++ * For almost every interaction we care about, there will be a top-level
918
++ * `mouseover` and `mouseout` event that occurs so only pay attention to one of
919
++ * the two (to avoid duplicate events). We use the `mouseout` event.
920
+ *
921
+- * @see EventPluginHub.extractAbstractEvents
922
++ * However, there's one interaction where there will be no `mouseout` event to
923
++ * rely on - mousing from outside the browser *into* the chrome. We detect this
924
++ * scenario and only in that case, we use the `mouseover` event.
925
++ *
926
++ * @param {string} topLevelType Record from `EventConstants`.
927
++ * @param {DOMEventTarget} topLevelTarget The listening component root node.
928
++ * @param {string} topLevelTargetID ID of `topLevelTarget`.
929
++ * @param {object} nativeEvent Native browser event.
930
++ * @return {*} An accumulation of `AbstractEvent`s.
931
++ * @see {EventPluginHub.extractAbstractEvents}
932
+ */
933
+ var extractAbstractEvents = function(
934
+ topLevelType,
935
+- nativeEvent,
936
+- renderedTargetID,
937
+- renderedTarget) {
938
+-
939
++ topLevelTarget,
940
++ topLevelTargetID,
941
++ nativeEvent) {
942
+ if (topLevelType === topLevelTypes.topMouseOver &&
943
+ (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
944
+- return;
945
++ return null;
946
+ }
947
+ if (topLevelType !== topLevelTypes.topMouseOut &&
948
+- topLevelType !== topLevelTypes.topMouseOver){
949
++ topLevelType !== topLevelTypes.topMouseOver) {
950
+ return null; // Must not be a mouse in or mouse out - ignoring.
951
+ }
952
+
953
+@@ -51,32 +56,33 @@ var extractAbstractEvents = function(
954
+ if (topLevelType === topLevelTypes.topMouseOut) {
955
+ to = getFirstReactDOM(nativeEvent.relatedTarget || nativeEvent.toElement) ||
956
+ ExecutionEnvironment.global;
957
+- from = renderedTarget;
958
++ from = topLevelTarget;
959
+ } else {
960
+- to = renderedTarget;
961
++ to = topLevelTarget;
962
+ from = ExecutionEnvironment.global;
963
+ }
964
+
965
+ // Nothing pertains to our managed components.
966
+- if (from === to ) {
967
+- return;
968
++ if (from === to) {
969
++ return null;
970
+ }
971
+
972
+ var fromID = from ? getDOMNodeID(from) : '';
973
+ var toID = to ? getDOMNodeID(to) : '';
974
++
975
+ var leave = AbstractEvent.getPooled(
976
+ abstractEventTypes.mouseLeave,
977
+ fromID,
978
+- topLevelType,
979
+ nativeEvent
980
+ );
981
+ var enter = AbstractEvent.getPooled(
982
+ abstractEventTypes.mouseEnter,
983
+ toID,
984
+- topLevelType,
985
+ nativeEvent
986
+ );
987
++
988
+ EventPropagators.accumulateEnterLeaveDispatches(leave, enter, fromID, toID);
989
++
990
+ return [leave, enter];
991
+ };
992
+
993
+diff --git a/static_upstream/react/eventPlugins/ResponderEventPlugin.js b/static_upstream/react/eventPlugins/ResponderEventPlugin.js
994
+index 4861cad..2e6b557 100644
995
+--- a/static_upstream/react/eventPlugins/ResponderEventPlugin.js
996
++++ b/static_upstream/react/eventPlugins/ResponderEventPlugin.js
997
+@@ -148,14 +148,13 @@ var abstractEventTypes = {
998
+ */
999
+
1000
+ /**
1001
+- * @param {TopLevelTypes} topLevelType Top level event type being examined.
1002
+- * @param {DOMEvent} nativeEvent Native DOM event.
1003
++ * @param {string} topLevelType Record from `EventConstants`.
1004
+ * @param {string} renderedTargetID ID of deepest React rendered element.
1005
+- *
1006
+- * @return {Accumulation<AbstractEvent>} Extracted events.
1007
++ * @param {object} nativeEvent Native browser event.
1008
++ * @return {*} An accumulation of extracted `AbstractEvent`s.
1009
+ */
1010
+ var setResponderAndExtractTransfer =
1011
+- function(topLevelType, nativeEvent, renderedTargetID) {
1012
++ function(topLevelType, renderedTargetID, nativeEvent) {
1013
+ var type;
1014
+ var shouldSetEventType =
1015
+ isStartish(topLevelType) ? abstractEventTypes.startShouldSetResponder :
1016
+@@ -221,7 +220,6 @@ var setResponderAndExtractTransfer =
1017
+ return extracted;
1018
+ };
1019
+
1020
+-
1021
+ /**
1022
+ * A transfer is a negotiation between a currently set responder and the next
1023
+ * element to claim responder status. Any start event could trigger a transfer
1024
+@@ -239,51 +237,60 @@ function canTriggerTransfer(topLevelType) {
1025
+ (isPressing && isMoveish(topLevelType));
1026
+ }
1027
+
1028
+-var extractAbstractEvents =
1029
+- function(topLevelType, nativeEvent, renderedTargetID, renderedTarget) {
1030
+- var extracted;
1031
+- // Must have missed an end event - reset the state here.
1032
+- if (responderID && isStartish(topLevelType)) {
1033
+- responderID = null;
1034
+- }
1035
+- if (isStartish(topLevelType)) {
1036
+- isPressing = true;
1037
+- } else if (isEndish(topLevelType)) {
1038
+- isPressing = false;
1039
+- }
1040
+- if (canTriggerTransfer(topLevelType)) {
1041
+- var transfer = setResponderAndExtractTransfer(
1042
+- topLevelType,
1043
+- nativeEvent,
1044
+- renderedTargetID,
1045
+- renderedTarget
1046
+- );
1047
+- if (transfer) {
1048
+- extracted = accumulate(extracted, transfer);
1049
+- }
1050
+- }
1051
+- // Now that we know the responder is set correctly, we can dispatch
1052
+- // responder type events (directly to the responder).
1053
+- var type = isMoveish(topLevelType) ? abstractEventTypes.responderMove :
1054
+- isEndish(topLevelType) ? abstractEventTypes.responderRelease :
1055
+- isStartish(topLevelType) ? abstractEventTypes.responderStart : null;
1056
+- if (type) {
1057
+- var data = AbstractEvent.normalizePointerData(nativeEvent);
1058
+- var gesture = AbstractEvent.getPooled(
1059
+- type,
1060
+- responderID,
1061
+- topLevelType,
1062
+- nativeEvent,
1063
+- data
1064
+- );
1065
+- EventPropagators.accumulateDirectDispatches(gesture);
1066
+- extracted = accumulate(extracted, gesture);
1067
+- }
1068
+- if (type === abstractEventTypes.responderRelease) {
1069
+- responderID = null;
1070
++/**
1071
++ * @param {string} topLevelType Record from `EventConstants`.
1072
++ * @param {DOMEventTarget} topLevelTarget The listening component root node.
1073
++ * @param {string} topLevelTargetID ID of `topLevelTarget`.
1074
++ * @param {object} nativeEvent Native browser event.
1075
++ * @return {*} An accumulation of `AbstractEvent`s.
1076
++ * @see {EventPluginHub.extractAbstractEvents}
1077
++ */
1078
++var extractAbstractEvents = function(
1079
++ topLevelType,
1080
++ topLevelTarget,
1081
++ topLevelTargetID,
1082
++ nativeEvent) {
1083
++ var extracted;
1084
++ // Must have missed an end event - reset the state here.
1085
++ if (responderID && isStartish(topLevelType)) {
1086
++ responderID = null;
1087
++ }
1088
++ if (isStartish(topLevelType)) {
1089
++ isPressing = true;
1090
++ } else if (isEndish(topLevelType)) {
1091
++ isPressing = false;
1092
++ }
1093
++ if (canTriggerTransfer(topLevelType)) {
1094
++ var transfer = setResponderAndExtractTransfer(
1095
++ topLevelType,
1096
++ topLevelTargetID,
1097
++ nativeEvent
1098
++ );
1099
++ if (transfer) {
1100
++ extracted = accumulate(extracted, transfer);
1101
+ }
1102
+- return extracted;
1103
+- };
1104
++ }
1105
++ // Now that we know the responder is set correctly, we can dispatch
1106
++ // responder type events (directly to the responder).
1107
++ var type = isMoveish(topLevelType) ? abstractEventTypes.responderMove :
1108
++ isEndish(topLevelType) ? abstractEventTypes.responderRelease :
1109
++ isStartish(topLevelType) ? abstractEventTypes.responderStart : null;
1110
++ if (type) {
1111
++ var data = AbstractEvent.normalizePointerData(nativeEvent);
1112
++ var gesture = AbstractEvent.getPooled(
1113
++ type,
1114
++ responderID,
1115
++ nativeEvent,
1116
++ data
1117
++ );
1118
++ EventPropagators.accumulateDirectDispatches(gesture);
1119
++ extracted = accumulate(extracted, gesture);
1120
++ }
1121
++ if (type === abstractEventTypes.responderRelease) {
1122
++ responderID = null;
1123
++ }
1124
++ return extracted;
1125
++};
1126
+
1127
+ /**
1128
+ * Event plugin for formalizing the negotiation between claiming locks on
1129
+diff --git a/static_upstream/react/eventPlugins/SimpleEventPlugin.js b/static_upstream/react/eventPlugins/SimpleEventPlugin.js
1130
+index 8f2cdda..84310e27 100644
1131
+--- a/static_upstream/react/eventPlugins/SimpleEventPlugin.js
1132
++++ b/static_upstream/react/eventPlugins/SimpleEventPlugin.js
1133
+@@ -141,6 +141,7 @@ var SimpleEventPlugin = {
1134
+ /**
1135
+ * Same as the default implementation, except cancels the event when return
1136
+ * value is false.
1137
++ *
1138
+ * @param {AbstractEvent} AbstractEvent to handle
1139
+ * @param {function} Application-level callback
1140
+ * @param {string} domID DOM id to pass to the callback.
1141
+@@ -154,48 +155,55 @@ var SimpleEventPlugin = {
1142
+ },
1143
+
1144
+ /**
1145
+- * @see EventPluginHub.extractAbstractEvents
1146
++ * @param {string} topLevelType Record from `EventConstants`.
1147
++ * @param {DOMEventTarget} topLevelTarget The listening component root node.
1148
++ * @param {string} topLevelTargetID ID of `topLevelTarget`.
1149
++ * @param {object} nativeEvent Native browser event.
1150
++ * @return {*} An accumulation of `AbstractEvent`s.
1151
++ * @see {EventPluginHub.extractAbstractEvents}
1152
+ */
1153
+- extractAbstractEvents:
1154
+- function(topLevelType, nativeEvent, renderedTargetID, renderedTarget) {
1155
+- var data;
1156
+- var abstractEventType =
1157
+- SimpleEventPlugin.topLevelTypesToAbstract[topLevelType];
1158
+- if (!abstractEventType) {
1159
+- return null;
1160
+- }
1161
+- switch(topLevelType) {
1162
+- case topLevelTypes.topMouseWheel:
1163
+- data = AbstractEvent.normalizeMouseWheelData(nativeEvent);
1164
+- break;
1165
+- case topLevelTypes.topScroll:
1166
+- data = AbstractEvent.normalizeScrollDataFromTarget(renderedTarget);
1167
+- break;
1168
+- case topLevelTypes.topClick:
1169
+- case topLevelTypes.topDoubleClick:
1170
+- case topLevelTypes.topChange:
1171
+- case topLevelTypes.topDOMCharacterDataModified:
1172
+- case topLevelTypes.topMouseDown:
1173
+- case topLevelTypes.topMouseUp:
1174
+- case topLevelTypes.topMouseMove:
1175
+- case topLevelTypes.topTouchMove:
1176
+- case topLevelTypes.topTouchStart:
1177
+- case topLevelTypes.topTouchEnd:
1178
+- data = AbstractEvent.normalizePointerData(nativeEvent);
1179
+- break;
1180
+- default:
1181
+- data = null;
1182
+- }
1183
+- var abstractEvent = AbstractEvent.getPooled(
1184
+- abstractEventType,
1185
+- renderedTargetID,
1186
+- topLevelType,
1187
+- nativeEvent,
1188
+- data
1189
+- );
1190
+- EventPropagators.accumulateTwoPhaseDispatches(abstractEvent);
1191
+- return abstractEvent;
1192
++ extractAbstractEvents: function(
1193
++ topLevelType,
1194
++ topLevelTarget,
1195
++ topLevelTargetID,
1196
++ nativeEvent) {
1197
++ var data;
1198
++ var abstractEventType =
1199
++ SimpleEventPlugin.topLevelTypesToAbstract[topLevelType];
1200
++ if (!abstractEventType) {
1201
++ return null;
1202
+ }
1203
++ switch(topLevelType) {
1204
++ case topLevelTypes.topMouseWheel:
1205
++ data = AbstractEvent.normalizeMouseWheelData(nativeEvent);
1206
++ break;
1207
++ case topLevelTypes.topScroll:
1208
++ data = AbstractEvent.normalizeScrollDataFromTarget(topLevelTarget);
1209
++ break;
1210
++ case topLevelTypes.topClick:
1211
++ case topLevelTypes.topDoubleClick:
1212
++ case topLevelTypes.topChange:
1213
++ case topLevelTypes.topDOMCharacterDataModified:
1214
++ case topLevelTypes.topMouseDown:
1215
++ case topLevelTypes.topMouseUp:
1216
++ case topLevelTypes.topMouseMove:
1217
++ case topLevelTypes.topTouchMove:
1218
++ case topLevelTypes.topTouchStart:
1219
++ case topLevelTypes.topTouchEnd:
1220
++ data = AbstractEvent.normalizePointerData(nativeEvent);
1221
++ break;
1222
++ default:
1223
++ data = null;
1224
++ }
1225
++ var abstractEvent = AbstractEvent.getPooled(
1226
++ abstractEventType,
1227
++ topLevelTargetID,
1228
++ nativeEvent,
1229
++ data
1230
++ );
1231
++ EventPropagators.accumulateTwoPhaseDispatches(abstractEvent);
1232
++ return abstractEvent;
1233
++ }
1234
+ };
1235
+
1236
+ SimpleEventPlugin.topLevelTypesToAbstract = {
1237
+diff --git a/static_upstream/react/eventPlugins/TapEventPlugin.js b/static_upstream/react/eventPlugins/TapEventPlugin.js
1238
+index 29e03cf..92c8392 100644
1239
+--- a/static_upstream/react/eventPlugins/TapEventPlugin.js
1240
++++ b/static_upstream/react/eventPlugins/TapEventPlugin.js
1241
+@@ -1,5 +1,6 @@
1242
+ /**
1243
+ * @providesModule TapEventPlugin
1244
++ * @typechecks
1245
+ */
1246
+
1247
+ "use strict";
1248
+@@ -32,26 +33,27 @@ var abstractEventTypes = {
1249
+ };
1250
+
1251
+ /**
1252
+- * @see EventPluginHub.extractAbstractEvents
1253
++ * @param {string} topLevelType Record from `EventConstants`.
1254
++ * @param {DOMEventTarget} topLevelTarget The listening component root node.
1255
++ * @param {string} topLevelTargetID ID of `topLevelTarget`.
1256
++ * @param {object} nativeEvent Native browser event.
1257
++ * @return {*} An accumulation of `AbstractEvent`s.
1258
++ * @see {EventPluginHub.extractAbstractEvents}
1259
+ */
1260
+ var extractAbstractEvents = function(
1261
+ topLevelType,
1262
+- nativeEvent,
1263
+- renderedTargetID,
1264
+- renderedTarget) {
1265
+-
1266
++ topLevelTarget,
1267
++ topLevelTargetID,
1268
++ nativeEvent) {
1269
+ if (!isStartish(topLevelType) && !isEndish(topLevelType)) {
1270
+ return;
1271
+ }
1272
+ var abstractEvent;
1273
+ var dist = eventDistance(startCoords, nativeEvent);
1274
+ if (isEndish(topLevelType) && dist < tapMoveThreshold) {
1275
+- var type = abstractEventTypes.touchTap;
1276
+- var abstractTargetID = renderedTargetID;
1277
+ abstractEvent = AbstractEvent.getPooled(
1278
+- type,
1279
+- abstractTargetID,
1280
+- topLevelType,
1281
++ abstractEventTypes.touchTap,
1282
++ topLevelTargetID,
1283
+ nativeEvent
1284
+ );
1285
+ }
1286
+diff --git a/static_upstream/react/eventPlugins/__tests__/ResponderEventPlugin-test.js b/static_upstream/react/eventPlugins/__tests__/ResponderEventPlugin-test.js
1287
+index c148a5a..1dfb44e 100644
1288
+--- a/static_upstream/react/eventPlugins/__tests__/ResponderEventPlugin-test.js
1289
++++ b/static_upstream/react/eventPlugins/__tests__/ResponderEventPlugin-test.js
1290
+@@ -153,8 +153,9 @@ var existsInExtraction = function(extracted, test) {
1291
+ function assertGrantEvent(id, extracted) {
1292
+ var test = function(abstractEvent) {
1293
+ return abstractEvent instanceof AbstractEvent &&
1294
+- abstractEvent.type === responderAbstractEventTypes.responderGrant &&
1295
+- abstractEvent.abstractTargetID === id;
1296
++ abstractEvent.reactEventType ===
1297
++ responderAbstractEventTypes.responderGrant &&
1298
++ abstractEvent.reactTargetID === id;
1299
+ };
1300
+ expect(ResponderEventPlugin.getResponderID()).toBe(id);
1301
+ expect(existsInExtraction(extracted, test)).toBe(true);
1302
+@@ -163,8 +164,9 @@ function assertGrantEvent(id, extracted) {
1303
+ function assertResponderMoveEvent(id, extracted) {
1304
+ var test = function(abstractEvent) {
1305
+ return abstractEvent instanceof AbstractEvent &&
1306
+- abstractEvent.type === responderAbstractEventTypes.responderMove &&
1307
+- abstractEvent.abstractTargetID === id;
1308
++ abstractEvent.reactEventType ===
1309
++ responderAbstractEventTypes.responderMove &&
1310
++ abstractEvent.reactTargetID === id;
1311
+ };
1312
+ expect(ResponderEventPlugin.getResponderID()).toBe(id);
1313
+ expect(existsInExtraction(extracted, test)).toBe(true);
1314
+@@ -173,8 +175,9 @@ function assertResponderMoveEvent(id, extracted) {
1315
+ function assertTerminateEvent(id, extracted) {
1316
+ var test = function(abstractEvent) {
1317
+ return abstractEvent instanceof AbstractEvent &&
1318
+- abstractEvent.type === responderAbstractEventTypes.responderTerminate &&
1319
+- abstractEvent.abstractTargetID === id;
1320
++ abstractEvent.reactEventType ===
1321
++ responderAbstractEventTypes.responderTerminate &&
1322
++ abstractEvent.reactTargetID === id;
1323
+ };
1324
+ expect(ResponderEventPlugin.getResponderID()).not.toBe(id);
1325
+ expect(existsInExtraction(extracted, test)).toBe(true);
1326
+@@ -183,8 +186,9 @@ function assertTerminateEvent(id, extracted) {
1327
+ function assertRelease(id, extracted) {
1328
+ var test = function(abstractEvent) {
1329
+ return abstractEvent instanceof AbstractEvent &&
1330
+- abstractEvent.type === responderAbstractEventTypes.responderRelease &&
1331
+- abstractEvent.abstractTargetID === id;
1332
++ abstractEvent.reactEventType ===
1333
++ responderAbstractEventTypes.responderRelease &&
1334
++ abstractEvent.reactTargetID === id;
1335
+ };
1336
+ expect(ResponderEventPlugin.getResponderID()).toBe(null);
1337
+ expect(existsInExtraction(extracted, test)).toBe(true);