@samitouri / QOS-React-2 / commits / bd88982fbf

Event API: use `capture` for all event listeners using experimental responder system (#15526)

Dominic Gannaway committed Apr 30, 2019 at 11:40 UTC bd88982fbff117ebc044a33702906c32940c653b
12 files changed +38 -68
packages/events/EventSystemFlags.js
+1 -2
@@ -13,5 +13,4 @@ export const PLUGIN_EVENT_SYSTEM = 1;
13 export const RESPONDER_EVENT_SYSTEM = 1 << 1;
14 export const IS_PASSIVE = 1 << 2;
15 export const IS_ACTIVE = 1 << 3;
16 -export const IS_CAPTURE = 1 << 4;
17 -export const PASSIVE_NOT_SUPPORTED = 1 << 5;
16 +export const PASSIVE_NOT_SUPPORTED = 1 << 4;
packages/react-dom/src/client/ReactDOMComponent.js
+1 -11
@@ -1294,7 +1294,6 @@ export function listenToEventResponderEventTypes(
1294 for (let i = 0, length = eventTypes.length; i < length; ++i) {
1295 const targetEventType = eventTypes[i];
1296 let topLevelType;
1297 - let capture = false;
1297 let passive = true;
1298
1299 // If no event config object is provided (i.e. - only a string),
@@ -1313,26 +1312,17 @@ export function listenToEventResponderEventTypes(
1312 const targetEventConfigObject = ((targetEventType: any): {
1313 name: string,
1314 passive?: boolean,
1316 - capture?: boolean,
1315 });
1316 topLevelType = targetEventConfigObject.name;
1317 if (targetEventConfigObject.passive !== undefined) {
1318 passive = targetEventConfigObject.passive;
1319 }
1322 - if (targetEventConfigObject.capture !== undefined) {
1323 - capture = targetEventConfigObject.capture;
1324 - }
1320 }
1326 - const listeningName = generateListeningKey(
1327 - topLevelType,
1328 - passive,
1329 - capture,
1330 - );
1321 + const listeningName = generateListeningKey(topLevelType, passive);
1322 if (!listeningSet.has(listeningName)) {
1323 trapEventForResponderEventSystem(
1324 element,
1325 ((topLevelType: any): DOMTopLevelEventType),
1335 - capture,
1326 passive,
1327 );
1328 listeningSet.add(listeningName);
packages/react-dom/src/events/DOMEventResponderSystem.js
+2 -28
@@ -9,7 +9,6 @@
9 import {
10 type EventSystemFlags,
11 IS_PASSIVE,
12 - IS_CAPTURE,
12 PASSIVE_NOT_SUPPORTED,
13 } from 'events/EventSystemFlags';
14 import type {AnyNativeEvent} from 'events/PluginModuleType';
@@ -247,28 +246,22 @@ const eventResponderContext: ReactResponderContext = {
246 for (let i = 0; i < rootEventTypes.length; i++) {
247 const rootEventType = rootEventTypes[i];
248 let name = rootEventType;
250 - let capture = false;
249 let passive = true;
250
251 if (typeof rootEventType !== 'string') {
252 const targetEventConfigObject = ((rootEventType: any): {
253 name: string,
254 passive?: boolean,
257 - capture?: boolean,
255 });
256 name = targetEventConfigObject.name;
257 if (targetEventConfigObject.passive !== undefined) {
258 passive = targetEventConfigObject.passive;
259 }
263 - if (targetEventConfigObject.capture !== undefined) {
264 - capture = targetEventConfigObject.capture;
265 - }
260 }
261
262 const listeningName = generateListeningKey(
263 ((name: any): string),
264 passive,
271 - capture,
265 );
266 let rootEventComponents = rootEventTypesToEventComponentInstances.get(
267 listeningName,
@@ -537,27 +530,21 @@ function getTargetEventTypesSet(
530 for (let i = 0; i < eventTypes.length; i++) {
531 const eventType = eventTypes[i];
532 let name = eventType;
540 - let capture = false;
533 let passive = true;
534
535 if (typeof eventType !== 'string') {
536 const targetEventConfigObject = ((eventType: any): {
537 name: string,
538 passive?: boolean,
547 - capture?: boolean,
539 });
540 name = targetEventConfigObject.name;
541 if (targetEventConfigObject.passive !== undefined) {
542 passive = targetEventConfigObject.passive;
543 }
553 - if (targetEventConfigObject.capture !== undefined) {
554 - capture = targetEventConfigObject.capture;
555 - }
544 }
545 const listeningName = generateListeningKey(
546 ((name: any): string),
547 passive,
560 - capture,
548 );
549 cachedSet.add(listeningName);
550 }
@@ -640,12 +627,10 @@ function traverseAndHandleEventResponderInstances(
627 eventSystemFlags: EventSystemFlags,
628 ): void {
629 const isPassiveEvent = (eventSystemFlags & IS_PASSIVE) !== 0;
643 - const isCaptureEvent = (eventSystemFlags & IS_CAPTURE) !== 0;
630 const isPassiveSupported = (eventSystemFlags & PASSIVE_NOT_SUPPORTED) === 0;
631 const listeningName = generateListeningKey(
632 ((topLevelType: any): string),
633 isPassiveEvent || !isPassiveSupported,
648 - isCaptureEvent,
634 );
635
636 // Trigger event responders in this order:
@@ -875,29 +860,20 @@ function registerRootEventType(
860 eventComponentInstance: ReactEventComponentInstance,
861 ): void {
862 let name = rootEventType;
878 - let capture = false;
863 let passive = true;
864
865 if (typeof rootEventType !== 'string') {
866 const targetEventConfigObject = ((rootEventType: any): {
867 name: string,
868 passive?: boolean,
885 - capture?: boolean,
869 });
870 name = targetEventConfigObject.name;
871 if (targetEventConfigObject.passive !== undefined) {
872 passive = targetEventConfigObject.passive;
873 }
891 - if (targetEventConfigObject.capture !== undefined) {
892 - capture = targetEventConfigObject.capture;
893 - }
874 }
875
896 - const listeningName = generateListeningKey(
897 - ((name: any): string),
898 - passive,
899 - capture,
900 - );
876 + const listeningName = generateListeningKey(((name: any): string), passive);
877 let rootEventComponentInstances = rootEventTypesToEventComponentInstances.get(
878 listeningName,
879 );
@@ -928,12 +904,10 @@ function registerRootEventType(
904 export function generateListeningKey(
905 topLevelType: string,
906 passive: boolean,
931 - capture: boolean,
907 ): string {
908 // Create a unique name for this event, plus its properties. We'll
909 // use this to ensure we don't listen to the same event with the same
910 // properties again.
911 const passiveKey = passive ? '_passive' : '_active';
937 - const captureKey = capture ? '_capture' : '';
938 - return `${topLevelType}${passiveKey}${captureKey}`;
912 + return `${topLevelType}${passiveKey}`;
913 }
packages/react-dom/src/events/EventListener.js
+6 -3
@@ -23,11 +23,14 @@ export function addEventCaptureListener(
23 element.addEventListener(eventType, listener, true);
24 }
25
26 -export function addEventListener(
26 +export function addEventCaptureListenerWithPassiveFlag(
27 element: Document | Element | Node,
28 eventType: string,
29 listener: Function,
30 - options: {passive: boolean},
30 + passive: boolean,
31 ): void {
32 - element.addEventListener(eventType, listener, (options: any));
32 + element.addEventListener(eventType, listener, {
33 + capture: true,
34 + passive,
35 + });
36 }
packages/react-dom/src/events/ReactDOMEventListener.js
+11 -10
@@ -22,14 +22,13 @@ import {
22 RESPONDER_EVENT_SYSTEM,
23 IS_PASSIVE,
24 IS_ACTIVE,
25 - IS_CAPTURE,
25 PASSIVE_NOT_SUPPORTED,
26 } from 'events/EventSystemFlags';
27
28 import {
29 addEventBubbleListener,
30 addEventCaptureListener,
32 - addEventListener,
31 + addEventCaptureListenerWithPassiveFlag,
32 } from './EventListener';
33 import getEventTarget from './getEventTarget';
34 import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
@@ -168,7 +167,6 @@ export function trapCapturedEvent(
167 export function trapEventForResponderEventSystem(
168 element: Document | Element | Node,
169 topLevelType: DOMTopLevelEventType,
171 - capture: boolean,
170 passive: boolean,
171 ): void {
172 if (enableEventAPI) {
@@ -190,15 +188,18 @@ export function trapEventForResponderEventSystem(
188 } else {
189 eventFlags |= IS_ACTIVE;
190 }
193 - if (capture) {
194 - eventFlags |= IS_CAPTURE;
195 - }
191 // Check if interactive and wrap in interactiveUpdates
192 const listener = dispatchEvent.bind(null, topLevelType, eventFlags);
198 - addEventListener(element, rawEventName, listener, {
199 - capture,
200 - passive,
201 - });
193 + if (passiveBrowserEventsSupported) {
194 + addEventCaptureListenerWithPassiveFlag(
195 + element,
196 + rawEventName,
197 + listener,
198 + passive,
199 + );
200 + } else {
201 + addEventCaptureListener(element, rawEventName, listener);
202 + }
203 }
204 }
205
packages/react-dom/src/events/forks/EventListener-www.js
+4 -7
@@ -12,8 +12,6 @@ const EventListenerWWW = require('EventListener');
12 import typeof * as EventListenerType from '../EventListener';
13 import typeof * as EventListenerShimType from './EventListener-www';
14
15 -const NORMAL_PRIORITY = 0;
16 -
15 export function addEventBubbleListener(
16 element: Element,
17 eventType: string,
@@ -30,18 +28,17 @@ export function addEventCaptureListener(
28 EventListenerWWW.capture(element, eventType, listener);
29 }
30
33 -export function addEventListener(
31 +export function addEventCaptureListenerWithPassiveFlag(
32 element: Element,
33 eventType: string,
34 listener: Function,
37 - options: {passive: boolean},
35 + passive: boolean,
36 ): void {
39 - EventListenerWWW.listen(
37 + EventListenerWWW.captureWithPassiveFlag(
38 element,
39 eventType,
40 listener,
43 - NORMAL_PRIORITY,
44 - options,
41 + passive,
42 );
43 }
44
packages/react-events/README.md
+1 -1
@@ -34,7 +34,7 @@ events, and implement a state machine.
34 // types
35 type ResponderEventType =
36 | string
37 - | {name: string, passive?: boolean, capture?: boolean};
37 + | {name: string, passive?: boolean};
38
39 type ResponderEvent = {|
40 nativeEvent: any,
packages/react-events/src/Focus.js
+2 -2
@@ -36,8 +36,8 @@ type FocusEvent = {|
36 |};
37
38 const targetEventTypes = [
39 - {name: 'focus', passive: true, capture: true},
40 - {name: 'blur', passive: true, capture: true},
39 + {name: 'focus', passive: true},
40 + {name: 'blur', passive: true},
41 ];
42
43 const rootEventTypes = [
packages/react-events/src/FocusScope.js
+1 -1
@@ -25,7 +25,7 @@ type FocusScopeState = {
25 };
26
27 const targetEventTypes = [{name: 'keydown', passive: false}];
28 -const rootEventTypes = [{name: 'focus', passive: true, capture: true}];
28 +const rootEventTypes = [{name: 'focus', passive: true}];
29
30 function focusElement(element: ?HTMLElement) {
31 if (element != null) {
packages/react-events/src/__tests__/Press-test.internal.js
+2 -2
@@ -1269,13 +1269,13 @@ describe('Event responder: Press', () => {
1269 createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
1270 );
1271 expect(events).toEqual([
1272 - 'pointerdown',
1272 'inner: onPressStart',
1273 'inner: onPressChange',
1275 - 'pointerup',
1274 + 'pointerdown',
1275 'inner: onPressEnd',
1276 'inner: onPressChange',
1277 'inner: onPress',
1278 + 'pointerup',
1279 ]);
1280 });
1281
packages/shared/ReactTypes.js
+1 -1
@@ -83,7 +83,7 @@ export type RefObject = {|
83
84 export type ReactEventResponderEventType =
85 | string
86 - | {name: string, passive?: boolean, capture?: boolean};
86 + | {name: string, passive?: boolean};
87
88 export type ReactEventResponder = {
89 targetEventTypes?: Array<ReactEventResponderEventType>,
scripts/flow/environment.js
+6
@@ -39,5 +39,11 @@ declare module 'EventListener' {
39 options?: {passive: boolean},
40 ) => mixed,
41 capture: (target: Element, type: string, callback: Function) => mixed,
42 + captureWithPassiveFlag: (
43 + target: Element,
44 + type: string,
45 + callback: Function,
46 + passive: boolean,
47 + ) => mixed,
48 };
49 }