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');