@samitouri / QOS-React-2 / commits / 67e3f3fb6e

[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 +}