Skip to content

Commit 66f280c

Browse files
authored
Add internal logic for listening to event responders (#15168)
* Add the logic for listening to event responders
1 parent b1a56ab commit 66f280c

File tree

4 files changed

+108
-35
lines changed

4 files changed

+108
-35
lines changed

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

+72-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {registrationNameModules} from 'events/EventPluginRegistry';
1313
import warning from 'shared/warning';
1414
import {canUseDOM} from 'shared/ExecutionEnvironment';
1515
import warningWithoutStack from 'shared/warningWithoutStack';
16+
import type {ReactEventResponder} from 'shared/ReactTypes';
17+
import type {DOMTopLevelEventType} from 'events/TopLevelEventTypes';
1618

1719
import {
1820
getValueForAttribute,
@@ -57,7 +59,12 @@ import {
5759
TOP_SUBMIT,
5860
TOP_TOGGLE,
5961
} from '../events/DOMTopLevelEventTypes';
60-
import {listenTo, trapBubbledEvent} from '../events/ReactBrowserEventEmitter';
62+
import {
63+
listenTo,
64+
trapBubbledEvent,
65+
getListeningSetForElement,
66+
} from '../events/ReactBrowserEventEmitter';
67+
import {trapEventForResponderEventSystem} from '../events/ReactDOMEventListener.js';
6168
import {mediaEventTypes} from '../events/DOMTopLevelEventTypes';
6269
import {
6370
createDangerousStringForStyles,
@@ -78,6 +85,8 @@ import {validateProperties as validateARIAProperties} from '../shared/ReactDOMIn
7885
import {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook';
7986
import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
8087

88+
import {enableEventAPI} from 'shared/ReactFeatureFlags';
89+
8190
let didWarnInvalidHydration = false;
8291
let didWarnShadyDOM = false;
8392

@@ -1267,3 +1276,65 @@ export function restoreControlledState(
12671276
return;
12681277
}
12691278
}
1279+
1280+
export function listenToEventResponderEvents(
1281+
eventResponder: ReactEventResponder,
1282+
element: Element | Document,
1283+
): void {
1284+
if (enableEventAPI) {
1285+
const {targetEventTypes} = eventResponder;
1286+
// Get the listening Set for this element. We use this to track
1287+
// what events we're listening to.
1288+
const listeningSet = getListeningSetForElement(element);
1289+
1290+
// Go through each target event type of the event responder
1291+
for (let i = 0, length = targetEventTypes.length; i < length; ++i) {
1292+
const targetEventType = targetEventTypes[i];
1293+
let topLevelType;
1294+
let capture = false;
1295+
let passive = true;
1296+
1297+
// If no event config object is provided (i.e. - only a string),
1298+
// we default to enabling passive and not capture.
1299+
if (typeof targetEventType === 'string') {
1300+
topLevelType = targetEventType;
1301+
} else {
1302+
if (__DEV__) {
1303+
warning(
1304+
typeof targetEventType === 'object' && targetEventType !== null,
1305+
'Event Responder: invalid entry in targetEventTypes array. ' +
1306+
'Entry must be string or an object. Instead, got %s.',
1307+
targetEventType,
1308+
);
1309+
}
1310+
const targetEventConfigObject = ((targetEventType: any): {
1311+
name: string,
1312+
passive?: boolean,
1313+
capture?: boolean,
1314+
});
1315+
topLevelType = targetEventConfigObject.name;
1316+
if (targetEventConfigObject.passive !== undefined) {
1317+
passive = targetEventConfigObject.passive;
1318+
}
1319+
if (targetEventConfigObject.capture !== undefined) {
1320+
capture = targetEventConfigObject.capture;
1321+
}
1322+
}
1323+
// Create a unique name for this event, plus its properties. We'll
1324+
// use this to ensure we don't listen to the same event with the same
1325+
// properties again.
1326+
const passiveKey = passive ? '_passive' : '';
1327+
const captureKey = capture ? '_capture' : '';
1328+
const listeningName = `${topLevelType}${passiveKey}${captureKey}`;
1329+
if (!listeningSet.has(listeningName)) {
1330+
trapEventForResponderEventSystem(
1331+
element,
1332+
((topLevelType: any): DOMTopLevelEventType),
1333+
capture,
1334+
passive,
1335+
);
1336+
listeningSet.add(listeningName);
1337+
}
1338+
}
1339+
}
1340+
}

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
warnForDeletedHydratableText,
2525
warnForInsertedHydratedElement,
2626
warnForInsertedHydratedText,
27+
listenToEventResponderEvents,
2728
} from './ReactDOMComponent';
2829
import {getSelectionInformation, restoreSelection} from './ReactInputSelection';
2930
import setTextContent from './setTextContent';
@@ -860,15 +861,16 @@ export function handleEventComponent(
860861
eventResponder: ReactEventResponder,
861862
rootContainerInstance: Container,
862863
internalInstanceHandle: Object,
863-
) {
864-
// TODO: add handleEventComponent implementation
864+
): void {
865+
const rootElement = rootContainerInstance.ownerDocument;
866+
listenToEventResponderEvents(eventResponder, rootElement);
865867
}
866868

867869
export function handleEventTarget(
868870
type: Symbol | number,
869871
props: Props,
870872
internalInstanceHandle: Object,
871-
) {
873+
): void {
872874
// Touch target hit slop handling
873875
if (type === REACT_EVENT_TARGET_TOUCH_HIT) {
874876
// Validates that there is a single element

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ const elementListeningSets:
9090
| WeakMap
9191
| Map<
9292
Document | Element | Node,
93-
Set<DOMTopLevelEventType>,
93+
Set<DOMTopLevelEventType | string>,
9494
> = new PossiblyWeakMap();
9595

96-
function getListeningSetForElement(
96+
export function getListeningSetForElement(
9797
element: Document | Element | Node,
98-
): Set<DOMTopLevelEventType> {
98+
): Set<DOMTopLevelEventType | string> {
9999
let listeningSet = elementListeningSets.get(element);
100100
if (listeningSet === undefined) {
101101
listeningSet = new Set();

scripts/rollup/results.json

+28-28
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@
6060
"filename": "react-dom.development.js",
6161
"bundleType": "NODE_DEV",
6262
"packageName": "react-dom",
63-
"size": 798048,
64-
"gzip": 181482
63+
"size": 813661,
64+
"gzip": 184364
6565
},
6666
{
6767
"filename": "react-dom.production.min.js",
6868
"bundleType": "NODE_PROD",
6969
"packageName": "react-dom",
70-
"size": 107733,
71-
"gzip": 34431
70+
"size": 108035,
71+
"gzip": 34515
7272
},
7373
{
7474
"filename": "ReactDOM-dev.js",
@@ -102,15 +102,15 @@
102102
"filename": "react-dom-test-utils.development.js",
103103
"bundleType": "NODE_DEV",
104104
"packageName": "react-dom",
105-
"size": 47988,
106-
"gzip": 13245
105+
"size": 48334,
106+
"gzip": 13206
107107
},
108108
{
109109
"filename": "react-dom-test-utils.production.min.js",
110110
"bundleType": "NODE_PROD",
111111
"packageName": "react-dom",
112-
"size": 10288,
113-
"gzip": 3812
112+
"size": 9954,
113+
"gzip": 3660
114114
},
115115
{
116116
"filename": "ReactTestUtils-dev.js",
@@ -137,15 +137,15 @@
137137
"filename": "react-dom-unstable-native-dependencies.development.js",
138138
"bundleType": "NODE_DEV",
139139
"packageName": "react-dom",
140-
"size": 61725,
141-
"gzip": 16151
140+
"size": 61643,
141+
"gzip": 16033
142142
},
143143
{
144144
"filename": "react-dom-unstable-native-dependencies.production.min.js",
145145
"bundleType": "NODE_PROD",
146146
"packageName": "react-dom",
147-
"size": 11001,
148-
"gzip": 3783
147+
"size": 10669,
148+
"gzip": 3640
149149
},
150150
{
151151
"filename": "ReactDOMUnstableNativeDependencies-dev.js",
@@ -179,15 +179,15 @@
179179
"filename": "react-dom-server.browser.development.js",
180180
"bundleType": "NODE_DEV",
181181
"packageName": "react-dom",
182-
"size": 129302,
183-
"gzip": 34571
182+
"size": 132758,
183+
"gzip": 35195
184184
},
185185
{
186186
"filename": "react-dom-server.browser.production.min.js",
187187
"bundleType": "NODE_PROD",
188188
"packageName": "react-dom",
189-
"size": 19590,
190-
"gzip": 7447
189+
"size": 19756,
190+
"gzip": 7540
191191
},
192192
{
193193
"filename": "ReactDOMServer-dev.js",
@@ -207,15 +207,15 @@
207207
"filename": "react-dom-server.node.development.js",
208208
"bundleType": "NODE_DEV",
209209
"packageName": "react-dom",
210-
"size": 131409,
211-
"gzip": 35129
210+
"size": 134747,
211+
"gzip": 35752
212212
},
213213
{
214214
"filename": "react-dom-server.node.production.min.js",
215215
"bundleType": "NODE_PROD",
216216
"packageName": "react-dom",
217-
"size": 20483,
218-
"gzip": 7757
217+
"size": 20639,
218+
"gzip": 7850
219219
},
220220
{
221221
"filename": "react-art.development.js",
@@ -718,8 +718,8 @@
718718
"filename": "react-dom.profiling.min.js",
719719
"bundleType": "NODE_PROFILING",
720720
"packageName": "react-dom",
721-
"size": 110923,
722-
"gzip": 35060
721+
"size": 111211,
722+
"gzip": 35133
723723
},
724724
{
725725
"filename": "ReactNativeRenderer-profiling.js",
@@ -1054,22 +1054,22 @@
10541054
"filename": "react-dom-unstable-fire.development.js",
10551055
"bundleType": "NODE_DEV",
10561056
"packageName": "react-dom",
1057-
"size": 798401,
1058-
"gzip": 181622
1057+
"size": 814014,
1058+
"gzip": 184503
10591059
},
10601060
{
10611061
"filename": "react-dom-unstable-fire.production.min.js",
10621062
"bundleType": "NODE_PROD",
10631063
"packageName": "react-dom",
1064-
"size": 107747,
1065-
"gzip": 34441
1064+
"size": 108049,
1065+
"gzip": 34524
10661066
},
10671067
{
10681068
"filename": "react-dom-unstable-fire.profiling.min.js",
10691069
"bundleType": "NODE_PROFILING",
10701070
"packageName": "react-dom",
1071-
"size": 110937,
1072-
"gzip": 35069
1071+
"size": 111225,
1072+
"gzip": 35142
10731073
},
10741074
{
10751075
"filename": "ReactFire-dev.js",

0 commit comments

Comments
 (0)