@samitouri / QOS-React-2 / commits / 4a465fbd9a

Make events propagate through shadow DOMs.

Jim committed Jun 16, 2015 at 14:15 UTC 4a465fbd9a99815e9a0eb8b14af0c0423d9e8552
27 files changed +167 -68
src/renderers/dom/client/ReactEventListener.js
+50 -1
@@ -23,6 +23,8 @@ var assign = require('Object.assign');
23 var getEventTarget = require('getEventTarget');
24 var getUnboundedScrollPosition = require('getUnboundedScrollPosition');
25
26 +var DOCUMENT_FRAGMENT_NODE_TYPE = 11;
27 +
28 /**
29 * Finds the parent React component of `node`.
30 *
@@ -60,6 +62,17 @@ PooledClass.addPoolingTo(
62 );
63
64 function handleTopLevelImpl(bookKeeping) {
65 + if (bookKeeping.nativeEvent.path) {
66 + // New browsers have a path attribute on native events
67 + handleTopLevelWithPath(bookKeeping);
68 + } else {
69 + // Legacy browsers don't have a path attribute on native events
70 + handleTopLevelWithoutPath(bookKeeping);
71 + }
72 +}
73 +
74 +// Legacy browsers don't have a path attribute on native events
75 +function handleTopLevelWithoutPath(bookKeeping) {
76 var topLevelTarget = ReactMount.getFirstReactDOM(
77 getEventTarget(bookKeeping.nativeEvent)
78 ) || window;
@@ -81,11 +94,47 @@ function handleTopLevelImpl(bookKeeping) {
94 bookKeeping.topLevelType,
95 topLevelTarget,
96 topLevelTargetID,
84 - bookKeeping.nativeEvent
97 + bookKeeping.nativeEvent,
98 + getEventTarget(bookKeeping.nativeEvent)
99 );
100 }
101 }
102
103 +// New browsers have a path attribute on native events
104 +function handleTopLevelWithPath(bookKeeping) {
105 + var path = bookKeeping.nativeEvent.path;
106 + var currentNativeTarget = path[0];
107 + for (var i = 0; i < path.length; i++) {
108 + var currentPathElement = path[i];
109 + var currentPathElemenId = ReactMount.getID(currentPathElement);
110 + if (currentPathElement.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE) {
111 + currentNativeTarget = path[i + 1];
112 + }
113 + if (ReactMount.isRenderedByReact(currentPathElement)) {
114 + var newRootId = ReactInstanceHandles.getReactRootIDFromNodeID(
115 + currentPathElemenId
116 + );
117 + bookKeeping.ancestors.push(currentPathElement);
118 +
119 + var topLevelTargetID = ReactMount.getID(currentPathElement) || '';
120 + ReactEventListener._handleTopLevel(
121 + bookKeeping.topLevelType,
122 + currentPathElement,
123 + topLevelTargetID,
124 + bookKeeping.nativeEvent,
125 + currentNativeTarget
126 + );
127 +
128 + // Jump to the root of this React render tree
129 + while (currentPathElemenId !== newRootId) {
130 + i++;
131 + currentPathElement = path[i];
132 + currentPathElemenId = ReactMount.getID(currentPathElement);
133 + }
134 + }
135 + }
136 +}
137 +
138 function scrollValueMonitor(cb) {
139 var scrollPosition = getUnboundedScrollPosition(window);
140 cb(scrollPosition);
src/renderers/dom/client/eventPlugins/EnterLeaveEventPlugin.js
+6 -3
@@ -63,7 +63,8 @@ var EnterLeaveEventPlugin = {
63 topLevelType,
64 topLevelTarget,
65 topLevelTargetID,
66 - nativeEvent) {
66 + nativeEvent,
67 + nativeEventTarget) {
68 if (topLevelType === topLevelTypes.topMouseOver &&
69 (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
70 return null;
@@ -110,7 +111,8 @@ var EnterLeaveEventPlugin = {
111 var leave = SyntheticMouseEvent.getPooled(
112 eventTypes.mouseLeave,
113 fromID,
113 - nativeEvent
114 + nativeEvent,
115 + nativeEventTarget
116 );
117 leave.type = 'mouseleave';
118 leave.target = from;
@@ -119,7 +121,8 @@ var EnterLeaveEventPlugin = {
121 var enter = SyntheticMouseEvent.getPooled(
122 eventTypes.mouseEnter,
123 toID,
122 - nativeEvent
124 + nativeEvent,
125 + nativeEventTarget
126 );
127 enter.type = 'mouseenter';
128 enter.target = to;
src/renderers/dom/client/eventPlugins/SelectEventPlugin.js
+7 -6
@@ -92,7 +92,7 @@ function getSelection(node) {
92 * @param {object} nativeEvent
93 * @return {?SyntheticEvent}
94 */
95 -function constructSelectEvent(nativeEvent) {
95 +function constructSelectEvent(nativeEvent, nativeEventTarget) {
96 // Ensure we have the right element, and that the user is not dragging a
97 // selection (this matches native `select` event behavior). In HTML5, select
98 // fires only on input and textarea thus if there's no focused element we
@@ -111,7 +111,8 @@ function constructSelectEvent(nativeEvent) {
111 var syntheticEvent = SyntheticEvent.getPooled(
112 eventTypes.select,
113 activeElementID,
114 - nativeEvent
114 + nativeEvent,
115 + nativeEventTarget
116 );
117
118 syntheticEvent.type = 'select';
@@ -155,8 +156,8 @@ var SelectEventPlugin = {
156 topLevelType,
157 topLevelTarget,
158 topLevelTargetID,
158 - nativeEvent) {
159 -
159 + nativeEvent,
160 + nativeEventTarget) {
161 if (!hasListener) {
162 return null;
163 }
@@ -185,7 +186,7 @@ var SelectEventPlugin = {
186 case topLevelTypes.topContextMenu:
187 case topLevelTypes.topMouseUp:
188 mouseDown = false;
188 - return constructSelectEvent(nativeEvent);
189 + return constructSelectEvent(nativeEvent, nativeEventTarget);
190
191 // Chrome and IE fire non-standard event when selection is changed (and
192 // sometimes when it hasn't).
@@ -196,7 +197,7 @@ var SelectEventPlugin = {
197 case topLevelTypes.topSelectionChange:
198 case topLevelTypes.topKeyDown:
199 case topLevelTypes.topKeyUp:
199 - return constructSelectEvent(nativeEvent);
200 + return constructSelectEvent(nativeEvent, nativeEventTarget);
201 }
202
203 return null;
src/renderers/dom/client/eventPlugins/SimpleEventPlugin.js
+4 -2
@@ -334,7 +334,8 @@ var SimpleEventPlugin = {
334 topLevelType,
335 topLevelTarget,
336 topLevelTargetID,
337 - nativeEvent) {
337 + nativeEvent,
338 + nativeEventTarget) {
339 var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
340 if (!dispatchConfig) {
341 return null;
@@ -418,7 +419,8 @@ var SimpleEventPlugin = {
419 var event = EventConstructor.getPooled(
420 dispatchConfig,
421 topLevelTargetID,
421 - nativeEvent
422 + nativeEvent,
423 + nativeEventTarget
424 );
425 EventPropagators.accumulateTwoPhaseDispatches(event);
426 return event;
src/renderers/dom/client/eventPlugins/TapEventPlugin.js
+4 -2
@@ -101,7 +101,8 @@ var TapEventPlugin = {
101 topLevelType,
102 topLevelTarget,
103 topLevelTargetID,
104 - nativeEvent) {
104 + nativeEvent,
105 + nativeEventTarget) {
106 if (!isStartish(topLevelType) && !isEndish(topLevelType)) {
107 return null;
108 }
@@ -122,7 +123,8 @@ var TapEventPlugin = {
123 event = SyntheticUIEvent.getPooled(
124 eventTypes.touchTap,
125 topLevelTargetID,
125 - nativeEvent
126 + nativeEvent,
127 + nativeEventTarget
128 );
129 }
130 if (isStartish(topLevelType)) {
src/renderers/dom/client/eventPlugins/__tests__/EnterLeaveEventPlugin-test.js
+2 -1
@@ -48,7 +48,8 @@ describe('EnterLeaveEventPlugin', function() {
48 topLevelTypes.topMouseOver,
49 div,
50 ReactMount.getID(div),
51 - {target: div}
51 + {target: div},
52 + div
53 );
54 expect(extracted.length).toBe(2);
55
src/renderers/dom/client/eventPlugins/__tests__/SelectEventPlugin-test.js
+2 -1
@@ -30,7 +30,8 @@ describe('SelectEventPlugin', function() {
30 topLevelEvent,
31 node,
32 ReactMount.getID(node),
33 - {target: node}
33 + {target: node},
34 + node
35 );
36 }
37
src/renderers/dom/client/syntheticEvents/SyntheticClipboardEvent.js
+2 -2
@@ -34,8 +34,8 @@ var ClipboardEventInterface = {
34 * @param {object} nativeEvent Native browser event.
35 * @extends {SyntheticUIEvent}
36 */
37 -function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent) {
38 - SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
37 +function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
38 + SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
39 }
40
41 SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);
src/renderers/dom/client/syntheticEvents/SyntheticCompositionEvent.js
+3 -2
@@ -31,8 +31,9 @@ var CompositionEventInterface = {
31 function SyntheticCompositionEvent(
32 dispatchConfig,
33 dispatchMarker,
34 - nativeEvent) {
35 - SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
34 + nativeEvent,
35 + nativeEventTarget) {
36 + SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
37 }
38
39 SyntheticEvent.augmentClass(
src/renderers/dom/client/syntheticEvents/SyntheticDragEvent.js
+2 -2
@@ -28,8 +28,8 @@ var DragEventInterface = {
28 * @param {object} nativeEvent Native browser event.
29 * @extends {SyntheticUIEvent}
30 */
31 -function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent) {
32 - SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
31 +function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
32 + SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
33 }
34
35 SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);
src/renderers/dom/client/syntheticEvents/SyntheticEvent.js
+6 -5
@@ -16,15 +16,14 @@ var PooledClass = require('PooledClass');
16
17 var assign = require('Object.assign');
18 var emptyFunction = require('emptyFunction');
19 -var getEventTarget = require('getEventTarget');
19
20 /**
21 * @interface Event
22 * @see http://www.w3.org/TR/DOM-Level-3-Events/
23 */
24 var EventInterface = {
25 + path: null,
26 type: null,
27 - target: getEventTarget,
27 // currentTarget is set when dispatching; no use in copying it here
28 currentTarget: emptyFunction.thatReturnsNull,
29 eventPhase: null,
@@ -54,10 +53,12 @@ var EventInterface = {
53 * @param {string} dispatchMarker Marker identifying the event target.
54 * @param {object} nativeEvent Native browser event.
55 */
57 -function SyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent) {
56 +function SyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
57 this.dispatchConfig = dispatchConfig;
58 this.dispatchMarker = dispatchMarker;
59 this.nativeEvent = nativeEvent;
60 + this.target = nativeEventTarget;
61 + this.currentTarget = nativeEventTarget;
62
63 var Interface = this.constructor.Interface;
64 for (var propName in Interface) {
@@ -156,9 +157,9 @@ SyntheticEvent.augmentClass = function(Class, Interface) {
157 Class.Interface = assign({}, Super.Interface, Interface);
158 Class.augmentClass = Super.augmentClass;
159
159 - PooledClass.addPoolingTo(Class, PooledClass.threeArgumentPooler);
160 + PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler);
161 };
162
162 -PooledClass.addPoolingTo(SyntheticEvent, PooledClass.threeArgumentPooler);
163 +PooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler);
164
165 module.exports = SyntheticEvent;
src/renderers/dom/client/syntheticEvents/SyntheticFocusEvent.js
+2 -2
@@ -28,8 +28,8 @@ var FocusEventInterface = {
28 * @param {object} nativeEvent Native browser event.
29 * @extends {SyntheticUIEvent}
30 */
31 -function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent) {
32 - SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
31 +function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
32 + SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
33 }
34
35 SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);
src/renderers/dom/client/syntheticEvents/SyntheticInputEvent.js
+3 -2
@@ -32,8 +32,9 @@ var InputEventInterface = {
32 function SyntheticInputEvent(
33 dispatchConfig,
34 dispatchMarker,
35 - nativeEvent) {
36 - SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
35 + nativeEvent,
36 + nativeEventTarget) {
37 + SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
38 }
39
40 SyntheticEvent.augmentClass(
src/renderers/dom/client/syntheticEvents/SyntheticKeyboardEvent.js
+2 -2
@@ -76,8 +76,8 @@ var KeyboardEventInterface = {
76 * @param {object} nativeEvent Native browser event.
77 * @extends {SyntheticUIEvent}
78 */
79 -function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent) {
80 - SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
79 +function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
80 + SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
81 }
82
83 SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);
src/renderers/dom/client/syntheticEvents/SyntheticMouseEvent.js
+2 -2
@@ -72,8 +72,8 @@ var MouseEventInterface = {
72 * @param {object} nativeEvent Native browser event.
73 * @extends {SyntheticUIEvent}
74 */
75 -function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent) {
76 - SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
75 +function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
76 + SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
77 }
78
79 SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);
src/renderers/dom/client/syntheticEvents/SyntheticTouchEvent.js
+2 -2
@@ -37,8 +37,8 @@ var TouchEventInterface = {
37 * @param {object} nativeEvent Native browser event.
38 * @extends {SyntheticUIEvent}
39 */
40 -function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent) {
41 - SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
40 +function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
41 + SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
42 }
43
44 SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);
src/renderers/dom/client/syntheticEvents/SyntheticUIEvent.js
+2 -2
@@ -51,8 +51,8 @@ var UIEventInterface = {
51 * @param {object} nativeEvent Native browser event.
52 * @extends {SyntheticEvent}
53 */
54 -function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent) {
55 - SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
54 +function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
55 + SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
56 }
57
58 SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);
src/renderers/dom/client/syntheticEvents/SyntheticWheelEvent.js
+2 -2
@@ -50,8 +50,8 @@ var WheelEventInterface = {
50 * @param {object} nativeEvent Native browser event.
51 * @extends {SyntheticMouseEvent}
52 */
53 -function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent) {
54 - SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
53 +function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
54 + SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
55 }
56
57 SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);
src/renderers/dom/client/syntheticEvents/__tests__/SyntheticEvent-test.js
+2 -1
@@ -20,7 +20,8 @@ describe('SyntheticEvent', function() {
20 SyntheticEvent = require('SyntheticEvent');
21
22 createEvent = function(nativeEvent) {
23 - return SyntheticEvent.getPooled({}, '', nativeEvent);
23 + var target = require('getEventTarget')(nativeEvent);
24 + return SyntheticEvent.getPooled({}, '', nativeEvent, target);
25 };
26 });
27
src/renderers/dom/client/syntheticEvents/__tests__/SyntheticWheelEvent-test.js
+2 -1
@@ -20,7 +20,8 @@ describe('SyntheticWheelEvent', function() {
20 SyntheticWheelEvent = require('SyntheticWheelEvent');
21
22 createEvent = function(nativeEvent) {
23 - return SyntheticWheelEvent.getPooled({}, '', nativeEvent);
23 + var target = require('getEventTarget')(nativeEvent);
24 + return SyntheticWheelEvent.getPooled({}, '', nativeEvent, target);
25 };
26 });
27
src/renderers/shared/event/EventPluginHub.js
+4 -2
@@ -230,7 +230,8 @@ var EventPluginHub = {
230 topLevelType,
231 topLevelTarget,
232 topLevelTargetID,
233 - nativeEvent) {
233 + nativeEvent,
234 + nativeEventTarget) {
235 var events;
236 var plugins = EventPluginRegistry.plugins;
237 for (var i = 0; i < plugins.length; i++) {
@@ -241,7 +242,8 @@ var EventPluginHub = {
242 topLevelType,
243 topLevelTarget,
244 topLevelTargetID,
244 - nativeEvent
245 + nativeEvent,
246 + nativeEventTarget
247 );
248 if (extractedEvents) {
249 events = accumulateInto(events, extractedEvents);
src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js
+27 -12
@@ -325,7 +325,8 @@ to return true:wantsResponderID| |
325 function setResponderAndExtractTransfer(
326 topLevelType,
327 topLevelTargetID,
328 - nativeEvent) {
328 + nativeEvent,
329 + nativeEventTarget) {
330 var shouldSetEventType =
331 isStartish(topLevelType) ? eventTypes.startShouldSetResponder :
332 isMoveish(topLevelType) ? eventTypes.moveShouldSetResponder :
@@ -346,7 +347,8 @@ function setResponderAndExtractTransfer(
347 var shouldSetEvent = ResponderSyntheticEvent.getPooled(
348 shouldSetEventType,
349 bubbleShouldSetFrom,
349 - nativeEvent
350 + nativeEvent,
351 + nativeEventTarget
352 );
353 shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
354 if (skipOverBubbleShouldSetFrom) {
@@ -366,7 +368,8 @@ function setResponderAndExtractTransfer(
368 var grantEvent = ResponderSyntheticEvent.getPooled(
369 eventTypes.responderGrant,
370 wantsResponderID,
369 - nativeEvent
371 + nativeEvent,
372 + nativeEventTarget
373 );
374 grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
375
@@ -376,7 +379,8 @@ function setResponderAndExtractTransfer(
379 var terminationRequestEvent = ResponderSyntheticEvent.getPooled(
380 eventTypes.responderTerminationRequest,
381 responderID,
379 - nativeEvent
382 + nativeEvent,
383 + nativeEventTarget
384 );
385 terminationRequestEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
386 EventPropagators.accumulateDirectDispatches(terminationRequestEvent);
@@ -391,7 +395,8 @@ function setResponderAndExtractTransfer(
395 var terminateEvent = ResponderSyntheticEvent.getPooled(
396 terminateType,
397 responderID,
394 - nativeEvent
398 + nativeEvent,
399 + nativeEventTarget
400 );
401 terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
402 EventPropagators.accumulateDirectDispatches(terminateEvent);
@@ -401,7 +406,8 @@ function setResponderAndExtractTransfer(
406 var rejectEvent = ResponderSyntheticEvent.getPooled(
407 eventTypes.responderReject,
408 wantsResponderID,
404 - nativeEvent
409 + nativeEvent,
410 + nativeEventTarget
411 );
412 rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
413 EventPropagators.accumulateDirectDispatches(rejectEvent);
@@ -487,8 +493,8 @@ var ResponderEventPlugin = {
493 topLevelType,
494 topLevelTarget,
495 topLevelTargetID,
490 - nativeEvent) {
491 -
496 + nativeEvent,
497 + nativeEventTarget) {
498 if (isStartish(topLevelType)) {
499 trackedTouchCount += 1;
500 } else if (isEndish(topLevelType)) {
@@ -499,10 +505,14 @@ var ResponderEventPlugin = {
505 );
506 }
507
502 - ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent);
508 + ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent, nativeEventTarget);
509
510 var extracted = canTriggerTransfer(topLevelType, topLevelTargetID) ?
505 - setResponderAndExtractTransfer(topLevelType, topLevelTargetID, nativeEvent) :
511 + setResponderAndExtractTransfer(
512 + topLevelType,
513 + topLevelTargetID,
514 + nativeEvent,
515 + nativeEventTarget) :
516 null;
517 // Responder may or may not have transfered on a new touch start/move.
518 // Regardless, whoever is the responder after any potential transfer, we
@@ -525,7 +535,12 @@ var ResponderEventPlugin = {
535
536 if (incrementalTouch) {
537 var gesture =
528 - ResponderSyntheticEvent.getPooled(incrementalTouch, responderID, nativeEvent);
538 + ResponderSyntheticEvent.getPooled(
539 + incrementalTouch,
540 + responderID,
541 + nativeEvent,
542 + nativeEventTarget
543 + );
544 gesture.touchHistory = ResponderTouchHistoryStore.touchHistory;
545 EventPropagators.accumulateDirectDispatches(gesture);
546 extracted = accumulate(extracted, gesture);
@@ -545,7 +560,7 @@ var ResponderEventPlugin = {
560 null;
561 if (finalTouch) {
562 var finalEvent =
548 - ResponderSyntheticEvent.getPooled(finalTouch, responderID, nativeEvent);
563 + ResponderSyntheticEvent.getPooled(finalTouch, responderID, nativeEvent, nativeEventTarget);
564 finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
565 EventPropagators.accumulateDirectDispatches(finalEvent);
566 extracted = accumulate(extracted, finalEvent);
src/renderers/shared/event/eventPlugins/ResponderSyntheticEvent.js
+2 -2
@@ -31,8 +31,8 @@ var ResponderEventInterface = {
31 * @param {object} nativeEvent Native event.
32 * @extends {SyntheticEvent}
33 */
34 -function ResponderSyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent) {
35 - SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
34 +function ResponderSyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
35 + SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
36 }
37
38 SyntheticEvent.augmentClass(ResponderSyntheticEvent, ResponderEventInterface);
src/renderers/shared/event/eventPlugins/__tests__/ResponderEventPlugin-test.js
+9 -5
@@ -67,7 +67,7 @@ var antiSubsequence = function(arr, indices) {
67 * @param allTouchHandles
68 */
69 var _touchConfig =
70 - function(topType, targetNodeHandle, allTouchHandles, changedIndices) {
70 + function(topType, targetNodeHandle, allTouchHandles, changedIndices, eventTarget) {
71 var allTouchObjects = allTouchHandles.map(touch);
72 var changedTouchObjects = subsequence(allTouchObjects, changedIndices);
73 var activeTouchObjects =
@@ -112,7 +112,8 @@ var startConfig = function(nodeHandle, allTouchHandles, changedIndices) {
112 topLevelTypes.topTouchStart,
113 nodeHandle,
114 allTouchHandles,
115 - changedIndices
115 + changedIndices,
116 + nodeHandle
117 );
118 };
119
@@ -124,7 +125,8 @@ var moveConfig = function(nodeHandle, allTouchHandles, changedIndices) {
125 topLevelTypes.topTouchMove,
126 nodeHandle,
127 allTouchHandles,
127 - changedIndices
128 + changedIndices,
129 + nodeHandle
130 );
131 };
132
@@ -136,7 +138,8 @@ var endConfig = function(nodeHandle, allTouchHandles, changedIndices) {
138 topLevelTypes.topTouchEnd,
139 nodeHandle,
140 allTouchHandles,
139 - changedIndices
141 + changedIndices,
142 + nodeHandle
143 );
144 };
145
@@ -290,7 +293,8 @@ var run = function(config, hierarchyConfig, nativeEventConfig) {
293 nativeEventConfig.topLevelType,
294 nativeEventConfig.target,
295 nativeEventConfig.targetID,
293 - nativeEventConfig.nativeEvent
296 + nativeEventConfig.nativeEvent,
297 + nativeEventConfig.target
298 );
299
300 // At this point the negotiation events have been dispatched as part of the
src/renderers/shared/reconciler/ReactEventEmitterMixin.js
+4 -3
@@ -33,14 +33,15 @@ var ReactEventEmitterMixin = {
33 topLevelType,
34 topLevelTarget,
35 topLevelTargetID,
36 - nativeEvent) {
36 + nativeEvent,
37 + nativeEventTarget) {
38 var events = EventPluginHub.extractEvents(
39 topLevelType,
40 topLevelTarget,
41 topLevelTargetID,
41 - nativeEvent
42 + nativeEvent,
43 + nativeEventTarget
44 );
43 -
45 runEventQueueInBatch(events);
46 },
47 };
src/shared/utils/PooledClass.js
+12
@@ -53,6 +53,17 @@ var threeArgumentPooler = function(a1, a2, a3) {
53 }
54 };
55
56 +var fourArgumentPooler = function(a1, a2, a3, a4) {
57 + var Klass = this;
58 + if (Klass.instancePool.length) {
59 + var instance = Klass.instancePool.pop();
60 + Klass.call(instance, a1, a2, a3, a4);
61 + return instance;
62 + } else {
63 + return new Klass(a1, a2, a3, a4);
64 + }
65 +};
66 +
67 var fiveArgumentPooler = function(a1, a2, a3, a4, a5) {
68 var Klass = this;
69 if (Klass.instancePool.length) {
@@ -106,6 +117,7 @@ var PooledClass = {
117 oneArgumentPooler: oneArgumentPooler,
118 twoArgumentPooler: twoArgumentPooler,
119 threeArgumentPooler: threeArgumentPooler,
120 + fourArgumentPooler: fourArgumentPooler,
121 fiveArgumentPooler: fiveArgumentPooler,
122 };
123
src/test/ReactTestUtils.js
+2 -1
@@ -450,7 +450,8 @@ function makeSimulator(eventType) {
450 var event = new SyntheticEvent(
451 dispatchConfig,
452 ReactMount.getID(node),
453 - fakeNativeEvent
453 + fakeNativeEvent,
454 + node
455 );
456 assign(event, eventData);
457