[Flare] Revise responder event types (#16081)
Dominic Gannaway committed
Jul 8, 2019 at 14:35 UTC
67e3f3fb6e342f95f00215c84d5d013d7b0e1b33
25 files changed
+141
-279
packages/react-art/src/ReactARTHostConfig.js
+3
-3
@@ -428,19 +428,19 @@ export function unhideTextInstance(textInstance, text): void {
428
}
429
430
export function mountEventComponent(
431
- eventComponentInstance: ReactEventComponentInstance<any, any, any>,
431
+ eventComponentInstance: ReactEventComponentInstance<any, any>,
432
) {
433
throw new Error('Not yet implemented.');
434
}
435
436
export function updateEventComponent(
437
- eventComponentInstance: ReactEventComponentInstance<any, any, any>,
437
+ eventComponentInstance: ReactEventComponentInstance<any, any>,
438
) {
439
throw new Error('Not yet implemented.');
440
}
441
442
export function unmountEventComponent(
443
- eventComponentInstance: ReactEventComponentInstance<any, any, any>,
443
+ eventComponentInstance: ReactEventComponentInstance<any, any>,
444
): void {
445
throw new Error('Not yet implemented.');
446
}
packages/react-dom/src/client/ReactDOMComponent.js
+13
-37
@@ -13,12 +13,9 @@ import {registrationNameModules} from 'events/EventPluginRegistry';
13
import warning from 'shared/warning';
14
import {canUseDOM} from 'shared/ExecutionEnvironment';
15
import warningWithoutStack from 'shared/warningWithoutStack';
16
-import type {ReactDOMEventResponderEventType} from 'shared/ReactDOMTypes';
16
+import endsWith from 'shared/endsWith';
17
import type {DOMTopLevelEventType} from 'events/TopLevelEventTypes';
18
-import {
19
- setListenToResponderEventTypes,
20
- generateListeningKey,
21
-} from '../events/DOMEventResponderSystem';
18
+import {setListenToResponderEventTypes} from '../events/DOMEventResponderSystem';
19
20
import {
21
getValueForAttribute,
@@ -1284,7 +1281,7 @@ export function restoreControlledState(
1281
}
1282
1283
export function listenToEventResponderEventTypes(
1287
- eventTypes: Array<ReactDOMEventResponderEventType>,
1284
+ eventTypes: Array<string>,
1285
element: Element | Document,
1286
): void {
1287
if (enableFlareAPI) {
@@ -1294,40 +1291,19 @@ export function listenToEventResponderEventTypes(
1291
1292
// Go through each target event type of the event responder
1293
for (let i = 0, length = eventTypes.length; i < length; ++i) {
1297
- const targetEventType = eventTypes[i];
1298
- let topLevelType;
1299
- let passive = true;
1300
-
1301
- // If no event config object is provided (i.e. - only a string),
1302
- // we default to enabling passive and not capture.
1303
- if (typeof targetEventType === 'string') {
1304
- topLevelType = targetEventType;
1305
- } else {
1306
- if (__DEV__) {
1307
- warning(
1308
- typeof targetEventType === 'object' && targetEventType !== null,
1309
- 'Event Responder: invalid entry in event types array. ' +
1310
- 'Entry must be string or an object. Instead, got %s.',
1311
- targetEventType,
1312
- );
1313
- }
1314
- const targetEventConfigObject = ((targetEventType: any): {
1315
- name: string,
1316
- passive?: boolean,
1317
- });
1318
- topLevelType = targetEventConfigObject.name;
1319
- if (targetEventConfigObject.passive !== undefined) {
1320
- passive = targetEventConfigObject.passive;
1321
- }
1322
- }
1323
- const listeningName = generateListeningKey(topLevelType, passive);
1324
- if (!listeningSet.has(listeningName)) {
1294
+ const eventType = eventTypes[i];
1295
+ const isPassive = !endsWith(eventType, '_active');
1296
+ const eventKey = isPassive ? eventType + '_passive' : eventType;
1297
+ const targetEventType = isPassive
1298
+ ? eventType
1299
+ : eventType.substring(0, eventType.length - 7);
1300
+ if (!listeningSet.has(eventKey)) {
1301
trapEventForResponderEventSystem(
1302
element,
1327
- ((topLevelType: any): DOMTopLevelEventType),
1328
- passive,
1303
+ ((targetEventType: any): DOMTopLevelEventType),
1304
+ isPassive,
1305
);
1330
- listeningSet.add(listeningName);
1306
+ listeningSet.add(eventKey);
1307
}
1308
}
1309
}
packages/react-dom/src/events/DOMEventResponderSystem.js
+29
-106
@@ -21,7 +21,6 @@ import type {EventPriority} from 'shared/ReactTypes';
21
import type {
22
ReactDOMEventResponder,
23
ReactDOMEventComponentInstance,
24
- ReactDOMEventResponderEventType,
24
ReactDOMResponderContext,
25
ReactDOMResponderEvent,
26
} from 'shared/ReactDOMTypes';
@@ -95,10 +94,6 @@ const rootEventTypesToEventComponentInstances: Map<
94
DOMTopLevelEventType | string,
95
Set<ReactDOMEventComponentInstance>,
96
> = new Map();
98
-const targetEventTypeCached: Map<
99
- Array<ReactDOMEventResponderEventType>,
100
- Set<string>,
101
-> = new Map();
97
const ownershipChangeListeners: Set<ReactDOMEventComponentInstance> = new Set();
98
const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
99
const eventListeners:
@@ -248,9 +243,7 @@ const eventResponderContext: ReactDOMResponderContext = {
243
}
244
return false;
245
},
251
- addRootEventTypes(
252
- rootEventTypes: Array<ReactDOMEventResponderEventType>,
253
- ): void {
246
+ addRootEventTypes(rootEventTypes: Array<string>): void {
247
validateResponderContext();
248
const activeDocument = getActiveDocument();
249
listenToResponderEventTypesImpl(rootEventTypes, activeDocument);
@@ -260,37 +253,17 @@ const eventResponderContext: ReactDOMResponderContext = {
253
registerRootEventType(rootEventType, eventComponentInstance);
254
}
255
},
263
- removeRootEventTypes(
264
- rootEventTypes: Array<ReactDOMEventResponderEventType>,
265
- ): void {
256
+ removeRootEventTypes(rootEventTypes: Array<string>): void {
257
validateResponderContext();
258
for (let i = 0; i < rootEventTypes.length; i++) {
259
const rootEventType = rootEventTypes[i];
269
- let name = rootEventType;
270
- let passive = true;
271
-
272
- if (typeof rootEventType !== 'string') {
273
- const targetEventConfigObject = ((rootEventType: any): {
274
- name: string,
275
- passive?: boolean,
276
- });
277
- name = targetEventConfigObject.name;
278
- if (targetEventConfigObject.passive !== undefined) {
279
- passive = targetEventConfigObject.passive;
280
- }
281
- }
282
-
283
- const listeningName = generateListeningKey(
284
- ((name: any): string),
285
- passive,
286
- );
260
let rootEventComponents = rootEventTypesToEventComponentInstances.get(
288
- listeningName,
261
+ rootEventType,
262
);
263
let rootEventTypesSet = ((currentInstance: any): ReactDOMEventComponentInstance)
264
.rootEventTypes;
265
if (rootEventTypesSet !== null) {
293
- rootEventTypesSet.delete(listeningName);
266
+ rootEventTypesSet.delete(rootEventType);
267
}
268
if (rootEventComponents !== undefined) {
269
rootEventComponents.delete(
@@ -595,41 +568,20 @@ function processEventQueue(): void {
568
}
569
}
570
598
-function getDOMTargetEventTypesSet(
599
- eventTypes: Array<ReactDOMEventResponderEventType>,
600
-): Set<string> {
601
- let cachedSet = targetEventTypeCached.get(eventTypes);
602
-
603
- if (cachedSet === undefined) {
604
- cachedSet = new Set();
605
- for (let i = 0; i < eventTypes.length; i++) {
606
- const eventType = eventTypes[i];
607
- let name = eventType;
608
- let passive = true;
609
-
610
- if (typeof eventType !== 'string') {
611
- const targetEventConfigObject = ((eventType: any): {
612
- name: string,
613
- passive?: boolean,
614
- });
615
- name = targetEventConfigObject.name;
616
- if (targetEventConfigObject.passive !== undefined) {
617
- passive = targetEventConfigObject.passive;
618
- }
619
- }
620
- const listeningName = generateListeningKey(
621
- ((name: any): string),
622
- passive,
623
- );
624
- cachedSet.add(listeningName);
571
+function responderEventTypesContainType(
572
+ eventTypes: Array<string>,
573
+ type: string,
574
+): boolean {
575
+ for (let i = 0, len = eventTypes.length; i < len; i++) {
576
+ if (eventTypes[i] === type) {
577
+ return true;
578
}
626
- targetEventTypeCached.set(eventTypes, cachedSet);
579
}
628
- return cachedSet;
580
+ return false;
581
}
582
583
function handleTargetEventResponderInstance(
632
- listeningName: string,
584
+ eventType: string,
585
responderEvent: ReactDOMResponderEvent,
586
eventComponentInstance: ReactDOMEventComponentInstance,
587
hookComponentResponderValidation: null | Set<ReactDOMEventResponder>,
@@ -639,8 +591,7 @@ function handleTargetEventResponderInstance(
591
const targetEventTypes = responder.targetEventTypes;
592
// Validate the target event type exists on the responder
593
if (targetEventTypes !== undefined) {
642
- const targetEventTypesSet = getDOMTargetEventTypesSet(targetEventTypes);
643
- if (targetEventTypesSet.has(listeningName)) {
594
+ if (responderEventTypesContainType(targetEventTypes, eventType)) {
595
if (hookComponentResponderValidation !== null) {
596
hookComponentResponderValidation.add(responder);
597
}
@@ -700,7 +651,7 @@ function checkForLocalPropagationContinuation(
651
}
652
653
function traverseAndHandleEventResponderInstances(
703
- topLevelType: DOMTopLevelEventType,
654
+ topLevelType: string,
655
targetFiber: null | Fiber,
656
nativeEvent: AnyNativeEvent,
657
nativeEventTarget: EventTarget,
@@ -708,17 +659,15 @@ function traverseAndHandleEventResponderInstances(
659
): void {
660
const isPassiveEvent = (eventSystemFlags & IS_PASSIVE) !== 0;
661
const isPassiveSupported = (eventSystemFlags & PASSIVE_NOT_SUPPORTED) === 0;
711
- const listeningName = generateListeningKey(
712
- ((topLevelType: any): string),
713
- isPassiveEvent || !isPassiveSupported,
714
- );
662
+ const isPassive = isPassiveEvent || !isPassiveSupported;
663
+ const eventType = isPassive ? topLevelType : topLevelType + '_active';
664
665
// Trigger event responders in this order:
666
// - Bubble target phase
667
// - Root phase
668
669
const responderEvent = createDOMResponderEvent(
721
- ((topLevelType: any): string),
670
+ topLevelType,
671
nativeEvent,
672
((nativeEventTarget: any): Element | Document),
673
isPassiveEvent,
@@ -743,7 +692,7 @@ function traverseAndHandleEventResponderInstances(
692
// Switch to the current fiber tree
693
node = eventComponentInstance.currentFiber;
694
handleTargetEventResponderInstance(
746
- listeningName,
695
+ eventType,
696
responderEvent,
697
eventComponentInstance,
698
hookComponentResponderValidation,
@@ -760,7 +709,7 @@ function traverseAndHandleEventResponderInstances(
709
)
710
) {
711
handleTargetEventResponderInstance(
763
- listeningName,
712
+ eventType,
713
responderEvent,
714
eventComponentInstance,
715
null,
@@ -776,7 +725,7 @@ function traverseAndHandleEventResponderInstances(
725
responderEvent.currentTarget = null;
726
// Root phase
727
const rootEventInstances = rootEventTypesToEventComponentInstances.get(
779
- listeningName,
728
+ eventType,
729
);
730
if (rootEventInstances !== undefined) {
731
const rootEventComponentInstances = Array.from(rootEventInstances);
@@ -906,7 +855,7 @@ function validateResponderContext(): void {
855
}
856
857
export function dispatchEventForResponderEventSystem(
909
- topLevelType: DOMTopLevelEventType,
858
+ topLevelType: string,
859
targetFiber: null | Fiber,
860
nativeEvent: AnyNativeEvent,
861
nativeEventTarget: EventTarget,
@@ -950,7 +899,7 @@ export function dispatchEventForResponderEventSystem(
899
900
export function addRootEventTypesForComponentInstance(
901
eventComponentInstance: ReactDOMEventComponentInstance,
953
- rootEventTypes: Array<ReactDOMEventResponderEventType>,
902
+ rootEventTypes: Array<string>,
903
): void {
904
for (let i = 0; i < rootEventTypes.length; i++) {
905
const rootEventType = rootEventTypes[i];
@@ -959,31 +908,16 @@ export function addRootEventTypesForComponentInstance(
908
}
909
910
function registerRootEventType(
962
- rootEventType: ReactDOMEventResponderEventType,
911
+ rootEventType: string,
912
eventComponentInstance: ReactDOMEventComponentInstance,
913
): void {
965
- let name = rootEventType;
966
- let passive = true;
967
-
968
- if (typeof rootEventType !== 'string') {
969
- const targetEventConfigObject = ((rootEventType: any): {
970
- name: string,
971
- passive?: boolean,
972
- });
973
- name = targetEventConfigObject.name;
974
- if (targetEventConfigObject.passive !== undefined) {
975
- passive = targetEventConfigObject.passive;
976
- }
977
- }
978
-
979
- const listeningName = generateListeningKey(((name: any): string), passive);
914
let rootEventComponentInstances = rootEventTypesToEventComponentInstances.get(
981
- listeningName,
915
+ rootEventType,
916
);
917
if (rootEventComponentInstances === undefined) {
918
rootEventComponentInstances = new Set();
919
rootEventTypesToEventComponentInstances.set(
986
- listeningName,
920
+ rootEventType,
921
rootEventComponentInstances,
922
);
923
}
@@ -992,23 +926,12 @@ function registerRootEventType(
926
rootEventTypesSet = eventComponentInstance.rootEventTypes = new Set();
927
}
928
invariant(
995
- !rootEventTypesSet.has(listeningName),
929
+ !rootEventTypesSet.has(rootEventType),
930
'addRootEventTypes() found a duplicate root event ' +
931
'type of "%s". This might be because the event type exists in the event responder "rootEventTypes" ' +
932
'array or because of a previous addRootEventTypes() using this root event type.',
999
- name,
933
+ rootEventType,
934
);
1001
- rootEventTypesSet.add(listeningName);
935
+ rootEventTypesSet.add(rootEventType);
936
rootEventComponentInstances.add(eventComponentInstance);
937
}
1004
-
1005
-export function generateListeningKey(
1006
- topLevelType: string,
1007
- passive: boolean,
1008
-): string {
1009
- // Create a unique name for this event, plus its properties. We'll
1010
- // use this to ensure we don't listen to the same event with the same
1011
- // properties again.
1012
- const passiveKey = passive ? '_passive' : '_active';
1013
- return `${topLevelType}${passiveKey}`;
1014
-}
packages/react-dom/src/events/ReactDOMEventListener.js
+1
-1
@@ -334,7 +334,7 @@ export function dispatchEvent(
334
} else {
335
// React Flare event system
336
dispatchEventForResponderEventSystem(
337
- topLevelType,
337
+ (topLevelType: any),
338
targetInst,
339
nativeEvent,
340
nativeEventTarget,
packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js
+4
-4
@@ -627,7 +627,7 @@ describe('DOMEventResponderSystem', () => {
627
const buttonRef = React.createRef();
628
629
const ClickEventComponent1 = createReactEventComponent({
630
- targetEventTypes: [{name: 'click', passive: false, capture: false}],
630
+ targetEventTypes: ['click_active'],
631
onEvent: event => {
632
clickEventComponent1Fired++;
633
eventLog.push({
@@ -639,7 +639,7 @@ describe('DOMEventResponderSystem', () => {
639
});
640
641
const ClickEventComponent2 = createReactEventComponent({
642
- targetEventTypes: [{name: 'click', passive: true, capture: false}],
642
+ targetEventTypes: ['click'],
643
onEvent: event => {
644
clickEventComponent2Fired++;
645
eventLog.push({
@@ -686,7 +686,7 @@ describe('DOMEventResponderSystem', () => {
686
let eventLog = [];
687
688
const ClickEventComponent1 = createReactEventComponent({
689
- rootEventTypes: [{name: 'click', passive: false, capture: false}],
689
+ rootEventTypes: ['click_active'],
690
onRootEvent: event => {
691
clickEventComponent1Fired++;
692
eventLog.push({
@@ -698,7 +698,7 @@ describe('DOMEventResponderSystem', () => {
698
});
699
700
const ClickEventComponent2 = createReactEventComponent({
701
- rootEventTypes: [{name: 'click', passive: true, capture: false}],
701
+ rootEventTypes: ['click'],
702
onRootEvent: event => {
703
clickEventComponent2Fired++;
704
eventLog.push({
packages/react-events/src/dom/Drag.js
+8
-9
@@ -18,11 +18,7 @@ import React from 'react';
18
import {DiscreteEvent, UserBlockingEvent} from 'shared/ReactTypes';
19
20
const targetEventTypes = ['pointerdown'];
21
-const rootEventTypes = [
22
- 'pointerup',
23
- 'pointercancel',
24
- {name: 'pointermove', passive: false},
25
-];
21
+const rootEventTypes = ['pointerup', 'pointercancel', 'pointermove_active'];
22
23
type DragState = {
24
dragTarget: null | Element | Document,
@@ -38,10 +34,13 @@ type DragState = {
34
// too
35
if (typeof window !== 'undefined' && window.PointerEvent === undefined) {
36
targetEventTypes.push('touchstart', 'mousedown');
41
- rootEventTypes.push('mouseup', 'mousemove', 'touchend', 'touchcancel', {
42
- name: 'touchmove',
43
- passive: false,
44
- });
37
+ rootEventTypes.push(
38
+ 'mouseup',
39
+ 'mousemove',
40
+ 'touchend',
41
+ 'touchcancel',
42
+ 'touchmove_active',
43
+ );
44
}
45
46
type EventData = {
packages/react-events/src/dom/Focus.js
+1
-4
@@ -46,10 +46,7 @@ const isMac =
46
? /^Mac/.test(window.navigator.platform)
47
: false;
48
49
-const targetEventTypes = [
50
- {name: 'focus', passive: true},
51
- {name: 'blur', passive: true},
52
-];
49
+const targetEventTypes = ['focus', 'blur'];
50
51
const rootEventTypes = [
52
'keydown',
packages/react-events/src/dom/FocusScope.js
+2
-2
@@ -25,8 +25,8 @@ type FocusScopeState = {
25
currentFocusedNode: null | HTMLElement,
26
};
27
28
-const targetEventTypes = [{name: 'keydown', passive: false}];
29
-const rootEventTypes = [{name: 'focus', passive: true}];
28
+const targetEventTypes = ['keydown_active'];
29
+const rootEventTypes = ['focus'];
30
31
function focusElement(element: ?HTMLElement) {
32
if (element != null) {
packages/react-events/src/dom/Press.js
+5
-5
@@ -123,12 +123,12 @@ const DEFAULT_PRESS_RETENTION_OFFSET = {
123
};
124
125
const targetEventTypes = [
126
- {name: 'keydown', passive: false},
127
- {name: 'contextmenu', passive: false},
126
+ 'keydown_active',
127
+ 'contextmenu_active',
128
// We need to preventDefault on pointerdown for mouse/pen events
129
// that are in hit target area but not the element area.
130
- {name: 'pointerdown', passive: false},
131
- {name: 'click', passive: false},
130
+ 'pointerdown_active',
131
+ 'click_active',
132
];
133
const rootEventTypes = [
134
'click',
@@ -139,7 +139,7 @@ const rootEventTypes = [
139
'pointercancel',
140
// We listen to this here so stopPropagation can
141
// block other mouseup events used internally
142
- {name: 'mouseup', passive: false},
142
+ 'mouseup_active',
143
'touchend',
144
];
145
packages/react-events/src/dom/Swipe.js
+8
-9
@@ -18,20 +18,19 @@ import React from 'react';
18
import {UserBlockingEvent, DiscreteEvent} from 'shared/ReactTypes';
19
20
const targetEventTypes = ['pointerdown'];
21
-const rootEventTypes = [
22
- 'pointerup',
23
- 'pointercancel',
24
- {name: 'pointermove', passive: false},
25
-];
21
+const rootEventTypes = ['pointerup', 'pointercancel', 'pointermove_active'];
22
23
// In the case we don't have PointerEvents (Safari), we listen to touch events
24
// too
25
if (typeof window !== 'undefined' && window.PointerEvent === undefined) {
26
targetEventTypes.push('touchstart', 'mousedown');
31
- rootEventTypes.push('mouseup', 'mousemove', 'touchend', 'touchcancel', {
32
- name: 'touchmove',
33
- passive: false,
34
- });
27
+ rootEventTypes.push(
28
+ 'mouseup',
29
+ 'mousemove',
30
+ 'touchend',
31
+ 'touchcancel',
32
+ 'touchmove_active',
33
+ );
34
}
35
36
type EventData = {
packages/react-events/src/rn/Press.js
-2
@@ -10,7 +10,6 @@
10
import type {
11
ReactNativeResponderEvent,
12
ReactNativeResponderContext,
13
- ReactNativeEventResponderEventType,
13
ReactNativeEventTarget,
14
PointerType,
15
ReactFaricEventTouch,
@@ -24,7 +23,6 @@ import {
23
} from 'react-native-renderer/src/ReactNativeTypes';
24
25
type ReactNativeEventResponder = ReactEventResponder<
27
- ReactNativeEventResponderEventType,
26
ReactNativeResponderEvent,
27
ReactNativeResponderContext,
28
>;
packages/react-native-renderer/src/ReactFabricEventResponderSystem.js
+20
-33
@@ -23,7 +23,6 @@ import type {
23
ReactEventComponentInstance,
24
} from 'shared/ReactTypes';
25
import type {
26
- ReactNativeEventResponderEventType,
26
ReactNativeResponderContext,
27
ReactNativeResponderEvent,
28
EventPriority,
@@ -74,13 +73,11 @@ type EventQueue = {
73
};
74
75
type ReactNativeEventResponder = ReactEventResponder<
77
- ReactNativeEventResponderEventType,
76
ReactNativeResponderEvent,
77
ReactNativeResponderContext,
78
>;
79
80
type ReactNativeEventComponentInstance = ReactEventComponentInstance<
83
- ReactNativeEventResponderEventType,
81
ReactNativeResponderEvent,
82
ReactNativeResponderContext,
83
>;
@@ -89,13 +86,9 @@ const {measureInWindow} = nativeFabricUIManager;
86
87
const activeTimeouts: Map<number, ResponderTimeout> = new Map();
88
const rootEventTypesToEventComponentInstances: Map<
92
- ReactNativeEventResponderEventType | string,
89
+ string,
90
Set<ReactNativeEventComponentInstance>,
91
> = new Map();
95
-const targetEventTypeCached: Map<
96
- Array<ReactNativeEventResponderEventType>,
97
- Set<ReactNativeEventResponderEventType>,
98
-> = new Map();
92
const ownershipChangeListeners: Set<
93
ReactNativeEventComponentInstance,
94
> = new Set();
@@ -214,9 +207,7 @@ const eventResponderContext: ReactNativeResponderContext = {
207
});
208
});
209
},
217
- addRootEventTypes(
218
- rootEventTypes: Array<ReactNativeEventResponderEventType>,
219
- ): void {
210
+ addRootEventTypes(rootEventTypes: Array<string>): void {
211
validateResponderContext();
212
for (let i = 0; i < rootEventTypes.length; i++) {
213
const rootEventType = rootEventTypes[i];
@@ -224,9 +215,7 @@ const eventResponderContext: ReactNativeResponderContext = {
215
registerRootEventType(rootEventType, eventComponentInstance);
216
}
217
},
227
- removeRootEventTypes(
228
- rootEventTypes: Array<ReactNativeEventResponderEventType>,
229
- ): void {
218
+ removeRootEventTypes(rootEventTypes: Array<string>): void {
219
validateResponderContext();
220
for (let i = 0; i < rootEventTypes.length; i++) {
221
const rootEventType = rootEventTypes[i];
@@ -330,7 +319,7 @@ function processTimers(
319
}
320
321
function createFabricResponderEvent(
333
- topLevelType: ReactNativeEventResponderEventType,
322
+ topLevelType: string,
323
nativeEvent: ReactFaricEvent,
324
target: null | ReactNativeEventTarget,
325
): ReactNativeResponderEvent {
@@ -451,19 +440,18 @@ function processEvents(events: Array<EventObjectType>): void {
440
}
441
}
442
454
-function getFabricTargetEventTypesSet(
455
- eventTypes: Array<ReactNativeEventResponderEventType>,
456
-): Set<ReactNativeEventResponderEventType> {
457
- let cachedSet = targetEventTypeCached.get(eventTypes);
458
-
459
- if (cachedSet === undefined) {
460
- cachedSet = new Set();
461
- for (let i = 0; i < eventTypes.length; i++) {
462
- cachedSet.add(eventTypes[i]);
443
+// TODO this function is almost an exact copy of the DOM version, we should
444
+// somehow share the logic
445
+function responderEventTypesContainType(
446
+ eventTypes: Array<string>,
447
+ type: string,
448
+): boolean {
449
+ for (let i = 0, len = eventTypes.length; i < len; i++) {
450
+ if (eventTypes[i] === type) {
451
+ return true;
452
}
464
- targetEventTypeCached.set(eventTypes, cachedSet);
453
}
466
- return cachedSet;
454
+ return false;
455
}
456
457
// TODO this function is almost an exact copy of the DOM version, we should
@@ -499,7 +487,7 @@ function checkForLocalPropagationContinuation(
487
// TODO this function is almost an exact copy of the DOM version, we should
488
// somehow share the logic
489
function handleTargetEventResponderInstance(
502
- topLevelType: ReactNativeEventResponderEventType,
490
+ topLevelType: string,
491
responderEvent: ReactNativeResponderEvent,
492
eventComponentInstance: ReactNativeEventComponentInstance,
493
hookComponentResponderValidation: null | Set<ReactNativeEventResponder>,
@@ -509,8 +497,7 @@ function handleTargetEventResponderInstance(
497
const targetEventTypes = responder.targetEventTypes;
498
// Validate the target event type exists on the responder
499
if (targetEventTypes !== undefined) {
512
- const targetEventTypesSet = getFabricTargetEventTypesSet(targetEventTypes);
513
- if (targetEventTypesSet.has(topLevelType)) {
500
+ if (responderEventTypesContainType(targetEventTypes, topLevelType)) {
501
if (hookComponentResponderValidation !== null) {
502
hookComponentResponderValidation.add(responder);
503
}
@@ -544,7 +531,7 @@ function handleTargetEventResponderInstance(
531
// TODO this function is almost an exact copy of the DOM version, we should
532
// somehow share the logic
533
function traverseAndHandleEventResponderInstances(
547
- topLevelType: ReactNativeEventResponderEventType,
534
+ topLevelType: string,
535
targetFiber: null | Fiber,
536
nativeEvent: ReactFaricEvent,
537
): void {
@@ -642,7 +629,7 @@ function traverseAndHandleEventResponderInstances(
629
// TODO this function is almost an exact copy of the DOM version, we should
630
// somehow share the logic
631
export function dispatchEventForResponderEventSystem(
645
- topLevelType: ReactNativeEventResponderEventType,
632
+ topLevelType: string,
633
targetFiber: null | Fiber,
634
nativeEvent: ReactFaricEvent,
635
): void {
@@ -745,7 +732,7 @@ export function unmountEventResponder(
732
}
733
734
function registerRootEventType(
748
- rootEventType: ReactNativeEventResponderEventType,
735
+ rootEventType: string,
736
eventComponentInstance: ReactNativeEventComponentInstance,
737
) {
738
let rootEventComponentInstances = rootEventTypesToEventComponentInstances.get(
@@ -775,7 +762,7 @@ function registerRootEventType(
762
763
export function addRootEventTypesForComponentInstance(
764
eventComponentInstance: ReactNativeEventComponentInstance,
778
- rootEventTypes: Array<ReactNativeEventResponderEventType>,
765
+ rootEventTypes: Array<string>,
766
): void {
767
for (let i = 0; i < rootEventTypes.length; i++) {
768
const rootEventType = rootEventTypes[i];
packages/react-native-renderer/src/ReactFabricHostConfig.js
-2
@@ -13,7 +13,6 @@ import type {
13
MeasureOnSuccessCallback,
14
NativeMethodsMixinType,
15
ReactNativeBaseComponentViewConfig,
16
- ReactNativeEventResponderEventType,
16
ReactNativeResponderEvent,
17
ReactNativeResponderContext,
18
} from './ReactNativeTypes';
@@ -66,7 +65,6 @@ const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
65
let nextReactTag = 2;
66
67
type ReactNativeEventComponentInstance = ReactEventComponentInstance<
69
- ReactNativeEventResponderEventType,
68
ReactNativeResponderEvent,
69
ReactNativeResponderContext,
70
>;
packages/react-native-renderer/src/ReactNativeHostConfig.js
-2
@@ -9,7 +9,6 @@
9
10
import type {
11
ReactNativeBaseComponentViewConfig,
12
- ReactNativeEventResponderEventType,
12
ReactNativeResponderEvent,
13
ReactNativeResponderContext,
14
} from './ReactNativeTypes';
@@ -35,7 +34,6 @@ import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';
34
const {get: getViewConfigForType} = ReactNativeViewConfigRegistry;
35
36
type ReactNativeEventComponentInstance = ReactEventComponentInstance<
38
- ReactNativeEventResponderEventType,
37
ReactNativeResponderEvent,
38
ReactNativeResponderContext,
39
>;
packages/react-native-renderer/src/ReactNativeTypes.js
+3
-18
@@ -157,17 +157,6 @@ export type ReactFabricType = {
157
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: SecretInternalsFabricType,
158
};
159
160
-export type ReactNativeEventResponderEventType =
161
- | 'topMouseDown'
162
- | 'topMouseMove'
163
- | 'topMouseUp'
164
- | 'topScroll'
165
- | 'topSelectionChange'
166
- | 'topTouchCancel'
167
- | 'topTouchEnd'
168
- | 'topTouchMove'
169
- | 'topTouchStart';
170
-
160
export type ReactNativeEventTarget = {
161
node: Object,
162
canonical: {
@@ -202,7 +191,7 @@ export type ReactNativeResponderEvent = {
191
currentTarget: null | ReactNativeEventTarget,
192
nativeEvent: ReactFaricEvent,
193
target: null | ReactNativeEventTarget,
205
- type: ReactNativeEventResponderEventType,
194
+ type: string,
195
};
196
197
export type ReactNativeResponderContext = {
@@ -224,12 +213,8 @@ export type ReactNativeResponderContext = {
213
bottom: number,
214
}) => void,
215
): void,
227
- addRootEventTypes: (
228
- rootEventTypes: Array<ReactNativeEventResponderEventType>,
229
- ) => void,
230
- removeRootEventTypes: (
231
- rootEventTypes: Array<ReactNativeEventResponderEventType>,
232
- ) => void,
216
+ addRootEventTypes: (rootEventTypes: Array<string>) => void,
217
+ removeRootEventTypes: (rootEventTypes: Array<string>) => void,
218
setTimeout: (func: () => void, timeout: number) => number,
219
clearTimeout: (timerId: number) => void,
220
getTimeStamp: () => number,
packages/react-reconciler/src/ReactFiber.js
+1
-1
@@ -103,7 +103,7 @@ if (__DEV__) {
103
export type Dependencies = {
104
expirationTime: ExpirationTime,
105
firstContext: ContextDependency<mixed> | null,
106
- events: Array<ReactEventComponentInstance<any, any, any>> | null,
106
+ events: Array<ReactEventComponentInstance<any, any>> | null,
107
};
108
109
// A Fiber is work on a Component that needs to be done or was done. There can
packages/react-reconciler/src/ReactFiberCompleteWork.js
-1
@@ -1126,7 +1126,6 @@ function completeWork(
1126
let eventComponentInstance: ReactEventComponentInstance<
1127
any,
1128
any,
1129
- any,
1129
> | null =
1130
workInProgress.stateNode;
1131
packages/react-reconciler/src/ReactFiberEvents.js
+5
-5
@@ -32,8 +32,8 @@ export function prepareToReadEventComponents(workInProgress: Fiber): void {
32
currentEventComponentInstanceIndex = 0;
33
}
34
35
-export function updateEventComponentInstance<T, E, C>(
36
- eventComponent: ReactEventComponent<T, E, C>,
35
+export function updateEventComponentInstance<E, C>(
36
+ eventComponent: ReactEventComponent<E, C>,
37
props: Object,
38
): void {
39
const responder = eventComponent.responder;
@@ -82,14 +82,14 @@ export function updateEventComponentInstance<T, E, C>(
82
}
83
}
84
85
-export function createEventComponentInstance<T, E, C>(
85
+export function createEventComponentInstance<E, C>(
86
currentFiber: Fiber,
87
props: Object,
88
- responder: ReactEventResponder<T, E, C>,
88
+ responder: ReactEventResponder<E, C>,
89
rootInstance: mixed,
90
state: Object,
91
isHook: boolean,
92
-): ReactEventComponentInstance<T, E, C> {
92
+): ReactEventComponentInstance<E, C> {
93
return {
94
currentFiber,
95
isHook,
packages/react-reconciler/src/ReactFiberHooks.js
+7
-7
@@ -83,8 +83,8 @@ export type Dispatcher = {
83
deps: Array<mixed> | void | null,
84
): void,
85
useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void,
86
- useEvent<T, E, C>(
87
- eventComponent: ReactEventComponent<T, E, C>,
86
+ useEvent<E, C>(
87
+ eventComponent: ReactEventComponent<E, C>,
88
props: Object,
89
): void,
90
};
@@ -1416,7 +1416,7 @@ if (__DEV__) {
1416
mountHookTypesDev();
1417
return mountDebugValue(value, formatterFn);
1418
},
1419
- useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
1419
+ useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
1420
currentHookNameInDev = 'useEvent';
1421
mountHookTypesDev();
1422
updateEventComponentInstance(eventComponent, props);
@@ -1518,7 +1518,7 @@ if (__DEV__) {
1518
updateHookTypesDev();
1519
return mountDebugValue(value, formatterFn);
1520
},
1521
- useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
1521
+ useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
1522
currentHookNameInDev = 'useEvent';
1523
updateHookTypesDev();
1524
updateEventComponentInstance(eventComponent, props);
@@ -1620,7 +1620,7 @@ if (__DEV__) {
1620
updateHookTypesDev();
1621
return updateDebugValue(value, formatterFn);
1622
},
1623
- useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
1623
+ useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
1624
currentHookNameInDev = 'useEvent';
1625
updateHookTypesDev();
1626
updateEventComponentInstance(eventComponent, props);
@@ -1733,7 +1733,7 @@ if (__DEV__) {
1733
mountHookTypesDev();
1734
return mountDebugValue(value, formatterFn);
1735
},
1736
- useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
1736
+ useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
1737
currentHookNameInDev = 'useEvent';
1738
warnInvalidHookAccess();
1739
mountHookTypesDev();
@@ -1847,7 +1847,7 @@ if (__DEV__) {
1847
updateHookTypesDev();
1848
return updateDebugValue(value, formatterFn);
1849
},
1850
- useEvent<T, E, C>(eventComponent: ReactEventComponent<T, E, C>, props) {
1850
+ useEvent<E, C>(eventComponent: ReactEventComponent<E, C>, props) {
1851
currentHookNameInDev = 'useEvent';
1852
warnInvalidHookAccess();
1853
updateHookTypesDev();
packages/react-test-renderer/src/ReactTestHostConfig.js
+3
-3
@@ -286,19 +286,19 @@ export function unhideTextInstance(
286
}
287
288
export function mountEventComponent(
289
- eventComponentInstance: ReactEventComponentInstance<any, any, any>,
289
+ eventComponentInstance: ReactEventComponentInstance<any, any>,
290
): void {
291
// noop
292
}
293
294
export function updateEventComponent(
295
- eventComponentInstance: ReactEventComponentInstance<any, any, any>,
295
+ eventComponentInstance: ReactEventComponentInstance<any, any>,
296
): void {
297
// noop
298
}
299
300
export function unmountEventComponent(
301
- eventComponentInstance: ReactEventComponentInstance<any, any, any>,
301
+ eventComponentInstance: ReactEventComponentInstance<any, any>,
302
): void {
303
// noop
304
}
packages/react/src/ReactHooks.js
+2
-2
@@ -138,8 +138,8 @@ export function useDebugValue(value: any, formatterFn: ?(value: any) => any) {
138
139
export const emptyObject = {};
140
141
-export function useEvent<T, E, C>(
142
- eventComponent: ReactEventComponent<T, E, C>,
141
+export function useEvent<E, C>(
142
+ eventComponent: ReactEventComponent<E, C>,
143
props: null | Object,
144
) {
145
const dispatcher = resolveDispatcher();
packages/shared/ReactDOMTypes.js
+2
-12
@@ -15,10 +15,6 @@ import type {
15
16
type AnyNativeEvent = Event | KeyboardEvent | MouseEvent | Touch;
17
18
-export type ReactDOMEventResponderEventType =
19
- | string
20
- | {name: string, passive?: boolean};
21
-
18
export type PointerType =
19
| ''
20
| 'mouse'
@@ -39,13 +35,11 @@ export type ReactDOMResponderEvent = {
35
};
36
37
export type ReactDOMEventResponder = ReactEventResponder<
42
- ReactDOMEventResponderEventType,
38
ReactDOMResponderEvent,
39
ReactDOMResponderContext,
40
>;
41
42
export type ReactDOMEventComponentInstance = ReactEventComponentInstance<
48
- ReactDOMEventResponderEventType,
43
ReactDOMResponderEvent,
44
ReactDOMResponderContext,
45
>;
@@ -62,12 +56,8 @@ export type ReactDOMResponderContext = {
56
) => boolean,
57
isTargetWithinEventComponent: (Element | Document) => boolean,
58
isTargetWithinEventResponderScope: (Element | Document) => boolean,
65
- addRootEventTypes: (
66
- rootEventTypes: Array<ReactDOMEventResponderEventType>,
67
- ) => void,
68
- removeRootEventTypes: (
69
- rootEventTypes: Array<ReactDOMEventResponderEventType>,
70
- ) => void,
59
+ addRootEventTypes: (rootEventTypes: Array<string>) => void,
60
+ removeRootEventTypes: (rootEventTypes: Array<string>) => void,
61
hasOwnership: () => boolean,
62
requestGlobalOwnership: () => boolean,
63
releaseOwnership: () => boolean,
packages/shared/ReactTypes.js
+8
-8
@@ -14,7 +14,7 @@ export type ReactNode =
14
| ReactFragment
15
| ReactProvider<any>
16
| ReactConsumer<any>
17
- | ReactEventComponent<any, any, any>;
17
+ | ReactEventComponent<any, any>;
18
19
export type ReactEmpty = null | void | boolean;
20
@@ -80,20 +80,20 @@ export type RefObject = {|
80
current: any,
81
|};
82
83
-export type ReactEventComponentInstance<T, E, C> = {|
83
+export type ReactEventComponentInstance<E, C> = {|
84
currentFiber: mixed,
85
isHook: boolean,
86
props: Object,
87
- responder: ReactEventResponder<T, E, C>,
87
+ responder: ReactEventResponder<E, C>,
88
rootEventTypes: null | Set<string>,
89
rootInstance: null | mixed,
90
state: Object,
91
|};
92
93
-export type ReactEventResponder<T, E, C> = {
93
+export type ReactEventResponder<E, C> = {
94
displayName: string,
95
- targetEventTypes?: Array<T>,
96
- rootEventTypes?: Array<T>,
95
+ targetEventTypes?: Array<string>,
96
+ rootEventTypes?: Array<string>,
97
getInitialState?: (props: Object) => Object,
98
allowMultipleHostChildren: boolean,
99
allowEventHooks: boolean,
@@ -104,9 +104,9 @@ export type ReactEventResponder<T, E, C> = {
104
onOwnershipChange?: (context: C, props: Object, state: Object) => void,
105
};
106
107
-export type ReactEventComponent<T, E, C> = {|
107
+export type ReactEventComponent<E, C> = {|
108
$$typeof: Symbol | number,
109
- responder: ReactEventResponder<T, E, C>,
109
+ responder: ReactEventResponder<E, C>,
110
|};
111
112
export opaque type EventPriority = 0 | 1 | 2;
packages/shared/createEventComponent.js
+3
-3
@@ -28,9 +28,9 @@ if (__DEV__) {
28
}
29
}
30
31
-export default function createEventComponent<T, E, C>(
32
- responder: ReactEventResponder<T, E, C>,
33
-): ReactEventComponent<T, E, C> {
31
+export default function createEventComponent<E, C>(
32
+ responder: ReactEventResponder<E, C>,
33
+): ReactEventComponent<E, C> {
34
// We use responder as a Map key later on. When we have a bad
35
// polyfill, then we can't use it as a key as the polyfill tries
36
// to add a property to the object.
packages/shared/endsWith.js
new
+13
@@ -0,0 +1,13 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+export default function endsWith(subject: string, search: string): boolean {
11
+ const length = subject.length;
12
+ return subject.substring(length - search.length, length) === search;
13
+}