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
}