@samitouri / QOS-React / commits / 66f280c87b

Add internal logic for listening to event responders (#15168)

* Add the logic for listening to event responders

Dominic Gannaway committed Mar 21, 2019 at 12:32 UTC 66f280c87b05885ee55320a5e107a534a50f9375
4 files changed +108 -35
packages/react-dom/src/client/ReactDOMComponent.js
+72 -1
@@ -13,6 +13,8 @@ import {registrationNameModules} from 'events/EventPluginRegistry';
13 import warning from 'shared/warning';
14 import {canUseDOM} from 'shared/ExecutionEnvironment';
15 import warningWithoutStack from 'shared/warningWithoutStack';
16 +import type {ReactEventResponder} from 'shared/ReactTypes';
17 +import type {DOMTopLevelEventType} from 'events/TopLevelEventTypes';
18
19 import {
20 getValueForAttribute,
@@ -57,7 +59,12 @@ import {
59 TOP_SUBMIT,
60 TOP_TOGGLE,
61 } 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';
68 import {mediaEventTypes} from '../events/DOMTopLevelEventTypes';
69 import {
70 createDangerousStringForStyles,
@@ -78,6 +85,8 @@ import {validateProperties as validateARIAProperties} from '../shared/ReactDOMIn
85 import {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook';
86 import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
87
88 +import {enableEventAPI} from 'shared/ReactFeatureFlags';
89 +
90 let didWarnInvalidHydration = false;
91 let didWarnShadyDOM = false;
92
@@ -1267,3 +1276,65 @@ export function restoreControlledState(
1276 return;
1277 }
1278 }
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
@@ -24,6 +24,7 @@ import {
24 warnForDeletedHydratableText,
25 warnForInsertedHydratedElement,
26 warnForInsertedHydratedText,
27 + listenToEventResponderEvents,
28 } from './ReactDOMComponent';
29 import {getSelectionInformation, restoreSelection} from './ReactInputSelection';
30 import setTextContent from './setTextContent';
@@ -860,15 +861,16 @@ export function handleEventComponent(
861 eventResponder: ReactEventResponder,
862 rootContainerInstance: Container,
863 internalInstanceHandle: Object,
863 -) {
864 - // TODO: add handleEventComponent implementation
864 +): void {
865 + const rootElement = rootContainerInstance.ownerDocument;
866 + listenToEventResponderEvents(eventResponder, rootElement);
867 }
868
869 export function handleEventTarget(
870 type: Symbol | number,
871 props: Props,
872 internalInstanceHandle: Object,
871 -) {
873 +): void {
874 // Touch target hit slop handling
875 if (type === REACT_EVENT_TARGET_TOUCH_HIT) {
876 // Validates that there is a single element
packages/react-dom/src/events/ReactBrowserEventEmitter.js
+3 -3
@@ -90,12 +90,12 @@ const elementListeningSets:
90 | WeakMap
91 | Map<
92 Document | Element | Node,
93 - Set<DOMTopLevelEventType>,
93 + Set<DOMTopLevelEventType | string>,
94 > = new PossiblyWeakMap();
95
96 -function getListeningSetForElement(
96 +export function getListeningSetForElement(
97 element: Document | Element | Node,
98 -): Set<DOMTopLevelEventType> {
98 +): Set<DOMTopLevelEventType | string> {
99 let listeningSet = elementListeningSets.get(element);
100 if (listeningSet === undefined) {
101 listeningSet = new Set();
scripts/rollup/results.json
+28 -28
@@ -60,15 +60,15 @@
60 "filename": "react-dom.development.js",
61 "bundleType": "NODE_DEV",
62 "packageName": "react-dom",
63 - "size": 798048,
64 - "gzip": 181482
63 + "size": 813661,
64 + "gzip": 184364
65 },
66 {
67 "filename": "react-dom.production.min.js",
68 "bundleType": "NODE_PROD",
69 "packageName": "react-dom",
70 - "size": 107733,
71 - "gzip": 34431
70 + "size": 108035,
71 + "gzip": 34515
72 },
73 {
74 "filename": "ReactDOM-dev.js",
@@ -102,15 +102,15 @@
102 "filename": "react-dom-test-utils.development.js",
103 "bundleType": "NODE_DEV",
104 "packageName": "react-dom",
105 - "size": 47988,
106 - "gzip": 13245
105 + "size": 48334,
106 + "gzip": 13206
107 },
108 {
109 "filename": "react-dom-test-utils.production.min.js",
110 "bundleType": "NODE_PROD",
111 "packageName": "react-dom",
112 - "size": 10288,
113 - "gzip": 3812
112 + "size": 9954,
113 + "gzip": 3660
114 },
115 {
116 "filename": "ReactTestUtils-dev.js",
@@ -137,15 +137,15 @@
137 "filename": "react-dom-unstable-native-dependencies.development.js",
138 "bundleType": "NODE_DEV",
139 "packageName": "react-dom",
140 - "size": 61725,
141 - "gzip": 16151
140 + "size": 61643,
141 + "gzip": 16033
142 },
143 {
144 "filename": "react-dom-unstable-native-dependencies.production.min.js",
145 "bundleType": "NODE_PROD",
146 "packageName": "react-dom",
147 - "size": 11001,
148 - "gzip": 3783
147 + "size": 10669,
148 + "gzip": 3640
149 },
150 {
151 "filename": "ReactDOMUnstableNativeDependencies-dev.js",
@@ -179,15 +179,15 @@
179 "filename": "react-dom-server.browser.development.js",
180 "bundleType": "NODE_DEV",
181 "packageName": "react-dom",
182 - "size": 129302,
183 - "gzip": 34571
182 + "size": 132758,
183 + "gzip": 35195
184 },
185 {
186 "filename": "react-dom-server.browser.production.min.js",
187 "bundleType": "NODE_PROD",
188 "packageName": "react-dom",
189 - "size": 19590,
190 - "gzip": 7447
189 + "size": 19756,
190 + "gzip": 7540
191 },
192 {
193 "filename": "ReactDOMServer-dev.js",
@@ -207,15 +207,15 @@
207 "filename": "react-dom-server.node.development.js",
208 "bundleType": "NODE_DEV",
209 "packageName": "react-dom",
210 - "size": 131409,
211 - "gzip": 35129
210 + "size": 134747,
211 + "gzip": 35752
212 },
213 {
214 "filename": "react-dom-server.node.production.min.js",
215 "bundleType": "NODE_PROD",
216 "packageName": "react-dom",
217 - "size": 20483,
218 - "gzip": 7757
217 + "size": 20639,
218 + "gzip": 7850
219 },
220 {
221 "filename": "react-art.development.js",
@@ -718,8 +718,8 @@
718 "filename": "react-dom.profiling.min.js",
719 "bundleType": "NODE_PROFILING",
720 "packageName": "react-dom",
721 - "size": 110923,
722 - "gzip": 35060
721 + "size": 111211,
722 + "gzip": 35133
723 },
724 {
725 "filename": "ReactNativeRenderer-profiling.js",
@@ -1054,22 +1054,22 @@
1054 "filename": "react-dom-unstable-fire.development.js",
1055 "bundleType": "NODE_DEV",
1056 "packageName": "react-dom",
1057 - "size": 798401,
1058 - "gzip": 181622
1057 + "size": 814014,
1058 + "gzip": 184503
1059 },
1060 {
1061 "filename": "react-dom-unstable-fire.production.min.js",
1062 "bundleType": "NODE_PROD",
1063 "packageName": "react-dom",
1064 - "size": 107747,
1065 - "gzip": 34441
1064 + "size": 108049,
1065 + "gzip": 34524
1066 },
1067 {
1068 "filename": "react-dom-unstable-fire.profiling.min.js",
1069 "bundleType": "NODE_PROFILING",
1070 "packageName": "react-dom",
1071 - "size": 110937,
1072 - "gzip": 35069
1071 + "size": 111225,
1072 + "gzip": 35142
1073 },
1074 {
1075 "filename": "ReactFire-dev.js",