Skip to content

Commit 808f31a

Browse files
authored
Reduce the handleTopLevel() event code indirection (#11915)
* Refactor event emitters to reduce indirection * Remove unused handleTopLevel() injection * Rename handleTopLevel() to runExtractedEventsInBatch() and remove import indirection
1 parent 1c7c38c commit 808f31a

File tree

9 files changed

+42
-86
lines changed

9 files changed

+42
-86
lines changed

packages/events/EventPluginHub.js

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,13 @@ export function getListener(inst: Fiber, registrationName: string) {
164164
* @return {*} An accumulation of synthetic events.
165165
* @internal
166166
*/
167-
export function extractEvents(
167+
function extractEvents(
168168
topLevelType: string,
169169
targetInst: Fiber,
170170
nativeEvent: AnyNativeEvent,
171171
nativeEventTarget: EventTarget,
172-
) {
173-
let events;
172+
): Array<ReactSyntheticEvent> | ReactSyntheticEvent | null {
173+
let events = null;
174174
for (let i = 0; i < plugins.length; i++) {
175175
// Not every plugin in the ordering may be loaded at runtime.
176176
const possiblePlugin: PluginModule<AnyNativeEvent> = plugins[i];
@@ -189,27 +189,14 @@ export function extractEvents(
189189
return events;
190190
}
191191

192-
/**
193-
* Enqueues a synthetic event that should be dispatched when
194-
* `processEventQueue` is invoked.
195-
*
196-
* @param {*} events An accumulation of synthetic events.
197-
* @internal
198-
*/
199-
export function enqueueEvents(
200-
events: Array<ReactSyntheticEvent> | ReactSyntheticEvent,
192+
export function runEventsInBatch(
193+
events: Array<ReactSyntheticEvent> | ReactSyntheticEvent | null,
194+
simulated: boolean,
201195
) {
202-
if (events) {
196+
if (events !== null) {
203197
eventQueue = accumulateInto(eventQueue, events);
204198
}
205-
}
206199

207-
/**
208-
* Dispatches all synthetic events on the event queue.
209-
*
210-
* @internal
211-
*/
212-
export function processEventQueue(simulated: boolean) {
213200
// Set `eventQueue` to null before processing it so that we can tell if more
214201
// events get enqueued while processing.
215202
const processingEventQueue = eventQueue;
@@ -238,3 +225,18 @@ export function processEventQueue(simulated: boolean) {
238225
// This would be a good time to rethrow if any of the event handlers threw.
239226
ReactErrorUtils.rethrowCaughtError();
240227
}
228+
229+
export function runExtractedEventsInBatch(
230+
topLevelType: string,
231+
targetInst: Fiber,
232+
nativeEvent: AnyNativeEvent,
233+
nativeEventTarget: EventTarget,
234+
) {
235+
const events = extractEvents(
236+
topLevelType,
237+
targetInst,
238+
nativeEvent,
239+
nativeEventTarget,
240+
);
241+
runEventsInBatch(events, false);
242+
}

packages/events/ReactEventEmitterMixin.js

Lines changed: 0 additions & 36 deletions
This file was deleted.

packages/events/__tests__/ResponderEventPlugin-test.internal.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,7 @@ const run = function(config, hierarchyConfig, nativeEventConfig) {
312312
// At this point the negotiation events have been dispatched as part of the
313313
// extraction process, but not the side effectful events. Below, we dispatch
314314
// side effectful events.
315-
EventPluginHub.enqueueEvents(extractedEvents);
316-
EventPluginHub.processEventQueue(true);
315+
EventPluginHub.runEventsInBatch(extractedEvents, true);
317316

318317
// Ensure that every event that declared an `order`, was actually dispatched.
319318
expect('number of events dispatched:' + runData.dispatchCount).toBe(

packages/react-dom/src/client/ReactDOMClientInjection.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,9 @@ import BeforeInputEventPlugin from '../events/BeforeInputEventPlugin';
1313
import ChangeEventPlugin from '../events/ChangeEventPlugin';
1414
import DOMEventPluginOrder from '../events/DOMEventPluginOrder';
1515
import EnterLeaveEventPlugin from '../events/EnterLeaveEventPlugin';
16-
import {handleTopLevel} from '../events/ReactBrowserEventEmitter';
17-
import {setHandleTopLevel} from '../events/ReactDOMEventListener';
1816
import SelectEventPlugin from '../events/SelectEventPlugin';
1917
import SimpleEventPlugin from '../events/SimpleEventPlugin';
2018

21-
setHandleTopLevel(handleTopLevel);
22-
2319
/**
2420
* Inject modules for resolving DOM hierarchy and plugin ordering.
2521
*/

packages/react-dom/src/events/ChangeEventPlugin.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import {enqueueEvents, processEventQueue} from 'events/EventPluginHub';
8+
import * as EventPluginHub from 'events/EventPluginHub';
99
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
1010
import {enqueueStateRestore} from 'events/ReactControlledComponent';
1111
import {batchedUpdates} from 'events/ReactGenericBatching';
@@ -89,8 +89,7 @@ function manualDispatchChangeEvent(nativeEvent) {
8989
}
9090

9191
function runEventInBatch(event) {
92-
enqueueEvents(event);
93-
processEventQueue(false);
92+
EventPluginHub.runEventsInBatch(event, false);
9493
}
9594

9695
function getInstIfValueChanged(targetInst) {

packages/react-dom/src/events/ReactBrowserEventEmitter.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*/
77

88
import {registrationNameDependencies} from 'events/EventPluginRegistry';
9-
109
import {
1110
setEnabled,
1211
isEnabled,
@@ -16,8 +15,6 @@ import {
1615
import isEventSupported from './isEventSupported';
1716
import BrowserEventConstants from './BrowserEventConstants';
1817

19-
export * from 'events/ReactEventEmitterMixin';
20-
2118
const {topLevelTypes} = BrowserEventConstants;
2219

2320
/**

packages/react-dom/src/events/ReactDOMEventListener.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
import {batchedUpdates} from 'events/ReactGenericBatching';
9+
import {runExtractedEventsInBatch} from 'events/EventPluginHub';
910
import {isFiberMounted} from 'react-reconciler/reflection';
1011
import {HostRoot} from 'shared/ReactTypeOfWork';
1112

@@ -62,7 +63,7 @@ function releaseTopLevelCallbackBookKeeping(instance) {
6263
}
6364
}
6465

65-
function handleTopLevelImpl(bookKeeping) {
66+
function handleTopLevel(bookKeeping) {
6667
let targetInst = bookKeeping.targetInst;
6768

6869
// Loop through the hierarchy, in case there's any nested components.
@@ -85,7 +86,7 @@ function handleTopLevelImpl(bookKeeping) {
8586

8687
for (let i = 0; i < bookKeeping.ancestors.length; i++) {
8788
targetInst = bookKeeping.ancestors[i];
88-
_handleTopLevel(
89+
runExtractedEventsInBatch(
8990
bookKeeping.topLevelType,
9091
targetInst,
9192
bookKeeping.nativeEvent,
@@ -96,11 +97,6 @@ function handleTopLevelImpl(bookKeeping) {
9697

9798
// TODO: can we stop exporting these?
9899
export let _enabled = true;
99-
export let _handleTopLevel: null;
100-
101-
export function setHandleTopLevel(handleTopLevel) {
102-
_handleTopLevel = handleTopLevel;
103-
}
104100

105101
export function setEnabled(enabled) {
106102
_enabled = !!enabled;
@@ -180,7 +176,7 @@ export function dispatchEvent(topLevelType, nativeEvent) {
180176
try {
181177
// Event queue being processed in the same cycle allows
182178
// `preventDefault`.
183-
batchedUpdates(handleTopLevelImpl, bookKeeping);
179+
batchedUpdates(handleTopLevel, bookKeeping);
184180
} finally {
185181
releaseTopLevelCallbackBookKeeping(bookKeeping);
186182
}

packages/react-dom/src/test-utils/ReactTestUtils.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,7 @@ function makeSimulator(eventType) {
388388
// Normally extractEvent enqueues a state restore, but we'll just always
389389
// do that since we we're by-passing it here.
390390
ReactControlledComponent.enqueueStateRestore(domNode);
391-
392-
EventPluginHub.enqueueEvents(event);
393-
EventPluginHub.processEventQueue(true);
391+
EventPluginHub.runEventsInBatch(event, true);
394392
});
395393
};
396394
}

packages/react-native-renderer/src/ReactNativeEventEmitter.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
* @flow
88
*/
99

10-
import {getListener} from 'events/EventPluginHub';
10+
import {getListener, runExtractedEventsInBatch} from 'events/EventPluginHub';
1111
import {registrationNameModules} from 'events/EventPluginRegistry';
1212
import {batchedUpdates} from 'events/ReactGenericBatching';
13-
import {handleTopLevel} from 'events/ReactEventEmitterMixin';
1413
import warning from 'fbjs/lib/warning';
1514

1615
import {getInstanceFromNode} from './ReactNativeComponentTree';
1716
import ReactNativeTagHandles from './ReactNativeTagHandles';
1817

19-
export * from 'events/ReactEventEmitterMixin';
18+
import type {AnyNativeEvent} from 'events/PluginModuleType';
19+
2020
export {getListener, registrationNameModules as registrationNames};
2121

2222
/**
@@ -25,7 +25,7 @@ export {getListener, registrationNameModules as registrationNames};
2525
*/
2626

2727
// Shared default empty native event - conserve memory.
28-
const EMPTY_NATIVE_EVENT = {};
28+
const EMPTY_NATIVE_EVENT = (({}: any): AnyNativeEvent);
2929

3030
/**
3131
* Selects a subsequence of `Touch`es, without destroying `touches`.
@@ -90,12 +90,17 @@ const removeTouchesAtIndices = function(
9090
export function _receiveRootNodeIDEvent(
9191
rootNodeID: number,
9292
topLevelType: string,
93-
nativeEventParam: ?Object,
93+
nativeEventParam: ?AnyNativeEvent,
9494
) {
9595
const nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT;
9696
const inst = getInstanceFromNode(rootNodeID);
9797
batchedUpdates(function() {
98-
handleTopLevel(topLevelType, inst, nativeEvent, nativeEvent.target);
98+
runExtractedEventsInBatch(
99+
topLevelType,
100+
inst,
101+
nativeEvent,
102+
nativeEvent.target,
103+
);
99104
});
100105
// React Native doesn't use ReactControlledComponent but if it did, here's
101106
// where it would do it.
@@ -111,7 +116,7 @@ export function _receiveRootNodeIDEvent(
111116
export function receiveEvent(
112117
rootNodeID: number,
113118
topLevelType: string,
114-
nativeEventParam: Object,
119+
nativeEventParam: AnyNativeEvent,
115120
) {
116121
_receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam);
117122
}

0 commit comments

Comments
 (0)