@samitouri / QOS-React-2 / commits / 32bb44c80a

Clean up modern plugins to remove dead code (#18639)

Dominic Gannaway committed Apr 16, 2020 at 20:10 UTC 32bb44c80ac64b3c96fa9e03b6ecb6dce6a0de6e
14 files changed +345 -407
packages/react-dom/src/events/DOMModernPluginEventSystem.js
+310 -3
@@ -33,7 +33,12 @@ import {
33 USE_EVENT_SYSTEM,
34 } from './EventSystemFlags';
35
36 -import {HostRoot, HostPortal} from 'react-reconciler/src/ReactWorkTags';
36 +import {
37 + HostRoot,
38 + HostPortal,
39 + ScopeComponent,
40 + HostComponent,
41 +} from 'react-reconciler/src/ReactWorkTags';
42
43 import {
44 addTrappedEventListener,
@@ -86,10 +91,12 @@ import {
91 import {COMMENT_NODE} from '../shared/HTMLNodeType';
92 import {topLevelEventsToDispatchConfig} from './DOMEventProperties';
93 import {batchedEventUpdates} from './ReactDOMUpdateBatching';
94 +import getListener from './getListener';
95
96 import {
97 enableLegacyFBSupport,
98 enableUseEventAPI,
99 + enableScopeAPI,
100 } from 'shared/ReactFeatureFlags';
101 import {
102 invokeGuardedCallbackAndCatchFirstError,
@@ -153,7 +160,7 @@ const isArray = Array.isArray;
160 const PossiblyWeakMap = ((typeof WeakMap === 'function' ? WeakMap : Map): any);
161
162 // $FlowFixMe: Flow cannot handle polymorphic WeakMaps
156 -export const eventTargetEventListenerStore: WeakMap<
163 +const eventTargetEventListenerStore: WeakMap<
164 EventTarget,
165 Map<
166 DOMTopLevelEventType,
@@ -162,7 +169,7 @@ export const eventTargetEventListenerStore: WeakMap<
169 > = new PossiblyWeakMap();
170
171 // $FlowFixMe: Flow cannot handle polymorphic WeakMaps
165 -export const reactScopeListenerStore: WeakMap<
172 +const reactScopeListenerStore: WeakMap<
173 ReactScopeMethods,
174 Map<
175 DOMTopLevelEventType,
@@ -672,3 +679,303 @@ export function detachListenerFromReactScope(listener: ReactDOMListener): void {
679 }
680 }
681 }
682 +
683 +export function accumulateTwoPhaseListeners(
684 + event: ReactSyntheticEvent,
685 + accumulateUseEventListeners?: boolean,
686 +): void {
687 + const phasedRegistrationNames = event.dispatchConfig.phasedRegistrationNames;
688 + const dispatchListeners = [];
689 + const dispatchInstances: Array<Fiber | null> = [];
690 + const dispatchCurrentTargets = [];
691 +
692 + const {bubbled, captured} = phasedRegistrationNames;
693 + // If we are not handling EventTarget only phase, then we're doing the
694 + // usual two phase accumulation using the React fiber tree to pick up
695 + // all relevant useEvent and on* prop events.
696 + let instance = event._targetInst;
697 + let lastHostComponent = null;
698 +
699 + // Accumulate all instances and listeners via the target -> root path.
700 + while (instance !== null) {
701 + const {stateNode, tag} = instance;
702 + // Handle listeners that are on HostComponents (i.e. <div>)
703 + if (tag === HostComponent && stateNode !== null) {
704 + const currentTarget = stateNode;
705 + lastHostComponent = currentTarget;
706 + // For useEvent listenrs
707 + if (enableUseEventAPI && accumulateUseEventListeners) {
708 + // useEvent event listeners
709 + const targetType = event.type;
710 + const listeners = getListenersFromTarget(currentTarget);
711 +
712 + if (listeners !== null) {
713 + const listenersArr = Array.from(listeners);
714 + for (let i = 0; i < listenersArr.length; i++) {
715 + const listener = listenersArr[i];
716 + const {
717 + callback,
718 + event: {capture, type},
719 + } = listener;
720 + if (type === targetType) {
721 + if (capture === true) {
722 + dispatchListeners.unshift(callback);
723 + dispatchInstances.unshift(instance);
724 + dispatchCurrentTargets.unshift(currentTarget);
725 + } else {
726 + dispatchListeners.push(callback);
727 + dispatchInstances.push(instance);
728 + dispatchCurrentTargets.push(currentTarget);
729 + }
730 + }
731 + }
732 + }
733 + }
734 + // Standard React on* listeners, i.e. onClick prop
735 + if (captured !== null) {
736 + const captureListener = getListener(instance, captured);
737 + if (captureListener != null) {
738 + // Capture listeners/instances should go at the start, so we
739 + // unshift them to the start of the array.
740 + dispatchListeners.unshift(captureListener);
741 + dispatchInstances.unshift(instance);
742 + dispatchCurrentTargets.unshift(currentTarget);
743 + }
744 + }
745 + if (bubbled !== null) {
746 + const bubbleListener = getListener(instance, bubbled);
747 + if (bubbleListener != null) {
748 + // Bubble listeners/instances should go at the end, so we
749 + // push them to the end of the array.
750 + dispatchListeners.push(bubbleListener);
751 + dispatchInstances.push(instance);
752 + dispatchCurrentTargets.push(currentTarget);
753 + }
754 + }
755 + }
756 + if (
757 + enableUseEventAPI &&
758 + enableScopeAPI &&
759 + accumulateUseEventListeners &&
760 + tag === ScopeComponent &&
761 + lastHostComponent !== null
762 + ) {
763 + const reactScope = stateNode.methods;
764 + const eventTypeMap = reactScopeListenerStore.get(reactScope);
765 + if (eventTypeMap !== undefined) {
766 + const type = ((event.type: any): DOMTopLevelEventType);
767 + const listeners = eventTypeMap.get(type);
768 + if (listeners !== undefined) {
769 + const captureListeners = Array.from(listeners.captured);
770 + const bubbleListeners = Array.from(listeners.bubbled);
771 + const lastCurrentTarget = ((lastHostComponent: any): Element);
772 +
773 + for (let i = 0; i < captureListeners.length; i++) {
774 + const listener = captureListeners[i];
775 + const {callback} = listener;
776 + dispatchListeners.unshift(callback);
777 + dispatchInstances.unshift(instance);
778 + dispatchCurrentTargets.unshift(lastCurrentTarget);
779 + }
780 + for (let i = 0; i < bubbleListeners.length; i++) {
781 + const listener = bubbleListeners[i];
782 + const {callback} = listener;
783 + dispatchListeners.push(callback);
784 + dispatchInstances.push(instance);
785 + dispatchCurrentTargets.push(lastCurrentTarget);
786 + }
787 + }
788 + }
789 + }
790 + instance = instance.return;
791 + }
792 +
793 + // To prevent allocation to the event unless we actually
794 + // have listeners we check the length of one of the arrays.
795 + if (dispatchListeners.length > 0) {
796 + event._dispatchListeners = dispatchListeners;
797 + event._dispatchInstances = dispatchInstances;
798 + event._dispatchCurrentTargets = dispatchCurrentTargets;
799 + }
800 +}
801 +
802 +export function accumulateEventTargetListeners(
803 + event: ReactSyntheticEvent,
804 + currentTarget: EventTarget,
805 +): void {
806 + const dispatchListeners = [];
807 + const dispatchInstances: Array<Fiber | null> = [];
808 + const dispatchCurrentTargets = [];
809 +
810 + const eventTypeMap = eventTargetEventListenerStore.get(currentTarget);
811 + if (eventTypeMap !== undefined) {
812 + const type = ((event.type: any): DOMTopLevelEventType);
813 + const listeners = eventTypeMap.get(type);
814 + if (listeners !== undefined) {
815 + const isCapturePhase = (event: any).eventPhase === 1;
816 +
817 + if (isCapturePhase) {
818 + const captureListeners = Array.from(listeners.captured);
819 +
820 + for (let i = captureListeners.length - 1; i >= 0; i--) {
821 + const listener = captureListeners[i];
822 + const {callback} = listener;
823 + dispatchListeners.push(callback);
824 + // EventTarget listeners do not have instances, as there
825 + // is no backing Fiber instance for them (window, document etc).
826 + dispatchInstances.push(null);
827 + dispatchCurrentTargets.push(currentTarget);
828 + }
829 + } else {
830 + const bubbleListeners = Array.from(listeners.bubbled);
831 +
832 + for (let i = 0; i < bubbleListeners.length; i++) {
833 + const listener = bubbleListeners[i];
834 + const {callback} = listener;
835 + dispatchListeners.push(callback);
836 + // EventTarget listeners do not have instances, as there
837 + // is no backing Fiber instance for them (window, document etc).
838 + dispatchInstances.push(null);
839 + dispatchCurrentTargets.push(currentTarget);
840 + }
841 + }
842 + }
843 + }
844 + // To prevent allocation to the event unless we actually
845 + // have listeners we check the length of one of the arrays.
846 + if (dispatchListeners.length > 0) {
847 + event._dispatchListeners = dispatchListeners;
848 + event._dispatchInstances = dispatchInstances;
849 + event._dispatchCurrentTargets = dispatchCurrentTargets;
850 + }
851 +}
852 +
853 +function getParent(inst: Fiber | null): Fiber | null {
854 + if (inst === null) {
855 + return null;
856 + }
857 + do {
858 + inst = inst.return;
859 + // TODO: If this is a HostRoot we might want to bail out.
860 + // That is depending on if we want nested subtrees (layers) to bubble
861 + // events to their parent. We could also go through parentNode on the
862 + // host node but that wouldn't work for React Native and doesn't let us
863 + // do the portal feature.
864 + } while (inst && inst.tag !== HostComponent);
865 + if (inst) {
866 + return inst;
867 + }
868 + return null;
869 +}
870 +
871 +/**
872 + * Return the lowest common ancestor of A and B, or null if they are in
873 + * different trees.
874 + */
875 +function getLowestCommonAncestor(instA: Fiber, instB: Fiber): Fiber | null {
876 + let nodeA = instA;
877 + let nodeB = instB;
878 + let depthA = 0;
879 + for (let tempA = nodeA; tempA; tempA = getParent(tempA)) {
880 + depthA++;
881 + }
882 + let depthB = 0;
883 + for (let tempB = nodeB; tempB; tempB = getParent(tempB)) {
884 + depthB++;
885 + }
886 +
887 + // If A is deeper, crawl up.
888 + while (depthA - depthB > 0) {
889 + nodeA = getParent(nodeA);
890 + depthA--;
891 + }
892 +
893 + // If B is deeper, crawl up.
894 + while (depthB - depthA > 0) {
895 + nodeB = getParent(nodeB);
896 + depthB--;
897 + }
898 +
899 + // Walk in lockstep until we find a match.
900 + let depth = depthA;
901 + while (depth--) {
902 + if (nodeA === nodeB || (nodeB !== null && nodeA === nodeB.alternate)) {
903 + return nodeA;
904 + }
905 + nodeA = getParent(nodeA);
906 + nodeB = getParent(nodeB);
907 + }
908 + return null;
909 +}
910 +
911 +function accumulateEnterLeaveListenersForEvent(
912 + event: ReactSyntheticEvent,
913 + target: Fiber,
914 + common: Fiber | null,
915 + capture: boolean,
916 +): void {
917 + const registrationName = event.dispatchConfig.registrationName;
918 + if (registrationName === undefined) {
919 + return;
920 + }
921 + const dispatchListeners = [];
922 + const dispatchInstances: Array<Fiber | null> = [];
923 + const dispatchCurrentTargets = [];
924 +
925 + let instance = target;
926 + while (instance !== null) {
927 + if (instance === common) {
928 + break;
929 + }
930 + const {alternate, stateNode, tag} = instance;
931 + if (alternate !== null && alternate === common) {
932 + break;
933 + }
934 + if (tag === HostComponent && stateNode !== null) {
935 + const currentTarget = stateNode;
936 + if (capture) {
937 + const captureListener = getListener(instance, registrationName);
938 + if (captureListener != null) {
939 + // Capture listeners/instances should go at the start, so we
940 + // unshift them to the start of the array.
941 + dispatchListeners.unshift(captureListener);
942 + dispatchInstances.unshift(instance);
943 + dispatchCurrentTargets.unshift(currentTarget);
944 + }
945 + } else {
946 + const bubbleListener = getListener(instance, registrationName);
947 + if (bubbleListener != null) {
948 + // Bubble listeners/instances should go at the end, so we
949 + // push them to the end of the array.
950 + dispatchListeners.push(bubbleListener);
951 + dispatchInstances.push(instance);
952 + dispatchCurrentTargets.push(currentTarget);
953 + }
954 + }
955 + }
956 + instance = instance.return;
957 + }
958 + // To prevent allocation to the event unless we actually
959 + // have listeners we check the length of one of the arrays.
960 + if (dispatchListeners.length > 0) {
961 + event._dispatchListeners = dispatchListeners;
962 + event._dispatchInstances = dispatchInstances;
963 + event._dispatchCurrentTargets = dispatchCurrentTargets;
964 + }
965 +}
966 +
967 +export function accumulateEnterLeaveListeners(
968 + leaveEvent: ReactSyntheticEvent,
969 + enterEvent: ReactSyntheticEvent,
970 + from: Fiber | null,
971 + to: Fiber | null,
972 +): void {
973 + const common = from && to ? getLowestCommonAncestor(from, to) : null;
974 +
975 + if (from !== null) {
976 + accumulateEnterLeaveListenersForEvent(leaveEvent, from, common, false);
977 + }
978 + if (to !== null) {
979 + accumulateEnterLeaveListenersForEvent(enterEvent, to, common, true);
980 + }
981 +}
packages/react-dom/src/events/accumulateEnterLeaveListeners.js deleted
-144
@@ -1,144 +0,0 @@
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 -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
11 -import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType';
12 -
13 -import {HostComponent} from 'react-reconciler/src/ReactWorkTags';
14 -import getListener from './getListener';
15 -
16 -function getParent(inst: Fiber | null): Fiber | null {
17 - if (inst === null) {
18 - return null;
19 - }
20 - do {
21 - inst = inst.return;
22 - // TODO: If this is a HostRoot we might want to bail out.
23 - // That is depending on if we want nested subtrees (layers) to bubble
24 - // events to their parent. We could also go through parentNode on the
25 - // host node but that wouldn't work for React Native and doesn't let us
26 - // do the portal feature.
27 - } while (inst && inst.tag !== HostComponent);
28 - if (inst) {
29 - return inst;
30 - }
31 - return null;
32 -}
33 -
34 -/**
35 - * Return the lowest common ancestor of A and B, or null if they are in
36 - * different trees.
37 - */
38 -function getLowestCommonAncestor(instA: Fiber, instB: Fiber): Fiber | null {
39 - let nodeA = instA;
40 - let nodeB = instB;
41 - let depthA = 0;
42 - for (let tempA = nodeA; tempA; tempA = getParent(tempA)) {
43 - depthA++;
44 - }
45 - let depthB = 0;
46 - for (let tempB = nodeB; tempB; tempB = getParent(tempB)) {
47 - depthB++;
48 - }
49 -
50 - // If A is deeper, crawl up.
51 - while (depthA - depthB > 0) {
52 - nodeA = getParent(nodeA);
53 - depthA--;
54 - }
55 -
56 - // If B is deeper, crawl up.
57 - while (depthB - depthA > 0) {
58 - nodeB = getParent(nodeB);
59 - depthB--;
60 - }
61 -
62 - // Walk in lockstep until we find a match.
63 - let depth = depthA;
64 - while (depth--) {
65 - if (nodeA === nodeB || (nodeB !== null && nodeA === nodeB.alternate)) {
66 - return nodeA;
67 - }
68 - nodeA = getParent(nodeA);
69 - nodeB = getParent(nodeB);
70 - }
71 - return null;
72 -}
73 -
74 -function accumulateEnterLeaveListenersForEvent(
75 - event: ReactSyntheticEvent,
76 - target: Fiber,
77 - common: Fiber | null,
78 - capture: boolean,
79 -): void {
80 - const registrationName = event.dispatchConfig.registrationName;
81 - if (registrationName === undefined) {
82 - return;
83 - }
84 - const dispatchListeners = [];
85 - const dispatchInstances: Array<Fiber | null> = [];
86 - const dispatchCurrentTargets = [];
87 -
88 - let instance = target;
89 - while (instance !== null) {
90 - if (instance === common) {
91 - break;
92 - }
93 - const {alternate, stateNode, tag} = instance;
94 - if (alternate !== null && alternate === common) {
95 - break;
96 - }
97 - if (tag === HostComponent && stateNode !== null) {
98 - const currentTarget = stateNode;
99 - if (capture) {
100 - const captureListener = getListener(instance, registrationName);
101 - if (captureListener != null) {
102 - // Capture listeners/instances should go at the start, so we
103 - // unshift them to the start of the array.
104 - dispatchListeners.unshift(captureListener);
105 - dispatchInstances.unshift(instance);
106 - dispatchCurrentTargets.unshift(currentTarget);
107 - }
108 - } else {
109 - const bubbleListener = getListener(instance, registrationName);
110 - if (bubbleListener != null) {
111 - // Bubble listeners/instances should go at the end, so we
112 - // push them to the end of the array.
113 - dispatchListeners.push(bubbleListener);
114 - dispatchInstances.push(instance);
115 - dispatchCurrentTargets.push(currentTarget);
116 - }
117 - }
118 - }
119 - instance = instance.return;
120 - }
121 - // To prevent allocation to the event unless we actually
122 - // have listeners we check the length of one of the arrays.
123 - if (dispatchListeners.length > 0) {
124 - event._dispatchListeners = dispatchListeners;
125 - event._dispatchInstances = dispatchInstances;
126 - event._dispatchCurrentTargets = dispatchCurrentTargets;
127 - }
128 -}
129 -
130 -export default function accumulateEnterLeaveListeners(
131 - leaveEvent: ReactSyntheticEvent,
132 - enterEvent: ReactSyntheticEvent,
133 - from: Fiber | null,
134 - to: Fiber | null,
135 -): void {
136 - const common = from && to ? getLowestCommonAncestor(from, to) : null;
137 -
138 - if (from !== null) {
139 - accumulateEnterLeaveListenersForEvent(leaveEvent, from, common, false);
140 - }
141 - if (to !== null) {
142 - accumulateEnterLeaveListenersForEvent(enterEvent, to, common, true);
143 - }
144 -}
packages/react-dom/src/events/accumulateEventTargetListeners.js deleted
-65
@@ -1,65 +0,0 @@
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 -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
11 -import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
12 -import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType';
13 -
14 -import {eventTargetEventListenerStore} from './DOMModernPluginEventSystem';
15 -
16 -export default function accumulateEventTargetListeners(
17 - event: ReactSyntheticEvent,
18 - currentTarget: EventTarget,
19 -): void {
20 - const dispatchListeners = [];
21 - const dispatchInstances: Array<Fiber | null> = [];
22 - const dispatchCurrentTargets = [];
23 -
24 - const eventTypeMap = eventTargetEventListenerStore.get(currentTarget);
25 - if (eventTypeMap !== undefined) {
26 - const type = ((event.type: any): DOMTopLevelEventType);
27 - const listeners = eventTypeMap.get(type);
28 - if (listeners !== undefined) {
29 - const isCapturePhase = (event: any).eventPhase === 1;
30 -
31 - if (isCapturePhase) {
32 - const captureListeners = Array.from(listeners.captured);
33 -
34 - for (let i = captureListeners.length - 1; i >= 0; i--) {
35 - const listener = captureListeners[i];
36 - const {callback} = listener;
37 - dispatchListeners.push(callback);
38 - // EventTarget listeners do not have instances, as there
39 - // is no backing Fiber instance for them (window, document etc).
40 - dispatchInstances.push(null);
41 - dispatchCurrentTargets.push(currentTarget);
42 - }
43 - } else {
44 - const bubbleListeners = Array.from(listeners.bubbled);
45 -
46 - for (let i = 0; i < bubbleListeners.length; i++) {
47 - const listener = bubbleListeners[i];
48 - const {callback} = listener;
49 - dispatchListeners.push(callback);
50 - // EventTarget listeners do not have instances, as there
51 - // is no backing Fiber instance for them (window, document etc).
52 - dispatchInstances.push(null);
53 - dispatchCurrentTargets.push(currentTarget);
54 - }
55 - }
56 - }
57 - }
58 - // To prevent allocation to the event unless we actually
59 - // have listeners we check the length of one of the arrays.
60 - if (dispatchListeners.length > 0) {
61 - event._dispatchListeners = dispatchListeners;
62 - event._dispatchInstances = dispatchInstances;
63 - event._dispatchCurrentTargets = dispatchCurrentTargets;
64 - }
65 -}
packages/react-dom/src/events/accumulateTwoPhaseListeners.js deleted
-150
@@ -1,150 +0,0 @@
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 -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
11 -import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
12 -import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType';
13 -
14 -import {
15 - HostComponent,
16 - ScopeComponent,
17 -} from 'react-reconciler/src/ReactWorkTags';
18 -import {
19 - enableUseEventAPI,
20 - enableScopeAPI,
21 - enableModernEventSystem,
22 -} from 'shared/ReactFeatureFlags';
23 -
24 -import getListener from './getListener';
25 -import {getListenersFromTarget} from '../client/ReactDOMComponentTree';
26 -import {reactScopeListenerStore} from './DOMModernPluginEventSystem';
27 -
28 -export default function accumulateTwoPhaseListeners(
29 - event: ReactSyntheticEvent,
30 - accumulateUseEventListeners?: boolean,
31 -): void {
32 - const phasedRegistrationNames = event.dispatchConfig.phasedRegistrationNames;
33 - const dispatchListeners = [];
34 - const dispatchInstances: Array<Fiber | null> = [];
35 - const dispatchCurrentTargets = [];
36 -
37 - const {bubbled, captured} = phasedRegistrationNames;
38 - // If we are not handling EventTarget only phase, then we're doing the
39 - // usual two phase accumulation using the React fiber tree to pick up
40 - // all relevant useEvent and on* prop events.
41 - let instance = event._targetInst;
42 - let lastHostComponent = null;
43 -
44 - // Accumulate all instances and listeners via the target -> root path.
45 - while (instance !== null) {
46 - const {stateNode, tag} = instance;
47 - // Handle listeners that are on HostComponents (i.e. <div>)
48 - if (tag === HostComponent && stateNode !== null) {
49 - const currentTarget = stateNode;
50 - lastHostComponent = currentTarget;
51 - // For useEvent listenrs
52 - if (
53 - enableModernEventSystem &&
54 - enableUseEventAPI &&
55 - accumulateUseEventListeners
56 - ) {
57 - // useEvent event listeners
58 - const targetType = event.type;
59 - const listeners = getListenersFromTarget(currentTarget);
60 -
61 - if (listeners !== null) {
62 - const listenersArr = Array.from(listeners);
63 - for (let i = 0; i < listenersArr.length; i++) {
64 - const listener = listenersArr[i];
65 - const {
66 - callback,
67 - event: {capture, type},
68 - } = listener;
69 - if (type === targetType) {
70 - if (capture === true) {
71 - dispatchListeners.unshift(callback);
72 - dispatchInstances.unshift(instance);
73 - dispatchCurrentTargets.unshift(currentTarget);
74 - } else {
75 - dispatchListeners.push(callback);
76 - dispatchInstances.push(instance);
77 - dispatchCurrentTargets.push(currentTarget);
78 - }
79 - }
80 - }
81 - }
82 - }
83 - // Standard React on* listeners, i.e. onClick prop
84 - if (captured !== null) {
85 - const captureListener = getListener(instance, captured);
86 - if (captureListener != null) {
87 - // Capture listeners/instances should go at the start, so we
88 - // unshift them to the start of the array.
89 - dispatchListeners.unshift(captureListener);
90 - dispatchInstances.unshift(instance);
91 - dispatchCurrentTargets.unshift(currentTarget);
92 - }
93 - }
94 - if (bubbled !== null) {
95 - const bubbleListener = getListener(instance, bubbled);
96 - if (bubbleListener != null) {
97 - // Bubble listeners/instances should go at the end, so we
98 - // push them to the end of the array.
99 - dispatchListeners.push(bubbleListener);
100 - dispatchInstances.push(instance);
101 - dispatchCurrentTargets.push(currentTarget);
102 - }
103 - }
104 - }
105 - if (
106 - enableModernEventSystem &&
107 - enableUseEventAPI &&
108 - enableScopeAPI &&
109 - accumulateUseEventListeners &&
110 - tag === ScopeComponent &&
111 - lastHostComponent !== null
112 - ) {
113 - const reactScope = stateNode.methods;
114 - const eventTypeMap = reactScopeListenerStore.get(reactScope);
115 - if (eventTypeMap !== undefined) {
116 - const type = ((event.type: any): DOMTopLevelEventType);
117 - const listeners = eventTypeMap.get(type);
118 - if (listeners !== undefined) {
119 - const captureListeners = Array.from(listeners.captured);
120 - const bubbleListeners = Array.from(listeners.bubbled);
121 - const lastCurrentTarget = ((lastHostComponent: any): Element);
122 -
123 - for (let i = 0; i < captureListeners.length; i++) {
124 - const listener = captureListeners[i];
125 - const {callback} = listener;
126 - dispatchListeners.unshift(callback);
127 - dispatchInstances.unshift(instance);
128 - dispatchCurrentTargets.unshift(lastCurrentTarget);
129 - }
130 - for (let i = 0; i < bubbleListeners.length; i++) {
131 - const listener = bubbleListeners[i];
132 - const {callback} = listener;
133 - dispatchListeners.push(callback);
134 - dispatchInstances.push(instance);
135 - dispatchCurrentTargets.push(lastCurrentTarget);
136 - }
137 - }
138 - }
139 - }
140 - instance = instance.return;
141 - }
142 -
143 - // To prevent allocation to the event unless we actually
144 - // have listeners we check the length of one of the arrays.
145 - if (dispatchListeners.length > 0) {
146 - event._dispatchListeners = dispatchListeners;
147 - event._dispatchInstances = dispatchInstances;
148 - event._dispatchCurrentTargets = dispatchCurrentTargets;
149 - }
150 -}
packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js
+1 -1
@@ -28,7 +28,7 @@ import {
28 } from '../FallbackCompositionState';
29 import SyntheticCompositionEvent from '../SyntheticCompositionEvent';
30 import SyntheticInputEvent from '../SyntheticInputEvent';
31 -import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners';
31 +import {accumulateTwoPhaseListeners} from '../DOMModernPluginEventSystem';
32
33 const END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
34 const START_KEYCODE = 229;
packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js
+6 -12
@@ -5,7 +5,6 @@
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 -import {runEventsInBatch} from 'legacy-events/EventBatching';
8 import SyntheticEvent from 'legacy-events/SyntheticEvent';
9 import isTextInputElement from '../isTextInputElement';
10 import {canUseDOM} from 'shared/ExecutionEnvironment';
@@ -27,13 +26,12 @@ import {updateValueIfChanged} from '../../client/inputValueTracking';
26 import {setDefaultValue} from '../../client/ReactDOMInput';
27 import {enqueueStateRestore} from '../ReactDOMControlledComponent';
28
30 -import {
31 - disableInputAttributeSyncing,
32 - enableModernEventSystem,
33 -} from 'shared/ReactFeatureFlags';
34 -import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners';
29 +import {disableInputAttributeSyncing} from 'shared/ReactFeatureFlags';
30 import {batchedUpdates} from '../ReactDOMUpdateBatching';
36 -import {dispatchEventsInBatch} from '../DOMModernPluginEventSystem';
31 +import {
32 + dispatchEventsInBatch,
33 + accumulateTwoPhaseListeners,
34 +} from '../DOMModernPluginEventSystem';
35
36 const eventTypes = {
37 change: {
@@ -105,11 +103,7 @@ function manualDispatchChangeEvent(nativeEvent) {
103 }
104
105 function runEventInBatch(event) {
108 - if (enableModernEventSystem) {
109 - dispatchEventsInBatch([event]);
110 - } else {
111 - runEventsInBatch(event);
112 - }
106 + dispatchEventsInBatch([event]);
107 }
108
109 function getInstIfValueChanged(targetInst) {
packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js
+9 -29
@@ -11,20 +11,17 @@ import {
11 TOP_POINTER_OUT,
12 TOP_POINTER_OVER,
13 } from '../DOMTopLevelEventTypes';
14 -import {
15 - IS_REPLAYED,
16 - IS_FIRST_ANCESTOR,
17 -} from 'react-dom/src/events/EventSystemFlags';
14 +import {IS_REPLAYED} from 'react-dom/src/events/EventSystemFlags';
15 import SyntheticMouseEvent from '../SyntheticMouseEvent';
16 import SyntheticPointerEvent from '../SyntheticPointerEvent';
17 import {
18 getClosestInstanceFromNode,
19 getNodeFromInstance,
20 } from '../../client/ReactDOMComponentTree';
21 +import {accumulateEnterLeaveListeners} from '../DOMModernPluginEventSystem';
22 +
23 import {HostComponent, HostText} from 'react-reconciler/src/ReactWorkTags';
24 import {getNearestMountedFiber} from 'react-reconciler/src/ReactFiberTreeReflection';
26 -import {enableModernEventSystem} from 'shared/ReactFeatureFlags';
27 -import accumulateEnterLeaveListeners from '../accumulateEnterLeaveListeners';
25
26 const eventTypes = {
27 mouseEnter: {
@@ -70,20 +67,12 @@ const EnterLeaveEventPlugin = {
67 if (isOverEvent && (eventSystemFlags & IS_REPLAYED) === 0) {
68 const related = nativeEvent.relatedTarget || nativeEvent.fromElement;
69 if (related) {
73 - if (enableModernEventSystem) {
74 - // Due to the fact we don't add listeners to the document with the
75 - // modern event system and instead attach listeners to roots, we
76 - // need to handle the over event case. To ensure this, we just need to
77 - // make sure the node that we're coming from is managed by React.
78 - const inst = getClosestInstanceFromNode(related);
79 - if (inst !== null) {
80 - return null;
81 - }
82 - } else {
83 - // If this is an over event with a target, then we've already dispatched
84 - // the event in the out event of the other target. If this is replayed,
85 - // then it's because we couldn't dispatch against this target previously
86 - // so we have to do it now instead.
70 + // Due to the fact we don't add listeners to the document with the
71 + // modern event system and instead attach listeners to roots, we
72 + // need to handle the over event case. To ensure this, we just need to
73 + // make sure the node that we're coming from is managed by React.
74 + const inst = getClosestInstanceFromNode(related);
75 + if (inst !== null) {
76 return null;
77 }
78 }
@@ -176,15 +165,6 @@ const EnterLeaveEventPlugin = {
165
166 accumulateEnterLeaveListeners(leave, enter, from, to);
167
179 - if (!enableModernEventSystem) {
180 - // If we are not processing the first ancestor, then we
181 - // should not process the same nativeEvent again, as we
182 - // will have already processed it in the first ancestor.
183 - if ((eventSystemFlags & IS_FIRST_ANCESTOR) === 0) {
184 - return [leave];
185 - }
186 - }
187 -
168 return [leave, enter];
169 },
170 };
packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js
+1 -1
@@ -26,7 +26,7 @@ import {getNodeFromInstance} from '../../client/ReactDOMComponentTree';
26 import {hasSelectionCapabilities} from '../../client/ReactInputSelection';
27 import {DOCUMENT_NODE} from '../../shared/HTMLNodeType';
28 import {isListeningToAllDependencies} from '../DOMEventListenerMap';
29 -import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners';
29 +import {accumulateTwoPhaseListeners} from '../DOMModernPluginEventSystem';
30
31 const skipSelectionChangeEvent =
32 canUseDOM && 'documentMode' in document && document.documentMode <= 11;
packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js
+4 -2
@@ -24,6 +24,10 @@ import {
24 topLevelEventsToDispatchConfig,
25 simpleEventPluginEventTypes,
26 } from '../DOMEventProperties';
27 +import {
28 + accumulateEventTargetListeners,
29 + accumulateTwoPhaseListeners,
30 +} from '../DOMModernPluginEventSystem';
31
32 import SyntheticAnimationEvent from '../SyntheticAnimationEvent';
33 import SyntheticClipboardEvent from '../SyntheticClipboardEvent';
@@ -37,8 +41,6 @@ import SyntheticTransitionEvent from '../SyntheticTransitionEvent';
41 import SyntheticUIEvent from '../SyntheticUIEvent';
42 import SyntheticWheelEvent from '../SyntheticWheelEvent';
43 import getEventCharCode from '../getEventCharCode';
40 -import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners';
41 -import accumulateEventTargetListeners from '../accumulateEventTargetListeners';
44
45 import {enableUseEventAPI} from 'shared/ReactFeatureFlags';
46
packages/react-dom/src/events/plugins/__tests__/ModernBeforeInputEventPlugin-test.internal.js
+3
@@ -11,6 +11,7 @@
11
12 let React;
13 let ReactDOM;
14 +let ReactFeatureFlags;
15
16 describe('BeforeInputEventPlugin', () => {
17 let container;
@@ -77,6 +78,8 @@ describe('BeforeInputEventPlugin', () => {
78 }
79
80 beforeEach(() => {
81 + ReactFeatureFlags = require('shared/ReactFeatureFlags');
82 + ReactFeatureFlags.enableModernEventSystem = true;
83 React = require('react');
84 container = document.createElement('div');
85 document.body.appendChild(container);
packages/react-dom/src/events/plugins/__tests__/ModernChangeEventPlugin-test.internal.js
+2
@@ -470,6 +470,7 @@ describe('ChangeEventPlugin', () => {
470 beforeEach(() => {
471 jest.resetModules();
472 ReactFeatureFlags = require('shared/ReactFeatureFlags');
473 + ReactFeatureFlags.enableModernEventSystem = true;
474
475 React = require('react');
476 ReactDOM = require('react-dom');
@@ -720,6 +721,7 @@ describe('ChangeEventPlugin', () => {
721 it('mouse enter/leave should be user-blocking but not discrete', async () => {
722 // This is currently behind a feature flag
723 jest.resetModules();
724 + ReactFeatureFlags.enableModernEventSystem = true;
725 React = require('react');
726 ReactDOM = require('react-dom');
727 TestUtils = require('react-dom/test-utils');
packages/react-dom/src/events/plugins/__tests__/ModernEnterLeaveEventPlugin-test.internal.js
+3
@@ -11,6 +11,7 @@
11
12 let React;
13 let ReactDOM;
14 +let ReactFeatureFlags;
15
16 describe('EnterLeaveEventPlugin', () => {
17 let container;
@@ -18,6 +19,8 @@ describe('EnterLeaveEventPlugin', () => {
19 beforeEach(() => {
20 jest.resetModules();
21
22 + ReactFeatureFlags = require('shared/ReactFeatureFlags');
23 + ReactFeatureFlags.enableModernEventSystem = true;
24 React = require('react');
25 ReactDOM = require('react-dom');
26
packages/react-dom/src/events/plugins/__tests__/ModernSelectEventPlugin-test.internal.js
+3
@@ -11,11 +11,14 @@
11
12 let React;
13 let ReactDOM;
14 +let ReactFeatureFlags;
15
16 describe('SelectEventPlugin', () => {
17 let container;
18
19 beforeEach(() => {
20 + ReactFeatureFlags = require('shared/ReactFeatureFlags');
21 + ReactFeatureFlags.enableModernEventSystem = true;
22 React = require('react');
23 ReactDOM = require('react-dom');
24
packages/react-dom/src/events/plugins/__tests__/ModernSimpleEventPlugin-test.internal.js
+3
@@ -13,6 +13,7 @@ describe('SimpleEventPlugin', function() {
13 let React;
14 let ReactDOM;
15 let Scheduler;
16 + let ReactFeatureFlags;
17
18 let onClick;
19 let container;
@@ -36,6 +37,8 @@ describe('SimpleEventPlugin', function() {
37
38 beforeEach(function() {
39 jest.resetModules();
40 + ReactFeatureFlags = require('shared/ReactFeatureFlags');
41 + ReactFeatureFlags.enableModernEventSystem = true;
42 React = require('react');
43 ReactDOM = require('react-dom');
44 Scheduler = require('scheduler');