Skip to content

Commit

Permalink
Event API: use capture for all event listeners using experimental r…
Browse files Browse the repository at this point in the history
…esponder system (#15526)
  • Loading branch information
trueadm authored Apr 30, 2019
1 parent 72ca3c6 commit bd88982
Show file tree
Hide file tree
Showing 12 changed files with 38 additions and 68 deletions.
3 changes: 1 addition & 2 deletions packages/events/EventSystemFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
12 changes: 1 addition & 11 deletions packages/react-dom/src/client/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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);
Expand Down
30 changes: 2 additions & 28 deletions packages/react-dom/src/events/DOMEventResponderSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import {
type EventSystemFlags,
IS_PASSIVE,
IS_CAPTURE,
PASSIVE_NOT_SUPPORTED,
} from 'events/EventSystemFlags';
import type {AnyNativeEvent} from 'events/PluginModuleType';
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
);
Expand Down Expand Up @@ -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}`;
}
9 changes: 6 additions & 3 deletions packages/react-dom/src/events/EventListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
}
21 changes: 11 additions & 10 deletions packages/react-dom/src/events/ReactDOMEventListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -168,7 +167,6 @@ export function trapCapturedEvent(
export function trapEventForResponderEventSystem(
element: Document | Element | Node,
topLevelType: DOMTopLevelEventType,
capture: boolean,
passive: boolean,
): void {
if (enableEventAPI) {
Expand All @@ -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);
}
}
}

Expand Down
11 changes: 4 additions & 7 deletions packages/react-dom/src/events/forks/EventListener-www.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/react-events/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-events/src/Focus.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
2 changes: 1 addition & 1 deletion packages/react-events/src/FocusScope.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions packages/react-events/src/__tests__/Press-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
]);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/shared/ReactTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down
6 changes: 6 additions & 0 deletions scripts/flow/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}

0 comments on commit bd88982

Please sign in to comment.