mirror of
https://github.com/facebook/react.git
synced 2026-02-23 20:23:02 +00:00
Event API: use capture for all event listeners using experimental responder system (#15526)
This commit is contained in:
@@ -13,5 +13,4 @@ export const PLUGIN_EVENT_SYSTEM = 1;
|
||||
export const RESPONDER_EVENT_SYSTEM = 1 << 1;
|
||||
export const IS_PASSIVE = 1 << 2;
|
||||
export const IS_ACTIVE = 1 << 3;
|
||||
export const IS_CAPTURE = 1 << 4;
|
||||
export const PASSIVE_NOT_SUPPORTED = 1 << 5;
|
||||
export const PASSIVE_NOT_SUPPORTED = 1 << 4;
|
||||
|
||||
@@ -1294,7 +1294,6 @@ export function listenToEventResponderEventTypes(
|
||||
for (let i = 0, length = eventTypes.length; i < length; ++i) {
|
||||
const targetEventType = eventTypes[i];
|
||||
let topLevelType;
|
||||
let capture = false;
|
||||
let passive = true;
|
||||
|
||||
// If no event config object is provided (i.e. - only a string),
|
||||
@@ -1313,26 +1312,17 @@ export function listenToEventResponderEventTypes(
|
||||
const targetEventConfigObject = ((targetEventType: any): {
|
||||
name: string,
|
||||
passive?: boolean,
|
||||
capture?: boolean,
|
||||
});
|
||||
topLevelType = targetEventConfigObject.name;
|
||||
if (targetEventConfigObject.passive !== undefined) {
|
||||
passive = targetEventConfigObject.passive;
|
||||
}
|
||||
if (targetEventConfigObject.capture !== undefined) {
|
||||
capture = targetEventConfigObject.capture;
|
||||
}
|
||||
}
|
||||
const listeningName = generateListeningKey(
|
||||
topLevelType,
|
||||
passive,
|
||||
capture,
|
||||
);
|
||||
const listeningName = generateListeningKey(topLevelType, passive);
|
||||
if (!listeningSet.has(listeningName)) {
|
||||
trapEventForResponderEventSystem(
|
||||
element,
|
||||
((topLevelType: any): DOMTopLevelEventType),
|
||||
capture,
|
||||
passive,
|
||||
);
|
||||
listeningSet.add(listeningName);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import {
|
||||
type EventSystemFlags,
|
||||
IS_PASSIVE,
|
||||
IS_CAPTURE,
|
||||
PASSIVE_NOT_SUPPORTED,
|
||||
} from 'events/EventSystemFlags';
|
||||
import type {AnyNativeEvent} from 'events/PluginModuleType';
|
||||
@@ -247,28 +246,22 @@ const eventResponderContext: ReactResponderContext = {
|
||||
for (let i = 0; i < rootEventTypes.length; i++) {
|
||||
const rootEventType = rootEventTypes[i];
|
||||
let name = rootEventType;
|
||||
let capture = false;
|
||||
let passive = true;
|
||||
|
||||
if (typeof rootEventType !== 'string') {
|
||||
const targetEventConfigObject = ((rootEventType: any): {
|
||||
name: string,
|
||||
passive?: boolean,
|
||||
capture?: boolean,
|
||||
});
|
||||
name = targetEventConfigObject.name;
|
||||
if (targetEventConfigObject.passive !== undefined) {
|
||||
passive = targetEventConfigObject.passive;
|
||||
}
|
||||
if (targetEventConfigObject.capture !== undefined) {
|
||||
capture = targetEventConfigObject.capture;
|
||||
}
|
||||
}
|
||||
|
||||
const listeningName = generateListeningKey(
|
||||
((name: any): string),
|
||||
passive,
|
||||
capture,
|
||||
);
|
||||
let rootEventComponents = rootEventTypesToEventComponentInstances.get(
|
||||
listeningName,
|
||||
@@ -537,27 +530,21 @@ function getTargetEventTypesSet(
|
||||
for (let i = 0; i < eventTypes.length; i++) {
|
||||
const eventType = eventTypes[i];
|
||||
let name = eventType;
|
||||
let capture = false;
|
||||
let passive = true;
|
||||
|
||||
if (typeof eventType !== 'string') {
|
||||
const targetEventConfigObject = ((eventType: any): {
|
||||
name: string,
|
||||
passive?: boolean,
|
||||
capture?: boolean,
|
||||
});
|
||||
name = targetEventConfigObject.name;
|
||||
if (targetEventConfigObject.passive !== undefined) {
|
||||
passive = targetEventConfigObject.passive;
|
||||
}
|
||||
if (targetEventConfigObject.capture !== undefined) {
|
||||
capture = targetEventConfigObject.capture;
|
||||
}
|
||||
}
|
||||
const listeningName = generateListeningKey(
|
||||
((name: any): string),
|
||||
passive,
|
||||
capture,
|
||||
);
|
||||
cachedSet.add(listeningName);
|
||||
}
|
||||
@@ -640,12 +627,10 @@ function traverseAndHandleEventResponderInstances(
|
||||
eventSystemFlags: EventSystemFlags,
|
||||
): void {
|
||||
const isPassiveEvent = (eventSystemFlags & IS_PASSIVE) !== 0;
|
||||
const isCaptureEvent = (eventSystemFlags & IS_CAPTURE) !== 0;
|
||||
const isPassiveSupported = (eventSystemFlags & PASSIVE_NOT_SUPPORTED) === 0;
|
||||
const listeningName = generateListeningKey(
|
||||
((topLevelType: any): string),
|
||||
isPassiveEvent || !isPassiveSupported,
|
||||
isCaptureEvent,
|
||||
);
|
||||
|
||||
// Trigger event responders in this order:
|
||||
@@ -875,29 +860,20 @@ function registerRootEventType(
|
||||
eventComponentInstance: ReactEventComponentInstance,
|
||||
): void {
|
||||
let name = rootEventType;
|
||||
let capture = false;
|
||||
let passive = true;
|
||||
|
||||
if (typeof rootEventType !== 'string') {
|
||||
const targetEventConfigObject = ((rootEventType: any): {
|
||||
name: string,
|
||||
passive?: boolean,
|
||||
capture?: boolean,
|
||||
});
|
||||
name = targetEventConfigObject.name;
|
||||
if (targetEventConfigObject.passive !== undefined) {
|
||||
passive = targetEventConfigObject.passive;
|
||||
}
|
||||
if (targetEventConfigObject.capture !== undefined) {
|
||||
capture = targetEventConfigObject.capture;
|
||||
}
|
||||
}
|
||||
|
||||
const listeningName = generateListeningKey(
|
||||
((name: any): string),
|
||||
passive,
|
||||
capture,
|
||||
);
|
||||
const listeningName = generateListeningKey(((name: any): string), passive);
|
||||
let rootEventComponentInstances = rootEventTypesToEventComponentInstances.get(
|
||||
listeningName,
|
||||
);
|
||||
@@ -928,12 +904,10 @@ function registerRootEventType(
|
||||
export function generateListeningKey(
|
||||
topLevelType: string,
|
||||
passive: boolean,
|
||||
capture: boolean,
|
||||
): string {
|
||||
// Create a unique name for this event, plus its properties. We'll
|
||||
// use this to ensure we don't listen to the same event with the same
|
||||
// properties again.
|
||||
const passiveKey = passive ? '_passive' : '_active';
|
||||
const captureKey = capture ? '_capture' : '';
|
||||
return `${topLevelType}${passiveKey}${captureKey}`;
|
||||
return `${topLevelType}${passiveKey}`;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,14 @@ export function addEventCaptureListener(
|
||||
element.addEventListener(eventType, listener, true);
|
||||
}
|
||||
|
||||
export function addEventListener(
|
||||
export function addEventCaptureListenerWithPassiveFlag(
|
||||
element: Document | Element | Node,
|
||||
eventType: string,
|
||||
listener: Function,
|
||||
options: {passive: boolean},
|
||||
passive: boolean,
|
||||
): void {
|
||||
element.addEventListener(eventType, listener, (options: any));
|
||||
element.addEventListener(eventType, listener, {
|
||||
capture: true,
|
||||
passive,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,14 +22,13 @@ import {
|
||||
RESPONDER_EVENT_SYSTEM,
|
||||
IS_PASSIVE,
|
||||
IS_ACTIVE,
|
||||
IS_CAPTURE,
|
||||
PASSIVE_NOT_SUPPORTED,
|
||||
} from 'events/EventSystemFlags';
|
||||
|
||||
import {
|
||||
addEventBubbleListener,
|
||||
addEventCaptureListener,
|
||||
addEventListener,
|
||||
addEventCaptureListenerWithPassiveFlag,
|
||||
} from './EventListener';
|
||||
import getEventTarget from './getEventTarget';
|
||||
import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
|
||||
@@ -168,7 +167,6 @@ export function trapCapturedEvent(
|
||||
export function trapEventForResponderEventSystem(
|
||||
element: Document | Element | Node,
|
||||
topLevelType: DOMTopLevelEventType,
|
||||
capture: boolean,
|
||||
passive: boolean,
|
||||
): void {
|
||||
if (enableEventAPI) {
|
||||
@@ -190,15 +188,18 @@ export function trapEventForResponderEventSystem(
|
||||
} else {
|
||||
eventFlags |= IS_ACTIVE;
|
||||
}
|
||||
if (capture) {
|
||||
eventFlags |= IS_CAPTURE;
|
||||
}
|
||||
// Check if interactive and wrap in interactiveUpdates
|
||||
const listener = dispatchEvent.bind(null, topLevelType, eventFlags);
|
||||
addEventListener(element, rawEventName, listener, {
|
||||
capture,
|
||||
passive,
|
||||
});
|
||||
if (passiveBrowserEventsSupported) {
|
||||
addEventCaptureListenerWithPassiveFlag(
|
||||
element,
|
||||
rawEventName,
|
||||
listener,
|
||||
passive,
|
||||
);
|
||||
} else {
|
||||
addEventCaptureListener(element, rawEventName, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@ const EventListenerWWW = require('EventListener');
|
||||
import typeof * as EventListenerType from '../EventListener';
|
||||
import typeof * as EventListenerShimType from './EventListener-www';
|
||||
|
||||
const NORMAL_PRIORITY = 0;
|
||||
|
||||
export function addEventBubbleListener(
|
||||
element: Element,
|
||||
eventType: string,
|
||||
@@ -30,18 +28,17 @@ export function addEventCaptureListener(
|
||||
EventListenerWWW.capture(element, eventType, listener);
|
||||
}
|
||||
|
||||
export function addEventListener(
|
||||
export function addEventCaptureListenerWithPassiveFlag(
|
||||
element: Element,
|
||||
eventType: string,
|
||||
listener: Function,
|
||||
options: {passive: boolean},
|
||||
passive: boolean,
|
||||
): void {
|
||||
EventListenerWWW.listen(
|
||||
EventListenerWWW.captureWithPassiveFlag(
|
||||
element,
|
||||
eventType,
|
||||
listener,
|
||||
NORMAL_PRIORITY,
|
||||
options,
|
||||
passive,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ events, and implement a state machine.
|
||||
// types
|
||||
type ResponderEventType =
|
||||
| string
|
||||
| {name: string, passive?: boolean, capture?: boolean};
|
||||
| {name: string, passive?: boolean};
|
||||
|
||||
type ResponderEvent = {|
|
||||
nativeEvent: any,
|
||||
|
||||
4
packages/react-events/src/Focus.js
vendored
4
packages/react-events/src/Focus.js
vendored
@@ -36,8 +36,8 @@ type FocusEvent = {|
|
||||
|};
|
||||
|
||||
const targetEventTypes = [
|
||||
{name: 'focus', passive: true, capture: true},
|
||||
{name: 'blur', passive: true, capture: true},
|
||||
{name: 'focus', passive: true},
|
||||
{name: 'blur', passive: true},
|
||||
];
|
||||
|
||||
const rootEventTypes = [
|
||||
|
||||
2
packages/react-events/src/FocusScope.js
vendored
2
packages/react-events/src/FocusScope.js
vendored
@@ -25,7 +25,7 @@ type FocusScopeState = {
|
||||
};
|
||||
|
||||
const targetEventTypes = [{name: 'keydown', passive: false}];
|
||||
const rootEventTypes = [{name: 'focus', passive: true, capture: true}];
|
||||
const rootEventTypes = [{name: 'focus', passive: true}];
|
||||
|
||||
function focusElement(element: ?HTMLElement) {
|
||||
if (element != null) {
|
||||
|
||||
@@ -1269,13 +1269,13 @@ describe('Event responder: Press', () => {
|
||||
createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
|
||||
);
|
||||
expect(events).toEqual([
|
||||
'pointerdown',
|
||||
'inner: onPressStart',
|
||||
'inner: onPressChange',
|
||||
'pointerup',
|
||||
'pointerdown',
|
||||
'inner: onPressEnd',
|
||||
'inner: onPressChange',
|
||||
'inner: onPress',
|
||||
'pointerup',
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ export type RefObject = {|
|
||||
|
||||
export type ReactEventResponderEventType =
|
||||
| string
|
||||
| {name: string, passive?: boolean, capture?: boolean};
|
||||
| {name: string, passive?: boolean};
|
||||
|
||||
export type ReactEventResponder = {
|
||||
targetEventTypes?: Array<ReactEventResponderEventType>,
|
||||
|
||||
@@ -39,5 +39,11 @@ declare module 'EventListener' {
|
||||
options?: {passive: boolean},
|
||||
) => mixed,
|
||||
capture: (target: Element, type: string, callback: Function) => mixed,
|
||||
captureWithPassiveFlag: (
|
||||
target: Element,
|
||||
type: string,
|
||||
callback: Function,
|
||||
passive: boolean,
|
||||
) => mixed,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user