Do not bind topLevelType to dispatch (#13618)
* Do not bind topLevelType to dispatch A previous change made it such that all top level event types correspond to their associated native event string values. This commit eliminates the .bind attached to dispatch and fixes a related flow type. * Add note about why casting event.type to a topLevelType is safe * Move interactiveUpdates comment to point of assignment
Nathan Hunzaker committed
Sep 14, 2018 at 16:08 UTC
0c9c591bfb4c280d69bc9c1dd692ab0028bb0f8e
4 files changed
+23
-31
packages/events/PluginModuleType.js
+1
-1
@@ -16,7 +16,7 @@ import type {TopLevelType} from './TopLevelEventTypes';
16
17
export type EventTypes = {[key: string]: DispatchConfig};
18
19
-export type AnyNativeEvent = Event | KeyboardEvent | MouseEvent | Touch;
19
+export type AnyNativeEvent = Event | KeyboardEvent | MouseEvent | TouchEvent;
20
21
export type PluginName = string;
22
packages/events/ReactGenericBatching.js
+4
-4
@@ -20,8 +20,8 @@ import {
20
let _batchedUpdatesImpl = function(fn, bookkeeping) {
21
return fn(bookkeeping);
22
};
23
-let _interactiveUpdatesImpl = function(fn, a, b) {
24
- return fn(a, b);
23
+let _interactiveUpdatesImpl = function(fn, a) {
24
+ return fn(a);
25
};
26
let _flushInteractiveUpdatesImpl = function() {};
27
@@ -52,8 +52,8 @@ export function batchedUpdates(fn, bookkeeping) {
52
}
53
}
54
55
-export function interactiveUpdates(fn, a, b) {
56
- return _interactiveUpdatesImpl(fn, a, b);
55
+export function interactiveUpdates(fn, a) {
56
+ return _interactiveUpdatesImpl(fn, a);
57
}
58
59
export function flushInteractiveUpdates() {
packages/react-dom/src/events/ReactDOMEventListener.js
+14
-24
@@ -21,6 +21,7 @@ import getEventTarget from './getEventTarget';
21
import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
22
import SimpleEventPlugin from './SimpleEventPlugin';
23
import {getRawEventName} from './DOMTopLevelEventTypes';
24
+import {unsafeCastStringToDOMTopLevelType} from 'events/TopLevelEventTypes';
25
26
const {isInteractiveTopLevelEventType} = SimpleEventPlugin;
27
@@ -48,7 +49,6 @@ function findRootContainerNode(inst) {
49
50
// Used to store ancestor hierarchy in top level callback
51
function getTopLevelCallbackBookKeeping(
51
- topLevelType,
52
nativeEvent,
53
targetInst,
54
): {
@@ -57,6 +57,9 @@ function getTopLevelCallbackBookKeeping(
57
targetInst: Fiber | null,
58
ancestors: Array<Fiber>,
59
} {
60
+ // This is safe because DOMTopLevelTypes are always native event type strings
61
+ const topLevelType = unsafeCastStringToDOMTopLevelType(nativeEvent.type);
62
+
63
if (callbackBookkeepingPool.length) {
64
const instance = callbackBookkeepingPool.pop();
65
instance.topLevelType = topLevelType;
@@ -141,16 +144,13 @@ export function trapBubbledEvent(
144
if (!element) {
145
return null;
146
}
147
+
148
+ // Check if interactive and wrap in interactiveUpdates
149
const dispatch = isInteractiveTopLevelEventType(topLevelType)
150
? dispatchInteractiveEvent
151
: dispatchEvent;
152
148
- addEventBubbleListener(
149
- element,
150
- getRawEventName(topLevelType),
151
- // Check if interactive and wrap in interactiveUpdates
152
- dispatch.bind(null, topLevelType),
153
- );
153
+ addEventBubbleListener(element, getRawEventName(topLevelType), dispatch);
154
}
155
156
/**
@@ -169,26 +169,20 @@ export function trapCapturedEvent(
169
if (!element) {
170
return null;
171
}
172
+
173
+ // Check if interactive and wrap in interactiveUpdates
174
const dispatch = isInteractiveTopLevelEventType(topLevelType)
175
? dispatchInteractiveEvent
176
: dispatchEvent;
177
176
- addEventCaptureListener(
177
- element,
178
- getRawEventName(topLevelType),
179
- // Check if interactive and wrap in interactiveUpdates
180
- dispatch.bind(null, topLevelType),
181
- );
178
+ addEventCaptureListener(element, getRawEventName(topLevelType), dispatch);
179
}
180
184
-function dispatchInteractiveEvent(topLevelType, nativeEvent) {
185
- interactiveUpdates(dispatchEvent, topLevelType, nativeEvent);
181
+function dispatchInteractiveEvent(nativeEvent) {
182
+ interactiveUpdates(dispatchEvent, nativeEvent);
183
}
184
188
-export function dispatchEvent(
189
- topLevelType: DOMTopLevelEventType,
190
- nativeEvent: AnyNativeEvent,
191
-) {
185
+export function dispatchEvent(nativeEvent: AnyNativeEvent) {
186
if (!_enabled) {
187
return;
188
}
@@ -207,11 +201,7 @@ export function dispatchEvent(
201
targetInst = null;
202
}
203
210
- const bookKeeping = getTopLevelCallbackBookKeeping(
211
- topLevelType,
212
- nativeEvent,
213
- targetInst,
214
- );
204
+ const bookKeeping = getTopLevelCallbackBookKeeping(nativeEvent, targetInst);
205
206
try {
207
// Event queue being processed in the same cycle allows
packages/react-dom/src/test-utils/ReactTestUtils.js
+4
-2
@@ -42,7 +42,9 @@ const [
42
runEventsInBatch,
43
] = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Events;
44
45
-function Event(suffix) {}
45
+function Event(type) {
46
+ this.type = type;
47
+}
48
49
let hasWarnedAboutDeprecatedMockComponent = false;
50
@@ -59,7 +61,7 @@ let hasWarnedAboutDeprecatedMockComponent = false;
61
*/
62
function simulateNativeEventOnNode(topLevelType, node, fakeNativeEvent) {
63
fakeNativeEvent.target = node;
62
- dispatchEvent(topLevelType, fakeNativeEvent);
64
+ dispatchEvent(fakeNativeEvent);
65
}
66
67
/**