@samitouri / QOS-React-2 / commits / 991c3b8193

Make event config an implementation detail of each plugin (#19236)

* Merge two variables with same purpose * Replace dispatchConfig with _reactName on event object

Dan Abramov committed Jul 2, 2020 at 00:03 UTC 991c3b8193bd6bcc53c23c79eddc659eb41a4c3a
13 files changed +71 -176
packages/react-dom/src/client/ReactDOMComponent.js
+6 -6
@@ -8,7 +8,7 @@
8 */
9
10 import {
11 - registrationNames,
11 + registrationNameDependencies,
12 possibleRegistrationNames,
13 } from '../events/EventPluginRegistry';
14 import {canUseDOM} from 'shared/ExecutionEnvironment';
@@ -133,7 +133,7 @@ if (__DEV__) {
133 validateARIAProperties(type, props);
134 validateInputProperties(type, props);
135 validateUnknownProperties(type, props, {
136 - registrationNames,
136 + registrationNameDependencies,
137 possibleRegistrationNames,
138 });
139 };
@@ -356,7 +356,7 @@ function setInitialDOMProperties(
356 // We could have excluded it in the property list instead of
357 // adding a special case here, but then it wouldn't be emitted
358 // on server rendering (but we *do* want to emit it in SSR).
359 - } else if (registrationNames.hasOwnProperty(propKey)) {
359 + } else if (registrationNameDependencies.hasOwnProperty(propKey)) {
360 if (nextProp != null) {
361 if (__DEV__ && typeof nextProp !== 'function') {
362 warnForInvalidEventListener(propKey, nextProp);
@@ -694,7 +694,7 @@ export function diffProperties(
694 // Noop
695 } else if (propKey === AUTOFOCUS) {
696 // Noop. It doesn't work on updates anyway.
697 - } else if (registrationNames.hasOwnProperty(propKey)) {
697 + } else if (registrationNameDependencies.hasOwnProperty(propKey)) {
698 // This is a special case. If any listener updates we need to ensure
699 // that the "current" fiber pointer gets updated so we need a commit
700 // to update this element.
@@ -781,7 +781,7 @@ export function diffProperties(
781 propKey === SUPPRESS_HYDRATION_WARNING
782 ) {
783 // Noop
784 - } else if (registrationNames.hasOwnProperty(propKey)) {
784 + } else if (registrationNameDependencies.hasOwnProperty(propKey)) {
785 if (nextProp != null) {
786 // We eagerly listen to this even though we haven't committed yet.
787 if (__DEV__ && typeof nextProp !== 'function') {
@@ -978,7 +978,7 @@ export function diffHydratedProperties(
978 updatePayload = [CHILDREN, '' + nextProp];
979 }
980 }
981 - } else if (registrationNames.hasOwnProperty(propKey)) {
981 + } else if (registrationNameDependencies.hasOwnProperty(propKey)) {
982 if (nextProp != null) {
983 if (__DEV__ && typeof nextProp !== 'function') {
984 warnForInvalidEventListener(propKey, nextProp);
packages/react-dom/src/events/DOMEventProperties.js
+5 -9
@@ -13,10 +13,6 @@ import type {
13 DOMTopLevelEventType,
14 } from '../events/TopLevelEventTypes';
15 import type {EventTypes} from '../events/PluginModuleType';
16 -import type {
17 - DispatchConfig,
18 - CustomDispatchConfig,
19 -} from '../events/ReactSyntheticEventType';
16
17 import * as DOMTopLevelEventTypes from './DOMTopLevelEventTypes';
18 import {
@@ -35,9 +31,9 @@ import {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags';
31 // update the below line.
32 export const simpleEventPluginEventTypes: EventTypes = {};
33
38 -export const topLevelEventsToDispatchConfig: Map<
34 +export const topLevelEventsToReactNames: Map<
35 TopLevelType,
40 - DispatchConfig | CustomDispatchConfig,
36 + string | null,
37 > = new Map();
38
39 const eventPriorities = new Map();
@@ -167,8 +163,8 @@ const continuousPairsForSimpleEventPlugin = [
163 * },
164 * ...
165 * };
170 - * topLevelEventsToDispatchConfig = new Map([
171 - * [TOP_ABORT, { sameConfig }],
166 + * topLevelEventsToReactNames = new Map([
167 + * [TOP_ABORT, 'onAbort'],
168 * ]);
169 */
170
@@ -197,7 +193,7 @@ function processSimpleEventPluginPairsByPriority(
193 eventPriority: priority,
194 };
195 eventPriorities.set(topEvent, priority);
200 - topLevelEventsToDispatchConfig.set(topEvent, config);
196 + topLevelEventsToReactNames.set(topEvent, onEvent);
197 simpleEventPluginEventTypes[event] = config;
198 }
199 }
packages/react-dom/src/events/DOMModernPluginEventSystem.js
+9 -23
@@ -16,10 +16,7 @@ import type {
16 DispatchQueueItemPhase,
17 DispatchQueueItemPhaseEntry,
18 } from './PluginModuleType';
19 -import type {
20 - ReactSyntheticEvent,
21 - CustomDispatchConfig,
22 -} from './ReactSyntheticEventType';
19 +import type {ReactSyntheticEvent} from './ReactSyntheticEventType';
20 import type {
21 ElementListenerMap,
22 ElementListenerMapEntry,
@@ -113,7 +110,7 @@ import {
110 addEventCaptureListenerWithPassiveFlag,
111 } from './EventListener';
112 import {removeTrappedEventListener} from './DeprecatedDOMEventResponderSystem';
116 -import {topLevelEventsToDispatchConfig} from './DOMEventProperties';
113 +import {topLevelEventsToReactNames} from './DOMEventProperties';
114 import * as ModernBeforeInputEventPlugin from './plugins/ModernBeforeInputEventPlugin';
115 import * as ModernChangeEventPlugin from './plugins/ModernChangeEventPlugin';
116 import * as ModernEnterLeaveEventPlugin from './plugins/ModernEnterLeaveEventPlugin';
@@ -223,14 +220,6 @@ if (enableCreateEventHandleAPI) {
220 capturePhaseEvents.add(TOP_AFTER_BLUR);
221 }
222
226 -const emptyDispatchConfigForCustomEvents: CustomDispatchConfig = {
227 - customEvent: true,
228 - phasedRegistrationNames: {
229 - bubbled: null,
230 - captured: null,
231 - },
232 -};
233 -
223 function executeDispatch(
224 event: ReactSyntheticEvent,
225 listener: Function,
@@ -639,11 +628,11 @@ export function accumulateTwoPhaseListeners(
628 event: ReactSyntheticEvent,
629 accumulateEventHandleListeners?: boolean,
630 ): void {
642 - const phasedRegistrationNames = event.dispatchConfig.phasedRegistrationNames;
631 + const bubbled = event._reactName;
632 + const captured = bubbled !== null ? bubbled + 'Capture' : null;
633 const capturePhase: DispatchQueueItemPhase = [];
634 const bubblePhase: DispatchQueueItemPhase = [];
635
646 - const {bubbled, captured} = phasedRegistrationNames;
636 // If we are not handling EventTarget only phase, then we're doing the
637 // usual two phase accumulation using the React fiber tree to pick up
638 // all relevant useEvent and on* prop events.
@@ -826,7 +815,7 @@ function accumulateEnterLeaveListenersForEvent(
815 common: Fiber | null,
816 capture: boolean,
817 ): void {
829 - const registrationName = event.dispatchConfig.registrationName;
818 + const registrationName = event._reactName;
819 if (registrationName === undefined) {
820 return;
821 }
@@ -944,17 +933,14 @@ export function accumulateEventTargetListeners(
933 }
934
935 export function addEventTypeToDispatchConfig(type: DOMTopLevelEventType): void {
947 - const dispatchConfig = topLevelEventsToDispatchConfig.get(type);
948 - // If we don't have a dispatchConfig, then we're dealing with
936 + const reactName = topLevelEventsToReactNames.get(type);
937 + // If we don't have a reactName, then we're dealing with
938 // an event type that React does not know about (i.e. a custom event).
939 // We need to register an event config for this or the SimpleEventPlugin
940 // will not appropriately provide a SyntheticEvent, so we use out empty
941 // dispatch config for custom events.
953 - if (dispatchConfig === undefined) {
954 - topLevelEventsToDispatchConfig.set(
955 - type,
956 - emptyDispatchConfigForCustomEvents,
957 - );
942 + if (reactName === undefined) {
943 + topLevelEventsToReactNames.set(type, null);
944 }
945 }
946
packages/react-dom/src/events/EventPluginRegistry.js
+10 -14
@@ -10,13 +10,6 @@
10 import type {TopLevelType} from './TopLevelEventTypes';
11 import type {EventTypes} from './PluginModuleType';
12
13 -import invariant from 'shared/invariant';
14 -
15 -/**
16 - * Mapping from registration name to plugin module
17 - */
18 -export const registrationNames = {};
19 -
13 /**
14 * Mapping from registration name to event name
15 */
@@ -62,13 +55,16 @@ function publishRegistrationName(
55 registrationName: string,
56 dependencies: ?Array<TopLevelType>,
57 ): void {
65 - invariant(
66 - !registrationNames[registrationName],
67 - 'EventPluginRegistry: More than one plugin attempted to publish the same ' +
68 - 'registration name, `%s`.',
69 - registrationName,
70 - );
71 - registrationNames[registrationName] = true;
58 + if (__DEV__) {
59 + if (registrationNameDependencies[registrationName]) {
60 + console.error(
61 + 'EventPluginRegistry: More than one plugin attempted to publish the same ' +
62 + 'registration name, `%s`.',
63 + registrationName,
64 + );
65 + }
66 + }
67 +
68 registrationNameDependencies[registrationName] = dependencies;
69
70 if (__DEV__) {
packages/react-dom/src/events/ReactSyntheticEventType.js
+1 -10
@@ -22,21 +22,12 @@ export type DispatchConfig = {|
22 eventPriority?: EventPriority,
23 |};
24
25 -export type CustomDispatchConfig = {|
26 - phasedRegistrationNames: {|
27 - bubbled: null,
28 - captured: null,
29 - |},
30 - registrationName?: string,
31 - customEvent: true,
32 -|};
33 -
25 export type ReactSyntheticEvent = {|
35 - dispatchConfig: DispatchConfig | CustomDispatchConfig,
26 isPersistent: () => boolean,
27 isPropagationStopped: () => boolean,
28 _dispatchInstances?: null | Array<Fiber | null> | Fiber,
29 _dispatchListeners?: null | Array<Function> | Function,
30 + _reactName: string,
31 _targetInst: Fiber,
32 type: string,
33 currentTarget: null | EventTarget,
packages/react-dom/src/events/SyntheticEvent.js
+2 -12
@@ -48,19 +48,9 @@ function functionThatReturnsFalse() {
48 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
49 * normalizing browser quirks. Subclasses do not necessarily have to implement a
50 * DOM interface; custom application-specific events can also subclass this.
51 - *
52 - * @param {object} dispatchConfig Configuration used to dispatch this event.
53 - * @param {*} targetInst Marker identifying the event target.
54 - * @param {object} nativeEvent Native browser event.
55 - * @param {DOMEventTarget} nativeEventTarget Target node.
51 */
57 -function SyntheticEvent(
58 - dispatchConfig,
59 - targetInst,
60 - nativeEvent,
61 - nativeEventTarget,
62 -) {
63 - this.dispatchConfig = dispatchConfig;
52 +function SyntheticEvent(reactName, targetInst, nativeEvent, nativeEventTarget) {
53 + this._reactName = reactName;
54 this._targetInst = targetInst;
55 this.nativeEvent = nativeEvent;
56
packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js
+8 -8
@@ -140,11 +140,11 @@ function isKeypressCommand(nativeEvent) {
140 function getCompositionEventType(topLevelType) {
141 switch (topLevelType) {
142 case TOP_COMPOSITION_START:
143 - return eventTypes.compositionStart;
143 + return 'onCompositionStart';
144 case TOP_COMPOSITION_END:
145 - return eventTypes.compositionEnd;
145 + return 'onCompositionEnd';
146 case TOP_COMPOSITION_UPDATE:
147 - return eventTypes.compositionUpdate;
147 + return 'onCompositionUpdate';
148 }
149 }
150
@@ -237,10 +237,10 @@ function extractCompositionEvent(
237 eventType = getCompositionEventType(topLevelType);
238 } else if (!isComposing) {
239 if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
240 - eventType = eventTypes.compositionStart;
240 + eventType = 'onCompositionStart';
241 }
242 } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
243 - eventType = eventTypes.compositionEnd;
243 + eventType = 'onCompositionEnd';
244 }
245
246 if (!eventType) {
@@ -250,9 +250,9 @@ function extractCompositionEvent(
250 if (useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)) {
251 // The current composition is stored statically and must not be
252 // overwritten while composition continues.
253 - if (!isComposing && eventType === eventTypes.compositionStart) {
253 + if (!isComposing && eventType === 'onCompositionStart') {
254 isComposing = FallbackCompositionStateInitialize(nativeEventTarget);
255 - } else if (eventType === eventTypes.compositionEnd) {
255 + } else if (eventType === 'onCompositionEnd') {
256 if (isComposing) {
257 fallbackData = FallbackCompositionStateGetData();
258 }
@@ -430,7 +430,7 @@ function extractBeforeInputEvent(
430 }
431
432 const event = new SyntheticInputEvent(
433 - eventTypes.beforeInput,
433 + 'onBeforeInput',
434 null,
435 nativeEvent,
436 nativeEventTarget,
packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js
+1 -6
@@ -64,12 +64,7 @@ function createAndAccumulateChangeEvent(
64 nativeEvent,
65 target,
66 ) {
67 - const event = new SyntheticEvent(
68 - eventTypes.change,
69 - null,
70 - nativeEvent,
71 - target,
72 - );
67 + const event = new SyntheticEvent('onChange', null, nativeEvent, target);
68 event.type = 'change';
69 // Flag this event loop as needing state restore.
70 enqueueStateRestore(((target: any): Node));
packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js
+4 -4
@@ -126,16 +126,16 @@ function extractEvents(
126
127 if (topLevelType === TOP_MOUSE_OUT || topLevelType === TOP_MOUSE_OVER) {
128 eventInterface = SyntheticMouseEvent;
129 - leaveEventType = eventTypes.mouseLeave;
130 - enterEventType = eventTypes.mouseEnter;
129 + leaveEventType = 'onMouseLeave';
130 + enterEventType = 'onMouseEnter';
131 eventTypePrefix = 'mouse';
132 } else if (
133 topLevelType === TOP_POINTER_OUT ||
134 topLevelType === TOP_POINTER_OVER
135 ) {
136 eventInterface = SyntheticPointerEvent;
137 - leaveEventType = eventTypes.pointerLeave;
138 - enterEventType = eventTypes.pointerEnter;
137 + leaveEventType = 'onPointerLeave';
138 + enterEventType = 'onPointerEnter';
139 eventTypePrefix = 'pointer';
140 }
141
packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js
+1 -1
@@ -133,7 +133,7 @@ function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) {
133 lastSelection = currentSelection;
134
135 const syntheticEvent = new SyntheticEvent(
136 - eventTypes.select,
136 + 'onSelect',
137 null,
138 nativeEvent,
139 nativeEventTarget,
packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js
+6 -57
@@ -7,10 +7,7 @@
7 * @flow
8 */
9
10 -import type {
11 - TopLevelType,
12 - DOMTopLevelEventType,
13 -} from '../../events/TopLevelEventTypes';
10 +import type {TopLevelType} from '../../events/TopLevelEventTypes';
11 import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
12 import type {
13 AnyNativeEvent,
@@ -22,7 +19,7 @@ import SyntheticEvent from '../../events/SyntheticEvent';
19
20 import * as DOMTopLevelEventTypes from '../DOMTopLevelEventTypes';
21 import {
25 - topLevelEventsToDispatchConfig,
22 + topLevelEventsToReactNames,
23 simpleEventPluginEventTypes,
24 } from '../DOMEventProperties';
25 import {
@@ -46,41 +43,6 @@ import getEventCharCode from '../getEventCharCode';
43
44 import {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags';
45
49 -// Only used in DEV for exhaustiveness validation.
50 -const knownHTMLTopLevelTypes: Array<DOMTopLevelEventType> = [
51 - DOMTopLevelEventTypes.TOP_ABORT,
52 - DOMTopLevelEventTypes.TOP_CANCEL,
53 - DOMTopLevelEventTypes.TOP_CAN_PLAY,
54 - DOMTopLevelEventTypes.TOP_CAN_PLAY_THROUGH,
55 - DOMTopLevelEventTypes.TOP_CLOSE,
56 - DOMTopLevelEventTypes.TOP_DURATION_CHANGE,
57 - DOMTopLevelEventTypes.TOP_EMPTIED,
58 - DOMTopLevelEventTypes.TOP_ENCRYPTED,
59 - DOMTopLevelEventTypes.TOP_ENDED,
60 - DOMTopLevelEventTypes.TOP_ERROR,
61 - DOMTopLevelEventTypes.TOP_INPUT,
62 - DOMTopLevelEventTypes.TOP_INVALID,
63 - DOMTopLevelEventTypes.TOP_LOAD,
64 - DOMTopLevelEventTypes.TOP_LOADED_DATA,
65 - DOMTopLevelEventTypes.TOP_LOADED_METADATA,
66 - DOMTopLevelEventTypes.TOP_LOAD_START,
67 - DOMTopLevelEventTypes.TOP_PAUSE,
68 - DOMTopLevelEventTypes.TOP_PLAY,
69 - DOMTopLevelEventTypes.TOP_PLAYING,
70 - DOMTopLevelEventTypes.TOP_PROGRESS,
71 - DOMTopLevelEventTypes.TOP_RATE_CHANGE,
72 - DOMTopLevelEventTypes.TOP_RESET,
73 - DOMTopLevelEventTypes.TOP_SEEKED,
74 - DOMTopLevelEventTypes.TOP_SEEKING,
75 - DOMTopLevelEventTypes.TOP_STALLED,
76 - DOMTopLevelEventTypes.TOP_SUBMIT,
77 - DOMTopLevelEventTypes.TOP_SUSPEND,
78 - DOMTopLevelEventTypes.TOP_TIME_UPDATE,
79 - DOMTopLevelEventTypes.TOP_TOGGLE,
80 - DOMTopLevelEventTypes.TOP_VOLUME_CHANGE,
81 - DOMTopLevelEventTypes.TOP_WAITING,
82 -];
83 -
46 function extractEvents(
47 dispatchQueue: DispatchQueue,
48 topLevelType: TopLevelType,
@@ -90,8 +52,8 @@ function extractEvents(
52 eventSystemFlags: EventSystemFlags,
53 targetContainer: null | EventTarget,
54 ): void {
93 - const dispatchConfig = topLevelEventsToDispatchConfig.get(topLevelType);
94 - if (!dispatchConfig) {
55 + const reactName = topLevelEventsToReactNames.get(topLevelType);
56 + if (reactName === undefined) {
57 return;
58 }
59 let EventConstructor;
@@ -179,25 +141,12 @@ function extractEvents(
141 EventConstructor = SyntheticPointerEvent;
142 break;
143 default:
182 - if (__DEV__) {
183 - if (
184 - knownHTMLTopLevelTypes.indexOf(topLevelType) === -1 &&
185 - dispatchConfig.customEvent !== true
186 - ) {
187 - console.error(
188 - 'SimpleEventPlugin: Unhandled event type, `%s`. This warning ' +
189 - 'is likely caused by a bug in React. Please file an issue.',
190 - topLevelType,
191 - );
192 - }
193 - }
194 - // HTML Events
195 - // @see http://www.w3.org/TR/html5/index.html#events-0
144 + // Unknown event. This is used by createEventHandle.
145 EventConstructor = SyntheticEvent;
146 break;
147 }
148 const event = new EventConstructor(
200 - dispatchConfig,
149 + reactName,
150 null,
151 nativeEvent,
152 nativeEventTarget,
packages/react-dom/src/shared/ReactDOMUnknownPropertyHook.js
+5 -2
@@ -43,8 +43,11 @@ if (__DEV__) {
43
44 // We can't rely on the event system being injected on the server.
45 if (eventRegistry != null) {
46 - const {registrationNames, possibleRegistrationNames} = eventRegistry;
47 - if (registrationNames.hasOwnProperty(name)) {
46 + const {
47 + registrationNameDependencies,
48 + possibleRegistrationNames,
49 + } = eventRegistry;
50 + if (registrationNameDependencies.hasOwnProperty(name)) {
51 return true;
52 }
53 const registrationName = possibleRegistrationNames.hasOwnProperty(
packages/react-dom/src/test-utils/ReactTestUtils.js
+13 -24
@@ -491,14 +491,16 @@ function getListener(inst: Fiber, registrationName: string) {
491 }
492
493 function listenerAtPhase(inst, event, propagationPhase: PropagationPhases) {
494 - const registrationName =
495 - event.dispatchConfig.phasedRegistrationNames[propagationPhase];
494 + let registrationName = event._reactName;
495 + if (propagationPhase === 'captured') {
496 + registrationName += 'Capture';
497 + }
498 return getListener(inst, registrationName);
499 }
500
501 function accumulateDispatches(inst, ignoredDirection, event) {
500 - if (inst && event && event.dispatchConfig.registrationName) {
501 - const registrationName = event.dispatchConfig.registrationName;
502 + if (inst && event && event._reactName) {
503 + const registrationName = event._reactName;
504 const listener = getListener(inst, registrationName);
505 if (listener) {
506 if (event._dispatchListeners == null) {
@@ -533,13 +535,13 @@ function accumulateDirectionalDispatches(inst, phase, event) {
535 }
536
537 function accumulateDirectDispatchesSingle(event) {
536 - if (event && event.dispatchConfig.registrationName) {
538 + if (event && event._reactName) {
539 accumulateDispatches(event._targetInst, null, event);
540 }
541 }
542
543 function accumulateTwoPhaseDispatchesSingle(event) {
542 - if (event && event.dispatchConfig.phasedRegistrationNames) {
544 + if (event && event._reactName) {
545 traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
546 }
547 }
@@ -577,27 +579,14 @@ function makeSimulator(eventType) {
579 'a component instance. Pass the DOM node you wish to simulate the event on instead.',
580 );
581
580 - // Reconstruct more or less what the original event system produced.
581 - // We could remove this indirection here but we also don't plan to invest in Simulate anyway.
582 - const dispatchConfig = {};
583 - if (directDispatchEventTypes.has(eventType)) {
584 - dispatchConfig.registrationName =
585 - 'on' + eventType[0].toUpperCase() + eventType.slice(1);
586 - } else {
587 - dispatchConfig.phasedRegistrationNames = {
588 - bubbled: 'on' + eventType[0].toUpperCase() + eventType.slice(1),
589 - captured:
590 - 'on' + eventType[0].toUpperCase() + eventType.slice(1) + 'Capture',
591 - };
592 - }
593 -
582 + const reactName = 'on' + eventType[0].toUpperCase() + eventType.slice(1);
583 const fakeNativeEvent = new Event();
584 fakeNativeEvent.target = domNode;
585 fakeNativeEvent.type = eventType.toLowerCase();
586
587 const targetInst = getInstanceFromNode(domNode);
588 const event = new SyntheticEvent(
600 - dispatchConfig,
589 + reactName,
590 targetInst,
591 fakeNativeEvent,
592 domNode,
@@ -608,10 +597,10 @@ function makeSimulator(eventType) {
597 event.persist();
598 Object.assign(event, eventData);
599
611 - if (dispatchConfig.phasedRegistrationNames) {
612 - accumulateTwoPhaseDispatchesSingle(event);
613 - } else {
600 + if (directDispatchEventTypes.has(eventType)) {
601 accumulateDirectDispatchesSingle(event);
602 + } else {
603 + accumulateTwoPhaseDispatchesSingle(event);
604 }
605
606 ReactDOM.unstable_batchedUpdates(function() {