[Flare] Revise responder event types (#16081)

This commit is contained in:
Dominic Gannaway 2019-07-08 14:35:59 +01:00 committed by GitHub
parent 2a0f6390ed
commit 67e3f3fb6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 141 additions and 279 deletions

View File

@ -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.');
}

View File

@ -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,
@ -1284,7 +1281,7 @@ export function restoreControlledState(
}
export function listenToEventResponderEventTypes(
eventTypes: Array<ReactDOMEventResponderEventType>,
eventTypes: Array<string>,
element: Element | Document,
): void {
if (enableFlareAPI) {
@ -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);
}
}
}

View File

@ -21,7 +21,6 @@ import type {EventPriority} from 'shared/ReactTypes';
import type {
ReactDOMEventResponder,
ReactDOMEventComponentInstance,
ReactDOMEventResponderEventType,
ReactDOMResponderContext,
ReactDOMResponderEvent,
} from 'shared/ReactDOMTypes';
@ -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:
@ -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);
@ -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(
@ -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>,
@ -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);
}
@ -700,7 +651,7 @@ function checkForLocalPropagationContinuation(
}
function traverseAndHandleEventResponderInstances(
topLevelType: DOMTopLevelEventType,
topLevelType: string,
targetFiber: null | Fiber,
nativeEvent: AnyNativeEvent,
nativeEventTarget: EventTarget,
@ -708,17 +659,15 @@ function traverseAndHandleEventResponderInstances(
): 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,
@ -743,7 +692,7 @@ function traverseAndHandleEventResponderInstances(
// Switch to the current fiber tree
node = eventComponentInstance.currentFiber;
handleTargetEventResponderInstance(
listeningName,
eventType,
responderEvent,
eventComponentInstance,
hookComponentResponderValidation,
@ -760,7 +709,7 @@ function traverseAndHandleEventResponderInstances(
)
) {
handleTargetEventResponderInstance(
listeningName,
eventType,
responderEvent,
eventComponentInstance,
null,
@ -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);
@ -906,7 +855,7 @@ function validateResponderContext(): void {
}
export function dispatchEventForResponderEventSystem(
topLevelType: DOMTopLevelEventType,
topLevelType: string,
targetFiber: null | Fiber,
nativeEvent: AnyNativeEvent,
nativeEventTarget: EventTarget,
@ -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];
@ -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,
);
}
@ -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}`;
}

View File

@ -334,7 +334,7 @@ export function dispatchEvent(
} else {
// React Flare event system
dispatchEventForResponderEventSystem(
topLevelType,
(topLevelType: any),
targetInst,
nativeEvent,
nativeEventTarget,

View File

@ -627,7 +627,7 @@ describe('DOMEventResponderSystem', () => {
const buttonRef = React.createRef();
const ClickEventComponent1 = createReactEventComponent({
targetEventTypes: [{name: 'click', passive: false, capture: false}],
targetEventTypes: ['click_active'],
onEvent: event => {
clickEventComponent1Fired++;
eventLog.push({
@ -639,7 +639,7 @@ describe('DOMEventResponderSystem', () => {
});
const ClickEventComponent2 = createReactEventComponent({
targetEventTypes: [{name: 'click', passive: true, capture: false}],
targetEventTypes: ['click'],
onEvent: event => {
clickEventComponent2Fired++;
eventLog.push({
@ -686,7 +686,7 @@ describe('DOMEventResponderSystem', () => {
let eventLog = [];
const ClickEventComponent1 = createReactEventComponent({
rootEventTypes: [{name: 'click', passive: false, capture: false}],
rootEventTypes: ['click_active'],
onRootEvent: event => {
clickEventComponent1Fired++;
eventLog.push({
@ -698,7 +698,7 @@ describe('DOMEventResponderSystem', () => {
});
const ClickEventComponent2 = createReactEventComponent({
rootEventTypes: [{name: 'click', passive: true, capture: false}],
rootEventTypes: ['click'],
onRootEvent: event => {
clickEventComponent2Fired++;
eventLog.push({

View File

@ -18,11 +18,7 @@ import React from 'react';
import {DiscreteEvent, UserBlockingEvent} from 'shared/ReactTypes';
const targetEventTypes = ['pointerdown'];
const rootEventTypes = [
'pointerup',
'pointercancel',
{name: 'pointermove', passive: false},
];
const rootEventTypes = ['pointerup', 'pointercancel', 'pointermove_active'];
type DragState = {
dragTarget: null | Element | Document,
@ -38,10 +34,13 @@ type DragState = {
// too
if (typeof window !== 'undefined' && window.PointerEvent === undefined) {
targetEventTypes.push('touchstart', 'mousedown');
rootEventTypes.push('mouseup', 'mousemove', 'touchend', 'touchcancel', {
name: 'touchmove',
passive: false,
});
rootEventTypes.push(
'mouseup',
'mousemove',
'touchend',
'touchcancel',
'touchmove_active',
);
}
type EventData = {

View File

@ -46,10 +46,7 @@ const isMac =
? /^Mac/.test(window.navigator.platform)
: false;
const targetEventTypes = [
{name: 'focus', passive: true},
{name: 'blur', passive: true},
];
const targetEventTypes = ['focus', 'blur'];
const rootEventTypes = [
'keydown',

View File

@ -25,8 +25,8 @@ type FocusScopeState = {
currentFocusedNode: null | HTMLElement,
};
const targetEventTypes = [{name: 'keydown', passive: false}];
const rootEventTypes = [{name: 'focus', passive: true}];
const targetEventTypes = ['keydown_active'];
const rootEventTypes = ['focus'];
function focusElement(element: ?HTMLElement) {
if (element != null) {

View File

@ -123,12 +123,12 @@ const DEFAULT_PRESS_RETENTION_OFFSET = {
};
const targetEventTypes = [
{name: 'keydown', passive: false},
{name: 'contextmenu', passive: false},
'keydown_active',
'contextmenu_active',
// We need to preventDefault on pointerdown for mouse/pen events
// that are in hit target area but not the element area.
{name: 'pointerdown', passive: false},
{name: 'click', passive: false},
'pointerdown_active',
'click_active',
];
const rootEventTypes = [
'click',
@ -139,7 +139,7 @@ const rootEventTypes = [
'pointercancel',
// We listen to this here so stopPropagation can
// block other mouseup events used internally
{name: 'mouseup', passive: false},
'mouseup_active',
'touchend',
];

View File

@ -18,20 +18,19 @@ import React from 'react';
import {UserBlockingEvent, DiscreteEvent} from 'shared/ReactTypes';
const targetEventTypes = ['pointerdown'];
const rootEventTypes = [
'pointerup',
'pointercancel',
{name: 'pointermove', passive: false},
];
const rootEventTypes = ['pointerup', 'pointercancel', 'pointermove_active'];
// In the case we don't have PointerEvents (Safari), we listen to touch events
// too
if (typeof window !== 'undefined' && window.PointerEvent === undefined) {
targetEventTypes.push('touchstart', 'mousedown');
rootEventTypes.push('mouseup', 'mousemove', 'touchend', 'touchcancel', {
name: 'touchmove',
passive: false,
});
rootEventTypes.push(
'mouseup',
'mousemove',
'touchend',
'touchcancel',
'touchmove_active',
);
}
type EventData = {

View File

@ -10,7 +10,6 @@
import type {
ReactNativeResponderEvent,
ReactNativeResponderContext,
ReactNativeEventResponderEventType,
ReactNativeEventTarget,
PointerType,
ReactFaricEventTouch,
@ -24,7 +23,6 @@ import {
} from 'react-native-renderer/src/ReactNativeTypes';
type ReactNativeEventResponder = ReactEventResponder<
ReactNativeEventResponderEventType,
ReactNativeResponderEvent,
ReactNativeResponderContext,
>;

View File

@ -23,7 +23,6 @@ import type {
ReactEventComponentInstance,
} from 'shared/ReactTypes';
import type {
ReactNativeEventResponderEventType,
ReactNativeResponderContext,
ReactNativeResponderEvent,
EventPriority,
@ -74,13 +73,11 @@ type EventQueue = {
};
type ReactNativeEventResponder = ReactEventResponder<
ReactNativeEventResponderEventType,
ReactNativeResponderEvent,
ReactNativeResponderContext,
>;
type ReactNativeEventComponentInstance = ReactEventComponentInstance<
ReactNativeEventResponderEventType,
ReactNativeResponderEvent,
ReactNativeResponderContext,
>;
@ -89,13 +86,9 @@ const {measureInWindow} = nativeFabricUIManager;
const activeTimeouts: Map<number, ResponderTimeout> = new Map();
const rootEventTypesToEventComponentInstances: Map<
ReactNativeEventResponderEventType | string,
string,
Set<ReactNativeEventComponentInstance>,
> = new Map();
const targetEventTypeCached: Map<
Array<ReactNativeEventResponderEventType>,
Set<ReactNativeEventResponderEventType>,
> = new Map();
const ownershipChangeListeners: Set<
ReactNativeEventComponentInstance,
> = new Set();
@ -214,9 +207,7 @@ const eventResponderContext: ReactNativeResponderContext = {
});
});
},
addRootEventTypes(
rootEventTypes: Array<ReactNativeEventResponderEventType>,
): void {
addRootEventTypes(rootEventTypes: Array<string>): void {
validateResponderContext();
for (let i = 0; i < rootEventTypes.length; i++) {
const rootEventType = rootEventTypes[i];
@ -224,9 +215,7 @@ const eventResponderContext: ReactNativeResponderContext = {
registerRootEventType(rootEventType, eventComponentInstance);
}
},
removeRootEventTypes(
rootEventTypes: Array<ReactNativeEventResponderEventType>,
): void {
removeRootEventTypes(rootEventTypes: Array<string>): void {
validateResponderContext();
for (let i = 0; i < rootEventTypes.length; i++) {
const rootEventType = rootEventTypes[i];
@ -330,7 +319,7 @@ function processTimers(
}
function createFabricResponderEvent(
topLevelType: ReactNativeEventResponderEventType,
topLevelType: string,
nativeEvent: ReactFaricEvent,
target: null | ReactNativeEventTarget,
): ReactNativeResponderEvent {
@ -451,19 +440,18 @@ function processEvents(events: Array<EventObjectType>): void {
}
}
function getFabricTargetEventTypesSet(
eventTypes: Array<ReactNativeEventResponderEventType>,
): Set<ReactNativeEventResponderEventType> {
let cachedSet = targetEventTypeCached.get(eventTypes);
if (cachedSet === undefined) {
cachedSet = new Set();
for (let i = 0; i < eventTypes.length; i++) {
cachedSet.add(eventTypes[i]);
// TODO this function is almost an exact copy of the DOM version, we should
// somehow share the logic
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;
}
// TODO this function is almost an exact copy of the DOM version, we should
@ -499,7 +487,7 @@ function checkForLocalPropagationContinuation(
// TODO this function is almost an exact copy of the DOM version, we should
// somehow share the logic
function handleTargetEventResponderInstance(
topLevelType: ReactNativeEventResponderEventType,
topLevelType: string,
responderEvent: ReactNativeResponderEvent,
eventComponentInstance: ReactNativeEventComponentInstance,
hookComponentResponderValidation: null | Set<ReactNativeEventResponder>,
@ -509,8 +497,7 @@ function handleTargetEventResponderInstance(
const targetEventTypes = responder.targetEventTypes;
// Validate the target event type exists on the responder
if (targetEventTypes !== undefined) {
const targetEventTypesSet = getFabricTargetEventTypesSet(targetEventTypes);
if (targetEventTypesSet.has(topLevelType)) {
if (responderEventTypesContainType(targetEventTypes, topLevelType)) {
if (hookComponentResponderValidation !== null) {
hookComponentResponderValidation.add(responder);
}
@ -544,7 +531,7 @@ function handleTargetEventResponderInstance(
// TODO this function is almost an exact copy of the DOM version, we should
// somehow share the logic
function traverseAndHandleEventResponderInstances(
topLevelType: ReactNativeEventResponderEventType,
topLevelType: string,
targetFiber: null | Fiber,
nativeEvent: ReactFaricEvent,
): void {
@ -642,7 +629,7 @@ function traverseAndHandleEventResponderInstances(
// TODO this function is almost an exact copy of the DOM version, we should
// somehow share the logic
export function dispatchEventForResponderEventSystem(
topLevelType: ReactNativeEventResponderEventType,
topLevelType: string,
targetFiber: null | Fiber,
nativeEvent: ReactFaricEvent,
): void {
@ -745,7 +732,7 @@ export function unmountEventResponder(
}
function registerRootEventType(
rootEventType: ReactNativeEventResponderEventType,
rootEventType: string,
eventComponentInstance: ReactNativeEventComponentInstance,
) {
let rootEventComponentInstances = rootEventTypesToEventComponentInstances.get(
@ -775,7 +762,7 @@ function registerRootEventType(
export function addRootEventTypesForComponentInstance(
eventComponentInstance: ReactNativeEventComponentInstance,
rootEventTypes: Array<ReactNativeEventResponderEventType>,
rootEventTypes: Array<string>,
): void {
for (let i = 0; i < rootEventTypes.length; i++) {
const rootEventType = rootEventTypes[i];

View File

@ -13,7 +13,6 @@ import type {
MeasureOnSuccessCallback,
NativeMethodsMixinType,
ReactNativeBaseComponentViewConfig,
ReactNativeEventResponderEventType,
ReactNativeResponderEvent,
ReactNativeResponderContext,
} from './ReactNativeTypes';
@ -66,7 +65,6 @@ const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
let nextReactTag = 2;
type ReactNativeEventComponentInstance = ReactEventComponentInstance<
ReactNativeEventResponderEventType,
ReactNativeResponderEvent,
ReactNativeResponderContext,
>;

View File

@ -9,7 +9,6 @@
import type {
ReactNativeBaseComponentViewConfig,
ReactNativeEventResponderEventType,
ReactNativeResponderEvent,
ReactNativeResponderContext,
} from './ReactNativeTypes';
@ -35,7 +34,6 @@ import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';
const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
type ReactNativeEventComponentInstance = ReactEventComponentInstance<
ReactNativeEventResponderEventType,
ReactNativeResponderEvent,
ReactNativeResponderContext,
>;

View File

@ -157,17 +157,6 @@ export type ReactFabricType = {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: SecretInternalsFabricType,
};
export type ReactNativeEventResponderEventType =
| 'topMouseDown'
| 'topMouseMove'
| 'topMouseUp'
| 'topScroll'
| 'topSelectionChange'
| 'topTouchCancel'
| 'topTouchEnd'
| 'topTouchMove'
| 'topTouchStart';
export type ReactNativeEventTarget = {
node: Object,
canonical: {
@ -202,7 +191,7 @@ export type ReactNativeResponderEvent = {
currentTarget: null | ReactNativeEventTarget,
nativeEvent: ReactFaricEvent,
target: null | ReactNativeEventTarget,
type: ReactNativeEventResponderEventType,
type: string,
};
export type ReactNativeResponderContext = {
@ -224,12 +213,8 @@ export type ReactNativeResponderContext = {
bottom: number,
}) => void,
): void,
addRootEventTypes: (
rootEventTypes: Array<ReactNativeEventResponderEventType>,
) => void,
removeRootEventTypes: (
rootEventTypes: Array<ReactNativeEventResponderEventType>,
) => void,
addRootEventTypes: (rootEventTypes: Array<string>) => void,
removeRootEventTypes: (rootEventTypes: Array<string>) => void,
setTimeout: (func: () => void, timeout: number) => number,
clearTimeout: (timerId: number) => void,
getTimeStamp: () => number,

View File

@ -103,7 +103,7 @@ if (__DEV__) {
export type Dependencies = {
expirationTime: ExpirationTime,
firstContext: ContextDependency<mixed> | null,
events: Array<ReactEventComponentInstance<any, any, any>> | null,
events: Array<ReactEventComponentInstance<any, any>> | null,
};
// A Fiber is work on a Component that needs to be done or was done. There can

View File

@ -1126,7 +1126,6 @@ function completeWork(
let eventComponentInstance: ReactEventComponentInstance<
any,
any,
any,
> | null =
workInProgress.stateNode;

View File

@ -32,8 +32,8 @@ export function prepareToReadEventComponents(workInProgress: Fiber): void {
currentEventComponentInstanceIndex = 0;
}
export function updateEventComponentInstance<T, E, C>(
eventComponent: ReactEventComponent<T, E, C>,
export function updateEventComponentInstance<E, C>(
eventComponent: ReactEventComponent<E, C>,
props: Object,
): void {
const responder = eventComponent.responder;
@ -82,14 +82,14 @@ export function updateEventComponentInstance<T, E, C>(
}
}
export function createEventComponentInstance<T, E, C>(
export function createEventComponentInstance<E, C>(
currentFiber: Fiber,
props: Object,
responder: ReactEventResponder<T, E, C>,
responder: ReactEventResponder<E, C>,
rootInstance: mixed,
state: Object,
isHook: boolean,
): ReactEventComponentInstance<T, E, C> {
): ReactEventComponentInstance<E, C> {
return {
currentFiber,
isHook,

View File

@ -83,8 +83,8 @@ export type Dispatcher = {
deps: Array<mixed> | void | null,
): void,
useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void,
useEvent<T, E, C>(
eventComponent: ReactEventComponent<T, E, C>,
useEvent<E, C>(
eventComponent: ReactEventComponent<E, C>,
props: Object,
): void,
};
@ -1416,7 +1416,7 @@ if (__DEV__) {
mountHookTypesDev();
return mountDebugValue(value, formatterFn);
},
useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
currentHookNameInDev = 'useEvent';
mountHookTypesDev();
updateEventComponentInstance(eventComponent, props);
@ -1518,7 +1518,7 @@ if (__DEV__) {
updateHookTypesDev();
return mountDebugValue(value, formatterFn);
},
useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
currentHookNameInDev = 'useEvent';
updateHookTypesDev();
updateEventComponentInstance(eventComponent, props);
@ -1620,7 +1620,7 @@ if (__DEV__) {
updateHookTypesDev();
return updateDebugValue(value, formatterFn);
},
useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
currentHookNameInDev = 'useEvent';
updateHookTypesDev();
updateEventComponentInstance(eventComponent, props);
@ -1733,7 +1733,7 @@ if (__DEV__) {
mountHookTypesDev();
return mountDebugValue(value, formatterFn);
},
useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
currentHookNameInDev = 'useEvent';
warnInvalidHookAccess();
mountHookTypesDev();
@ -1847,7 +1847,7 @@ if (__DEV__) {
updateHookTypesDev();
return updateDebugValue(value, formatterFn);
},
useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
currentHookNameInDev = 'useEvent';
warnInvalidHookAccess();
updateHookTypesDev();

View File

@ -286,19 +286,19 @@ export function unhideTextInstance(
}
export function mountEventComponent(
eventComponentInstance: ReactEventComponentInstance<any, any, any>,
eventComponentInstance: ReactEventComponentInstance<any, any>,
): void {
// noop
}
export function updateEventComponent(
eventComponentInstance: ReactEventComponentInstance<any, any, any>,
eventComponentInstance: ReactEventComponentInstance<any, any>,
): void {
// noop
}
export function unmountEventComponent(
eventComponentInstance: ReactEventComponentInstance<any, any, any>,
eventComponentInstance: ReactEventComponentInstance<any, any>,
): void {
// noop
}

View File

@ -138,8 +138,8 @@ export function useDebugValue(value: any, formatterFn: ?(value: any) => any) {
export const emptyObject = {};
export function useEvent<T, E, C>(
eventComponent: ReactEventComponent<T, E, C>,
export function useEvent<E, C>(
eventComponent: ReactEventComponent<E, C>,
props: null | Object,
) {
const dispatcher = resolveDispatcher();

View File

@ -15,10 +15,6 @@ import type {
type AnyNativeEvent = Event | KeyboardEvent | MouseEvent | Touch;
export type ReactDOMEventResponderEventType =
| string
| {name: string, passive?: boolean};
export type PointerType =
| ''
| 'mouse'
@ -39,13 +35,11 @@ export type ReactDOMResponderEvent = {
};
export type ReactDOMEventResponder = ReactEventResponder<
ReactDOMEventResponderEventType,
ReactDOMResponderEvent,
ReactDOMResponderContext,
>;
export type ReactDOMEventComponentInstance = ReactEventComponentInstance<
ReactDOMEventResponderEventType,
ReactDOMResponderEvent,
ReactDOMResponderContext,
>;
@ -62,12 +56,8 @@ export type ReactDOMResponderContext = {
) => boolean,
isTargetWithinEventComponent: (Element | Document) => boolean,
isTargetWithinEventResponderScope: (Element | Document) => boolean,
addRootEventTypes: (
rootEventTypes: Array<ReactDOMEventResponderEventType>,
) => void,
removeRootEventTypes: (
rootEventTypes: Array<ReactDOMEventResponderEventType>,
) => void,
addRootEventTypes: (rootEventTypes: Array<string>) => void,
removeRootEventTypes: (rootEventTypes: Array<string>) => void,
hasOwnership: () => boolean,
requestGlobalOwnership: () => boolean,
releaseOwnership: () => boolean,

View File

@ -14,7 +14,7 @@ export type ReactNode =
| ReactFragment
| ReactProvider<any>
| ReactConsumer<any>
| ReactEventComponent<any, any, any>;
| ReactEventComponent<any, any>;
export type ReactEmpty = null | void | boolean;
@ -80,20 +80,20 @@ export type RefObject = {|
current: any,
|};
export type ReactEventComponentInstance<T, E, C> = {|
export type ReactEventComponentInstance<E, C> = {|
currentFiber: mixed,
isHook: boolean,
props: Object,
responder: ReactEventResponder<T, E, C>,
responder: ReactEventResponder<E, C>,
rootEventTypes: null | Set<string>,
rootInstance: null | mixed,
state: Object,
|};
export type ReactEventResponder<T, E, C> = {
export type ReactEventResponder<E, C> = {
displayName: string,
targetEventTypes?: Array<T>,
rootEventTypes?: Array<T>,
targetEventTypes?: Array<string>,
rootEventTypes?: Array<string>,
getInitialState?: (props: Object) => Object,
allowMultipleHostChildren: boolean,
allowEventHooks: boolean,
@ -104,9 +104,9 @@ export type ReactEventResponder<T, E, C> = {
onOwnershipChange?: (context: C, props: Object, state: Object) => void,
};
export type ReactEventComponent<T, E, C> = {|
export type ReactEventComponent<E, C> = {|
$$typeof: Symbol | number,
responder: ReactEventResponder<T, E, C>,
responder: ReactEventResponder<E, C>,
|};
export opaque type EventPriority = 0 | 1 | 2;

View File

@ -28,9 +28,9 @@ if (__DEV__) {
}
}
export default function createEventComponent<T, E, C>(
responder: ReactEventResponder<T, E, C>,
): ReactEventComponent<T, E, C> {
export default function createEventComponent<E, C>(
responder: ReactEventResponder<E, C>,
): ReactEventComponent<E, C> {
// We use responder as a Map key later on. When we have a bad
// polyfill, then we can't use it as a key as the polyfill tries
// to add a property to the object.

View File

@ -0,0 +1,13 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
export default function endsWith(subject: string, search: string): boolean {
const length = subject.length;
return subject.substring(length - search.length, length) === search;
}