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