Skip to content

Commit

Permalink
[Flare] Revise responder event types (#16081)
Browse files Browse the repository at this point in the history
  • Loading branch information
trueadm authored Jul 8, 2019
1 parent 2a0f639 commit 67e3f3f
Show file tree
Hide file tree
Showing 25 changed files with 141 additions and 279 deletions.
6 changes: 3 additions & 3 deletions packages/react-art/src/ReactARTHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,19 +428,19 @@ export function unhideTextInstance(textInstance, text): void {
}

export function mountEventComponent(
eventComponentInstance: ReactEventComponentInstance<any, any, any>,
eventComponentInstance: ReactEventComponentInstance<any, any>,
) {
throw new Error('Not yet implemented.');
}

export function updateEventComponent(
eventComponentInstance: ReactEventComponentInstance<any, any, any>,
eventComponentInstance: ReactEventComponentInstance<any, any>,
) {
throw new Error('Not yet implemented.');
}

export function unmountEventComponent(
eventComponentInstance: ReactEventComponentInstance<any, any, any>,
eventComponentInstance: ReactEventComponentInstance<any, any>,
): void {
throw new Error('Not yet implemented.');
}
50 changes: 13 additions & 37 deletions packages/react-dom/src/client/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@ import {registrationNameModules} from 'events/EventPluginRegistry';
import warning from 'shared/warning';
import {canUseDOM} from 'shared/ExecutionEnvironment';
import warningWithoutStack from 'shared/warningWithoutStack';
import type {ReactDOMEventResponderEventType} from 'shared/ReactDOMTypes';
import endsWith from 'shared/endsWith';
import type {DOMTopLevelEventType} from 'events/TopLevelEventTypes';
import {
setListenToResponderEventTypes,
generateListeningKey,
} from '../events/DOMEventResponderSystem';
import {setListenToResponderEventTypes} from '../events/DOMEventResponderSystem';

import {
getValueForAttribute,
Expand Down Expand Up @@ -1284,7 +1281,7 @@ export function restoreControlledState(
}

export function listenToEventResponderEventTypes(
eventTypes: Array<ReactDOMEventResponderEventType>,
eventTypes: Array<string>,
element: Element | Document,
): void {
if (enableFlareAPI) {
Expand All @@ -1294,40 +1291,19 @@ export function listenToEventResponderEventTypes(

// Go through each target event type of the event responder
for (let i = 0, length = eventTypes.length; i < length; ++i) {
const targetEventType = eventTypes[i];
let topLevelType;
let passive = true;

// If no event config object is provided (i.e. - only a string),
// we default to enabling passive and not capture.
if (typeof targetEventType === 'string') {
topLevelType = targetEventType;
} else {
if (__DEV__) {
warning(
typeof targetEventType === 'object' && targetEventType !== null,
'Event Responder: invalid entry in event types array. ' +
'Entry must be string or an object. Instead, got %s.',
targetEventType,
);
}
const targetEventConfigObject = ((targetEventType: any): {
name: string,
passive?: boolean,
});
topLevelType = targetEventConfigObject.name;
if (targetEventConfigObject.passive !== undefined) {
passive = targetEventConfigObject.passive;
}
}
const listeningName = generateListeningKey(topLevelType, passive);
if (!listeningSet.has(listeningName)) {
const eventType = eventTypes[i];
const isPassive = !endsWith(eventType, '_active');
const eventKey = isPassive ? eventType + '_passive' : eventType;
const targetEventType = isPassive
? eventType
: eventType.substring(0, eventType.length - 7);
if (!listeningSet.has(eventKey)) {
trapEventForResponderEventSystem(
element,
((topLevelType: any): DOMTopLevelEventType),
passive,
((targetEventType: any): DOMTopLevelEventType),
isPassive,
);
listeningSet.add(listeningName);
listeningSet.add(eventKey);
}
}
}
Expand Down
135 changes: 29 additions & 106 deletions packages/react-dom/src/events/DOMEventResponderSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import type {EventPriority} from 'shared/ReactTypes';
import type {
ReactDOMEventResponder,
ReactDOMEventComponentInstance,
ReactDOMEventResponderEventType,
ReactDOMResponderContext,
ReactDOMResponderEvent,
} from 'shared/ReactDOMTypes';
Expand Down Expand Up @@ -95,10 +94,6 @@ const rootEventTypesToEventComponentInstances: Map<
DOMTopLevelEventType | string,
Set<ReactDOMEventComponentInstance>,
> = new Map();
const targetEventTypeCached: Map<
Array<ReactDOMEventResponderEventType>,
Set<string>,
> = new Map();
const ownershipChangeListeners: Set<ReactDOMEventComponentInstance> = new Set();
const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
const eventListeners:
Expand Down Expand Up @@ -248,9 +243,7 @@ const eventResponderContext: ReactDOMResponderContext = {
}
return false;
},
addRootEventTypes(
rootEventTypes: Array<ReactDOMEventResponderEventType>,
): void {
addRootEventTypes(rootEventTypes: Array<string>): void {
validateResponderContext();
const activeDocument = getActiveDocument();
listenToResponderEventTypesImpl(rootEventTypes, activeDocument);
Expand All @@ -260,37 +253,17 @@ const eventResponderContext: ReactDOMResponderContext = {
registerRootEventType(rootEventType, eventComponentInstance);
}
},
removeRootEventTypes(
rootEventTypes: Array<ReactDOMEventResponderEventType>,
): void {
removeRootEventTypes(rootEventTypes: Array<string>): void {
validateResponderContext();
for (let i = 0; i < rootEventTypes.length; i++) {
const rootEventType = rootEventTypes[i];
let name = rootEventType;
let passive = true;

if (typeof rootEventType !== 'string') {
const targetEventConfigObject = ((rootEventType: any): {
name: string,
passive?: boolean,
});
name = targetEventConfigObject.name;
if (targetEventConfigObject.passive !== undefined) {
passive = targetEventConfigObject.passive;
}
}

const listeningName = generateListeningKey(
((name: any): string),
passive,
);
let rootEventComponents = rootEventTypesToEventComponentInstances.get(
listeningName,
rootEventType,
);
let rootEventTypesSet = ((currentInstance: any): ReactDOMEventComponentInstance)
.rootEventTypes;
if (rootEventTypesSet !== null) {
rootEventTypesSet.delete(listeningName);
rootEventTypesSet.delete(rootEventType);
}
if (rootEventComponents !== undefined) {
rootEventComponents.delete(
Expand Down Expand Up @@ -595,41 +568,20 @@ function processEventQueue(): void {
}
}

function getDOMTargetEventTypesSet(
eventTypes: Array<ReactDOMEventResponderEventType>,
): Set<string> {
let cachedSet = targetEventTypeCached.get(eventTypes);

if (cachedSet === undefined) {
cachedSet = new Set();
for (let i = 0; i < eventTypes.length; i++) {
const eventType = eventTypes[i];
let name = eventType;
let passive = true;

if (typeof eventType !== 'string') {
const targetEventConfigObject = ((eventType: any): {
name: string,
passive?: boolean,
});
name = targetEventConfigObject.name;
if (targetEventConfigObject.passive !== undefined) {
passive = targetEventConfigObject.passive;
}
}
const listeningName = generateListeningKey(
((name: any): string),
passive,
);
cachedSet.add(listeningName);
function responderEventTypesContainType(
eventTypes: Array<string>,
type: string,
): boolean {
for (let i = 0, len = eventTypes.length; i < len; i++) {
if (eventTypes[i] === type) {
return true;
}
targetEventTypeCached.set(eventTypes, cachedSet);
}
return cachedSet;
return false;
}

function handleTargetEventResponderInstance(
listeningName: string,
eventType: string,
responderEvent: ReactDOMResponderEvent,
eventComponentInstance: ReactDOMEventComponentInstance,
hookComponentResponderValidation: null | Set<ReactDOMEventResponder>,
Expand All @@ -639,8 +591,7 @@ function handleTargetEventResponderInstance(
const targetEventTypes = responder.targetEventTypes;
// Validate the target event type exists on the responder
if (targetEventTypes !== undefined) {
const targetEventTypesSet = getDOMTargetEventTypesSet(targetEventTypes);
if (targetEventTypesSet.has(listeningName)) {
if (responderEventTypesContainType(targetEventTypes, eventType)) {
if (hookComponentResponderValidation !== null) {
hookComponentResponderValidation.add(responder);
}
Expand Down Expand Up @@ -700,25 +651,23 @@ function checkForLocalPropagationContinuation(
}

function traverseAndHandleEventResponderInstances(
topLevelType: DOMTopLevelEventType,
topLevelType: string,
targetFiber: null | Fiber,
nativeEvent: AnyNativeEvent,
nativeEventTarget: EventTarget,
eventSystemFlags: EventSystemFlags,
): void {
const isPassiveEvent = (eventSystemFlags & IS_PASSIVE) !== 0;
const isPassiveSupported = (eventSystemFlags & PASSIVE_NOT_SUPPORTED) === 0;
const listeningName = generateListeningKey(
((topLevelType: any): string),
isPassiveEvent || !isPassiveSupported,
);
const isPassive = isPassiveEvent || !isPassiveSupported;
const eventType = isPassive ? topLevelType : topLevelType + '_active';

// Trigger event responders in this order:
// - Bubble target phase
// - Root phase

const responderEvent = createDOMResponderEvent(
((topLevelType: any): string),
topLevelType,
nativeEvent,
((nativeEventTarget: any): Element | Document),
isPassiveEvent,
Expand All @@ -743,7 +692,7 @@ function traverseAndHandleEventResponderInstances(
// Switch to the current fiber tree
node = eventComponentInstance.currentFiber;
handleTargetEventResponderInstance(
listeningName,
eventType,
responderEvent,
eventComponentInstance,
hookComponentResponderValidation,
Expand All @@ -760,7 +709,7 @@ function traverseAndHandleEventResponderInstances(
)
) {
handleTargetEventResponderInstance(
listeningName,
eventType,
responderEvent,
eventComponentInstance,
null,
Expand All @@ -776,7 +725,7 @@ function traverseAndHandleEventResponderInstances(
responderEvent.currentTarget = null;
// Root phase
const rootEventInstances = rootEventTypesToEventComponentInstances.get(
listeningName,
eventType,
);
if (rootEventInstances !== undefined) {
const rootEventComponentInstances = Array.from(rootEventInstances);
Expand Down Expand Up @@ -906,7 +855,7 @@ function validateResponderContext(): void {
}

export function dispatchEventForResponderEventSystem(
topLevelType: DOMTopLevelEventType,
topLevelType: string,
targetFiber: null | Fiber,
nativeEvent: AnyNativeEvent,
nativeEventTarget: EventTarget,
Expand Down Expand Up @@ -950,7 +899,7 @@ export function dispatchEventForResponderEventSystem(

export function addRootEventTypesForComponentInstance(
eventComponentInstance: ReactDOMEventComponentInstance,
rootEventTypes: Array<ReactDOMEventResponderEventType>,
rootEventTypes: Array<string>,
): void {
for (let i = 0; i < rootEventTypes.length; i++) {
const rootEventType = rootEventTypes[i];
Expand All @@ -959,31 +908,16 @@ export function addRootEventTypesForComponentInstance(
}

function registerRootEventType(
rootEventType: ReactDOMEventResponderEventType,
rootEventType: string,
eventComponentInstance: ReactDOMEventComponentInstance,
): void {
let name = rootEventType;
let passive = true;

if (typeof rootEventType !== 'string') {
const targetEventConfigObject = ((rootEventType: any): {
name: string,
passive?: boolean,
});
name = targetEventConfigObject.name;
if (targetEventConfigObject.passive !== undefined) {
passive = targetEventConfigObject.passive;
}
}

const listeningName = generateListeningKey(((name: any): string), passive);
let rootEventComponentInstances = rootEventTypesToEventComponentInstances.get(
listeningName,
rootEventType,
);
if (rootEventComponentInstances === undefined) {
rootEventComponentInstances = new Set();
rootEventTypesToEventComponentInstances.set(
listeningName,
rootEventType,
rootEventComponentInstances,
);
}
Expand All @@ -992,23 +926,12 @@ function registerRootEventType(
rootEventTypesSet = eventComponentInstance.rootEventTypes = new Set();
}
invariant(
!rootEventTypesSet.has(listeningName),
!rootEventTypesSet.has(rootEventType),
'addRootEventTypes() found a duplicate root event ' +
'type of "%s". This might be because the event type exists in the event responder "rootEventTypes" ' +
'array or because of a previous addRootEventTypes() using this root event type.',
name,
rootEventType,
);
rootEventTypesSet.add(listeningName);
rootEventTypesSet.add(rootEventType);
rootEventComponentInstances.add(eventComponentInstance);
}

export function generateListeningKey(
topLevelType: string,
passive: 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';
return `${topLevelType}${passiveKey}`;
}
2 changes: 1 addition & 1 deletion packages/react-dom/src/events/ReactDOMEventListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ export function dispatchEvent(
} else {
// React Flare event system
dispatchEventForResponderEventSystem(
topLevelType,
(topLevelType: any),
targetInst,
nativeEvent,
nativeEventTarget,
Expand Down
Loading

0 comments on commit 67e3f3f

Please sign in to comment.