@samitouri / QOS-React-2 / commits / 33dcf8a0b5

Set currentTarget on synthetic events

Fixes #658, fixes #659.

Ben Alpert committed Dec 30, 2013 at 11:52 UTC 33dcf8a0b57ed05ef675a714ab8762e9ae7471ed
6 files changed +91 -10
src/core/ReactDefaultInjection.js
+3 -1
@@ -29,6 +29,7 @@ var ReactDOMSelect = require('ReactDOMSelect');
29 var ReactDOMTextarea = require('ReactDOMTextarea');
30 var ReactEventEmitter = require('ReactEventEmitter');
31 var ReactEventTopLevelCallback = require('ReactEventTopLevelCallback');
32 +var ReactMount = require('ReactMount');
33 var ReactPerf = require('ReactPerf');
34 var ReactRootIndex = require('ReactRootIndex');
35
@@ -53,10 +54,11 @@ var ReactUpdates = require('ReactUpdates');
54 function inject() {
55 ReactEventEmitter.TopLevelCallbackCreator = ReactEventTopLevelCallback;
56 /**
56 - * Inject module for resolving DOM hierarchy and plugin ordering.
57 + * Inject modules for resolving DOM hierarchy and plugin ordering.
58 */
59 EventPluginHub.injection.injectEventPluginOrder(DefaultEventPluginOrder);
60 EventPluginHub.injection.injectInstanceHandle(ReactInstanceHandles);
61 + EventPluginHub.injection.injectMount(ReactMount);
62
63 /**
64 * Some important event plugins included by default (without having to require
src/core/__tests__/ReactEventEmitter-test.js
+47 -4
@@ -34,10 +34,16 @@ require('mock-modules')
34 var keyOf = require('keyOf');
35 var mocks = require('mocks');
36
37 -var EventPluginHub;
37 var ReactMount = require('ReactMount');
38 +var idToNode = {};
39 var getID = ReactMount.getID;
40 -var setID = ReactMount.setID;
40 +var setID = function(el, id) {
41 + ReactMount.setID(el, id);
42 + idToNode[id] = el;
43 +};
44 +var oldGetNode = ReactMount.getNode;
45 +
46 +var EventPluginHub;
47 var ReactEventEmitter;
48 var ReactTestUtils;
49 var TapEventPlugin;
@@ -93,10 +99,11 @@ describe('ReactEventEmitter', function() {
99 TapEventPlugin = require('TapEventPlugin');
100 ReactMount = require('ReactMount');
101 EventListener = require('EventListener');
96 - getID = ReactMount.getID;
97 - setID = ReactMount.setID;
102 ReactEventEmitter = require('ReactEventEmitter');
103 ReactTestUtils = require('ReactTestUtils');
104 + ReactMount.getNode = function(id) {
105 + return idToNode[id];
106 + };
107 idCallOrder = [];
108 tapMoveThreshold = TapEventPlugin.tapMoveThreshold;
109 EventPluginHub.injection.injectEventPluginsByName({
@@ -104,6 +111,10 @@ describe('ReactEventEmitter', function() {
111 });
112 });
113
114 + afterEach(function() {
115 + ReactMount.getNode = oldGetNode;
116 + });
117 +
118 it('should store a listener correctly', function() {
119 registerSimpleTestHandler();
120 var listener = ReactEventEmitter.getListener(getID(CHILD), ON_CLICK_KEY);
@@ -162,6 +173,38 @@ describe('ReactEventEmitter', function() {
173 expect(idCallOrder[2]).toBe(getID(GRANDPARENT));
174 });
175
176 + it('should set currentTarget', function() {
177 + ReactEventEmitter.putListener(
178 + getID(CHILD),
179 + ON_CLICK_KEY,
180 + function(event) {
181 + recordID(getID(CHILD));
182 + expect(event.currentTarget).toBe(CHILD);
183 + }
184 + );
185 + ReactEventEmitter.putListener(
186 + getID(PARENT),
187 + ON_CLICK_KEY,
188 + function(event) {
189 + recordID(getID(PARENT));
190 + expect(event.currentTarget).toBe(PARENT);
191 + }
192 + );
193 + ReactEventEmitter.putListener(
194 + getID(GRANDPARENT),
195 + ON_CLICK_KEY,
196 + function(event) {
197 + recordID(getID(GRANDPARENT));
198 + expect(event.currentTarget).toBe(GRANDPARENT);
199 + }
200 + );
201 + ReactTestUtils.Simulate.click(CHILD);
202 + expect(idCallOrder.length).toBe(3);
203 + expect(idCallOrder[0]).toBe(getID(CHILD));
204 + expect(idCallOrder[1]).toBe(getID(PARENT));
205 + expect(idCallOrder[2]).toBe(getID(GRANDPARENT));
206 + });
207 +
208 it('should support stopPropagation()', function() {
209 ReactEventEmitter.putListener(
210 getID(CHILD),
src/event/EventPluginHub.js
+6
@@ -85,6 +85,12 @@ var EventPluginHub = {
85 */
86 injection: {
87
88 + /**
89 + * @param {object} InjectedMount
90 + * @public
91 + */
92 + injectMount: EventPluginUtils.injection.injectMount,
93 +
94 /**
95 * @param {object} InjectedInstanceHandle
96 * @public
src/event/EventPluginUtils.js
+31 -3
@@ -22,6 +22,28 @@ var EventConstants = require('EventConstants');
22
23 var invariant = require('invariant');
24
25 +/**
26 + * Injected dependencies:
27 + */
28 +
29 +/**
30 + * - `Mount`: [required] Module that can convert between React dom IDs and
31 + * actual node references.
32 + */
33 +var injection = {
34 + Mount: null,
35 + injectMount: function(InjectedMount) {
36 + injection.Mount = InjectedMount;
37 + if (__DEV__) {
38 + invariant(
39 + InjectedMount && InjectedMount.getNode,
40 + 'EventPluginUtils.injection.injectMount(...): Injected Mount module ' +
41 + 'is missing getNode.'
42 + );
43 + }
44 + }
45 +};
46 +
47 var topLevelTypes = EventConstants.topLevelTypes;
48
49 function isEndish(topLevelType) {
@@ -39,6 +61,7 @@ function isStartish(topLevelType) {
61 topLevelType === topLevelTypes.topTouchStart;
62 }
63
64 +
65 var validateEventDispatches;
66 if (__DEV__) {
67 validateEventDispatches = function(event) {
@@ -90,7 +113,10 @@ function forEachEventDispatch(event, cb) {
113 * @param {string} domID DOM id to pass to the callback.
114 */
115 function executeDispatch(event, listener, domID) {
93 - listener(event, domID);
116 + event.currentTarget = injection.Mount.getNode(domID);
117 + var returnValue = listener(event, domID);
118 + event.currentTarget = null;
119 + return returnValue;
120 }
121
122 /**
@@ -175,11 +201,13 @@ var EventPluginUtils = {
201 isEndish: isEndish,
202 isMoveish: isMoveish,
203 isStartish: isStartish,
204 +
205 + executeDirectDispatch: executeDirectDispatch,
206 + executeDispatch: executeDispatch,
207 executeDispatchesInOrder: executeDispatchesInOrder,
208 executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
180 - executeDirectDispatch: executeDirectDispatch,
209 hasDispatches: hasDispatches,
182 - executeDispatch: executeDispatch,
210 + injection: injection,
211 useTouchEvents: false
212 };
213
src/event/synthetic/SyntheticEvent.js
+2 -1
@@ -33,7 +33,8 @@ var mergeInto = require('mergeInto');
33 var EventInterface = {
34 type: null,
35 target: getEventTarget,
36 - currentTarget: null,
36 + // currentTarget is set when dispatching; no use in copying it here
37 + currentTarget: emptyFunction.thatReturnsNull,
38 eventPhase: null,
39 bubbles: null,
40 cancelable: null,
src/eventPlugins/SimpleEventPlugin.js
+2 -1
@@ -19,6 +19,7 @@
19 "use strict";
20
21 var EventConstants = require('EventConstants');
22 +var EventPluginUtils = require('EventPluginUtils');
23 var EventPropagators = require('EventPropagators');
24 var SyntheticClipboardEvent = require('SyntheticClipboardEvent');
25 var SyntheticEvent = require('SyntheticEvent');
@@ -270,7 +271,7 @@ var SimpleEventPlugin = {
271 * @param {string} domID DOM ID to pass to the callback.
272 */
273 executeDispatch: function(event, listener, domID) {
273 - var returnValue = listener(event, domID);
274 + var returnValue = EventPluginUtils.executeDispatch(event, listener, domID);
275 if (returnValue === false) {
276 event.stopPropagation();
277 event.preventDefault();