Skip to content

Commit ad834b1

Browse files
committed
Refactor ElementListenerMap
Cleanup Cleanup Address comments
1 parent 4b02b66 commit ad834b1

8 files changed

+89
-92
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ import {
5959
TOP_SUBMIT,
6060
TOP_TOGGLE,
6161
} from '../events/DOMTopLevelEventTypes';
62-
import {getListenerMapForElement} from '../events/DOMEventListenerMap';
6362
import {mediaEventTypes} from '../events/DOMTopLevelEventTypes';
6463
import {
6564
createDangerousStringForStyles,
@@ -96,6 +95,7 @@ import {
9695
legacyTrapBubbledEvent,
9796
} from '../events/DOMLegacyEventPluginSystem';
9897
import {listenToEvent} from '../events/DOMModernPluginEventSystem';
98+
import {getEventListenerMap} from './ReactDOMComponentTree';
9999

100100
let didWarnInvalidHydration = false;
101101
let didWarnScriptTags = false;
@@ -1346,7 +1346,7 @@ export function listenToEventResponderEventTypes(
13461346
if (enableDeprecatedFlareAPI) {
13471347
// Get the listening Map for this element. We use this to track
13481348
// what events we're listening to.
1349-
const listenerMap = getListenerMapForElement(document);
1349+
const listenerMap = getEventListenerMap(document);
13501350

13511351
// Go through each target event type of the event responder
13521352
for (let i = 0, length = eventTypes.length; i < length; ++i) {

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

+23-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
SuspenseInstance,
1616
Props,
1717
} from './ReactDOMHostConfig';
18+
import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
1819

1920
import {
2021
HostComponent,
@@ -30,8 +31,19 @@ const randomKey = Math.random()
3031
.toString(36)
3132
.slice(2);
3233
const internalInstanceKey = '__reactFiber$' + randomKey;
33-
const internalEventHandlersKey = '__reactEvents$' + randomKey;
34+
const internalPropsKey = '__reactProps$' + randomKey;
3435
const internalContainerInstanceKey = '__reactContainer$' + randomKey;
36+
const internalEventHandlersKey = '__reactEvents$' + randomKey;
37+
38+
export type ElementListenerMap = Map<
39+
DOMTopLevelEventType | string,
40+
ElementListenerMapEntry,
41+
>;
42+
43+
export type ElementListenerMapEntry = {
44+
passive: void | boolean,
45+
listener: any => void,
46+
};
3547

3648
export function precacheFiberNode(
3749
hostInst: Fiber,
@@ -176,12 +188,20 @@ export function getNodeFromInstance(inst: Fiber): Instance | TextInstance {
176188
export function getFiberCurrentPropsFromNode(
177189
node: Instance | TextInstance | SuspenseInstance,
178190
): Props {
179-
return (node: any)[internalEventHandlersKey] || null;
191+
return (node: any)[internalPropsKey] || null;
180192
}
181193

182194
export function updateFiberProps(
183195
node: Instance | TextInstance | SuspenseInstance,
184196
props: Props,
185197
): void {
186-
(node: any)[internalEventHandlersKey] = props;
198+
(node: any)[internalPropsKey] = props;
199+
}
200+
201+
export function getEventListenerMap(node: EventTarget): ElementListenerMap {
202+
let elementListenerMap = (node: any)[internalEventHandlersKey];
203+
if (elementListenerMap === undefined) {
204+
elementListenerMap = (node: any)[internalEventHandlersKey] = new Map();
205+
}
206+
return elementListenerMap;
187207
}

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

-70
This file was deleted.

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

+6-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import type {AnyNativeEvent} from 'legacy-events/PluginModuleType';
1111
import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
12-
import type {ElementListenerMap} from '../events/DOMEventListenerMap';
12+
import type {ElementListenerMap} from '../client/ReactDOMComponentTree';
1313
import type {EventSystemFlags} from './EventSystemFlags';
1414
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
1515
import type {PluginModule} from 'legacy-events/PluginModuleType';
@@ -29,8 +29,10 @@ import accumulateInto from 'legacy-events/accumulateInto';
2929
import {registrationNameDependencies} from 'legacy-events/EventPluginRegistry';
3030

3131
import getEventTarget from './getEventTarget';
32-
import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
33-
import {getListenerMapForElement} from './DOMEventListenerMap';
32+
import {
33+
getClosestInstanceFromNode,
34+
getEventListenerMap,
35+
} from '../client/ReactDOMComponentTree';
3436
import isEventSupported from './isEventSupported';
3537
import {
3638
TOP_BLUR,
@@ -319,7 +321,7 @@ export function legacyListenToEvent(
319321
registrationName: string,
320322
mountAt: Document | Element,
321323
): void {
322-
const listenerMap = getListenerMapForElement(mountAt);
324+
const listenerMap = getEventListenerMap(mountAt);
323325
const dependencies = registrationNameDependencies[registrationName];
324326

325327
for (let i = 0; i < dependencies.length; i++) {

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

+7-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
1212
import type {
1313
ElementListenerMap,
1414
ElementListenerMapEntry,
15-
} from '../events/DOMEventListenerMap';
15+
} from '../client/ReactDOMComponentTree';
1616
import type {EventSystemFlags} from './EventSystemFlags';
1717
import type {EventPriority, ReactScopeMethods} from 'shared/ReactTypes';
1818
import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
@@ -36,7 +36,6 @@ import {
3636
} from 'react-reconciler/src/ReactWorkTags';
3737

3838
import getEventTarget from './getEventTarget';
39-
import {getListenerMapForElement} from './DOMEventListenerMap';
4039
import {
4140
TOP_FOCUS,
4241
TOP_LOAD,
@@ -74,7 +73,10 @@ import {
7473
TOP_SELECTION_CHANGE,
7574
getRawEventName,
7675
} from './DOMTopLevelEventTypes';
77-
import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
76+
import {
77+
getClosestInstanceFromNode,
78+
getEventListenerMap,
79+
} from '../client/ReactDOMComponentTree';
7880
import {COMMENT_NODE} from '../shared/HTMLNodeType';
7981
import {batchedEventUpdates} from './ReactDOMUpdateBatching';
8082
import getListener from './getListener';
@@ -237,7 +239,7 @@ export function listenToTopLevelEvent(
237239
// triggered on the document directly.
238240
if (topLevelType === TOP_SELECTION_CHANGE) {
239241
targetContainer = (targetContainer: any).ownerDocument || targetContainer;
240-
listenerMap = getListenerMapForElement(targetContainer);
242+
listenerMap = getEventListenerMap(targetContainer);
241243
}
242244
const listenerEntry: ElementListenerMapEntry | void = listenerMap.get(
243245
topLevelType,
@@ -262,7 +264,7 @@ export function listenToEvent(
262264
registrationName: string,
263265
rootContainerElement: Element,
264266
): void {
265-
const listenerMap = getListenerMapForElement(rootContainerElement);
267+
const listenerMap = getEventListenerMap(rootContainerElement);
266268
const dependencies = registrationNameDependencies[registrationName];
267269

268270
for (let i = 0; i < dependencies.length; i++) {

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import type {AnyNativeEvent} from 'legacy-events/PluginModuleType';
1111
import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
1212
import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
13-
import type {ElementListenerMap} from '../events/DOMEventListenerMap';
13+
import type {ElementListenerMap} from '../client/ReactDOMComponentTree';
1414
import type {EventSystemFlags} from './EventSystemFlags';
1515
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
1616

@@ -31,10 +31,10 @@ import {
3131
getSuspenseInstanceFromFiber,
3232
} from 'react-reconciler/src/ReactFiberTreeReflection';
3333
import {attemptToDispatchEvent} from './ReactDOMEventListener';
34-
import {getListenerMapForElement} from './DOMEventListenerMap';
3534
import {
3635
getInstanceFromNode,
3736
getClosestInstanceFromNode,
37+
getEventListenerMap,
3838
} from '../client/ReactDOMComponentTree';
3939
import {unsafeCastDOMTopLevelTypeToString} from 'legacy-events/TopLevelEventTypes';
4040
import {HostRoot, SuspenseComponent} from 'react-reconciler/src/ReactWorkTags';
@@ -256,10 +256,10 @@ export function eagerlyTrapReplayableEvents(
256256
container: Container,
257257
document: Document,
258258
) {
259-
const listenerMapForDoc = getListenerMapForElement(document);
259+
const listenerMapForDoc = getEventListenerMap(document);
260260
let listenerMapForContainer;
261261
if (enableModernEventSystem) {
262-
listenerMapForContainer = getListenerMapForElement(container);
262+
listenerMapForContainer = getEventListenerMap(container);
263263
}
264264
// Discrete
265265
discreteReplayableEvents.forEach(topLevelType => {

packages/react-dom/src/events/plugins/LegacySelectEventPlugin.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@ import {
2222
TOP_SELECTION_CHANGE,
2323
} from '../DOMTopLevelEventTypes';
2424
import getActiveElement from '../../client/getActiveElement';
25-
import {getNodeFromInstance} from '../../client/ReactDOMComponentTree';
25+
import {
26+
getNodeFromInstance,
27+
getEventListenerMap,
28+
} from '../../client/ReactDOMComponentTree';
2629
import {hasSelectionCapabilities} from '../../client/ReactInputSelection';
2730
import {DOCUMENT_NODE} from '../../shared/HTMLNodeType';
28-
import {isListeningToAllDependencies} from '../DOMEventListenerMap';
2931
import {accumulateTwoPhaseDispatches} from '../DOMLegacyEventPluginSystem';
3032

33+
import {registrationNameDependencies} from 'legacy-events/EventPluginRegistry';
34+
3135
const skipSelectionChangeEvent =
3236
canUseDOM && 'documentMode' in document && document.documentMode <= 11;
3337

@@ -143,6 +147,21 @@ function constructSelectEvent(nativeEvent, nativeEventTarget) {
143147
return null;
144148
}
145149

150+
function isListeningToAllDependencies(
151+
registrationName: string,
152+
mountAt: Document | Element,
153+
): boolean {
154+
const dependencies = registrationNameDependencies[registrationName];
155+
const listenerMap = getEventListenerMap(mountAt);
156+
for (let i = 0; i < dependencies.length; i++) {
157+
const event = dependencies[i];
158+
if (!listenerMap.has(event)) {
159+
return false;
160+
}
161+
}
162+
return true;
163+
}
164+
146165
/**
147166
* This plugin creates an `onSelect` event that normalizes select events
148167
* across form elements.

packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js

+26-2
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import {
2222
TOP_SELECTION_CHANGE,
2323
} from '../DOMTopLevelEventTypes';
2424
import getActiveElement from '../../client/getActiveElement';
25-
import {getNodeFromInstance} from '../../client/ReactDOMComponentTree';
25+
import {
26+
getNodeFromInstance,
27+
getEventListenerMap,
28+
} from '../../client/ReactDOMComponentTree';
2629
import {hasSelectionCapabilities} from '../../client/ReactInputSelection';
2730
import {DOCUMENT_NODE} from '../../shared/HTMLNodeType';
28-
import {isListeningToEvent, isListeningToEvents} from '../DOMEventListenerMap';
2931
import {accumulateTwoPhaseListeners} from '../DOMModernPluginEventSystem';
3032

3133
const skipSelectionChangeEvent =
@@ -144,6 +146,28 @@ function constructSelectEvent(nativeEvent, nativeEventTarget) {
144146
return null;
145147
}
146148

149+
function isListeningToEvents(
150+
events: Array<string>,
151+
mountAt: Document | Element,
152+
): boolean {
153+
const listenerMap = getEventListenerMap(mountAt);
154+
for (let i = 0; i < events.length; i++) {
155+
const event = events[i];
156+
if (!listenerMap.has(event)) {
157+
return false;
158+
}
159+
}
160+
return true;
161+
}
162+
163+
function isListeningToEvent(
164+
registrationName: string,
165+
mountAt: Document | Element,
166+
): boolean {
167+
const listenerMap = getEventListenerMap(mountAt);
168+
return listenerMap.has(registrationName);
169+
}
170+
147171
/**
148172
* This plugin creates an `onSelect` event that normalizes select events
149173
* across form elements.

0 commit comments

Comments
 (0)