From 32bb44c80ac64b3c96fa9e03b6ecb6dce6a0de6e Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 16 Apr 2020 20:10:23 +0100 Subject: [PATCH] Clean up modern plugins to remove dead code (#18639) --- .../src/events/DOMModernPluginEventSystem.js | 313 +++++++++++++++++- .../events/accumulateEnterLeaveListeners.js | 144 -------- .../events/accumulateEventTargetListeners.js | 65 ---- .../src/events/accumulateTwoPhaseListeners.js | 150 --------- .../plugins/ModernBeforeInputEventPlugin.js | 2 +- .../events/plugins/ModernChangeEventPlugin.js | 18 +- .../plugins/ModernEnterLeaveEventPlugin.js | 38 +-- .../events/plugins/ModernSelectEventPlugin.js | 2 +- .../events/plugins/ModernSimpleEventPlugin.js | 6 +- ...ernBeforeInputEventPlugin-test.internal.js | 3 + .../ModernChangeEventPlugin-test.internal.js | 2 + ...dernEnterLeaveEventPlugin-test.internal.js | 3 + .../ModernSelectEventPlugin-test.internal.js | 3 + .../ModernSimpleEventPlugin-test.internal.js | 3 + 14 files changed, 345 insertions(+), 407 deletions(-) delete mode 100644 packages/react-dom/src/events/accumulateEnterLeaveListeners.js delete mode 100644 packages/react-dom/src/events/accumulateEventTargetListeners.js delete mode 100644 packages/react-dom/src/events/accumulateTwoPhaseListeners.js diff --git a/packages/react-dom/src/events/DOMModernPluginEventSystem.js b/packages/react-dom/src/events/DOMModernPluginEventSystem.js index 8804095657..568df46f72 100644 --- a/packages/react-dom/src/events/DOMModernPluginEventSystem.js +++ b/packages/react-dom/src/events/DOMModernPluginEventSystem.js @@ -33,7 +33,12 @@ import { USE_EVENT_SYSTEM, } from './EventSystemFlags'; -import {HostRoot, HostPortal} from 'react-reconciler/src/ReactWorkTags'; +import { + HostRoot, + HostPortal, + ScopeComponent, + HostComponent, +} from 'react-reconciler/src/ReactWorkTags'; import { addTrappedEventListener, @@ -86,10 +91,12 @@ import { import {COMMENT_NODE} from '../shared/HTMLNodeType'; import {topLevelEventsToDispatchConfig} from './DOMEventProperties'; import {batchedEventUpdates} from './ReactDOMUpdateBatching'; +import getListener from './getListener'; import { enableLegacyFBSupport, enableUseEventAPI, + enableScopeAPI, } from 'shared/ReactFeatureFlags'; import { invokeGuardedCallbackAndCatchFirstError, @@ -153,7 +160,7 @@ const isArray = Array.isArray; const PossiblyWeakMap = ((typeof WeakMap === 'function' ? WeakMap : Map): any); // $FlowFixMe: Flow cannot handle polymorphic WeakMaps -export const eventTargetEventListenerStore: WeakMap< +const eventTargetEventListenerStore: WeakMap< EventTarget, Map< DOMTopLevelEventType, @@ -162,7 +169,7 @@ export const eventTargetEventListenerStore: WeakMap< > = new PossiblyWeakMap(); // $FlowFixMe: Flow cannot handle polymorphic WeakMaps -export const reactScopeListenerStore: WeakMap< +const reactScopeListenerStore: WeakMap< ReactScopeMethods, Map< DOMTopLevelEventType, @@ -672,3 +679,303 @@ export function detachListenerFromReactScope(listener: ReactDOMListener): void { } } } + +export function accumulateTwoPhaseListeners( + event: ReactSyntheticEvent, + accumulateUseEventListeners?: boolean, +): void { + const phasedRegistrationNames = event.dispatchConfig.phasedRegistrationNames; + const dispatchListeners = []; + const dispatchInstances: Array = []; + const dispatchCurrentTargets = []; + + const {bubbled, captured} = phasedRegistrationNames; + // If we are not handling EventTarget only phase, then we're doing the + // usual two phase accumulation using the React fiber tree to pick up + // all relevant useEvent and on* prop events. + let instance = event._targetInst; + let lastHostComponent = null; + + // Accumulate all instances and listeners via the target -> root path. + while (instance !== null) { + const {stateNode, tag} = instance; + // Handle listeners that are on HostComponents (i.e.
) + if (tag === HostComponent && stateNode !== null) { + const currentTarget = stateNode; + lastHostComponent = currentTarget; + // For useEvent listenrs + if (enableUseEventAPI && accumulateUseEventListeners) { + // useEvent event listeners + const targetType = event.type; + const listeners = getListenersFromTarget(currentTarget); + + if (listeners !== null) { + const listenersArr = Array.from(listeners); + for (let i = 0; i < listenersArr.length; i++) { + const listener = listenersArr[i]; + const { + callback, + event: {capture, type}, + } = listener; + if (type === targetType) { + if (capture === true) { + dispatchListeners.unshift(callback); + dispatchInstances.unshift(instance); + dispatchCurrentTargets.unshift(currentTarget); + } else { + dispatchListeners.push(callback); + dispatchInstances.push(instance); + dispatchCurrentTargets.push(currentTarget); + } + } + } + } + } + // Standard React on* listeners, i.e. onClick prop + if (captured !== null) { + const captureListener = getListener(instance, captured); + if (captureListener != null) { + // Capture listeners/instances should go at the start, so we + // unshift them to the start of the array. + dispatchListeners.unshift(captureListener); + dispatchInstances.unshift(instance); + dispatchCurrentTargets.unshift(currentTarget); + } + } + if (bubbled !== null) { + const bubbleListener = getListener(instance, bubbled); + if (bubbleListener != null) { + // Bubble listeners/instances should go at the end, so we + // push them to the end of the array. + dispatchListeners.push(bubbleListener); + dispatchInstances.push(instance); + dispatchCurrentTargets.push(currentTarget); + } + } + } + if ( + enableUseEventAPI && + enableScopeAPI && + accumulateUseEventListeners && + tag === ScopeComponent && + lastHostComponent !== null + ) { + const reactScope = stateNode.methods; + const eventTypeMap = reactScopeListenerStore.get(reactScope); + if (eventTypeMap !== undefined) { + const type = ((event.type: any): DOMTopLevelEventType); + const listeners = eventTypeMap.get(type); + if (listeners !== undefined) { + const captureListeners = Array.from(listeners.captured); + const bubbleListeners = Array.from(listeners.bubbled); + const lastCurrentTarget = ((lastHostComponent: any): Element); + + for (let i = 0; i < captureListeners.length; i++) { + const listener = captureListeners[i]; + const {callback} = listener; + dispatchListeners.unshift(callback); + dispatchInstances.unshift(instance); + dispatchCurrentTargets.unshift(lastCurrentTarget); + } + for (let i = 0; i < bubbleListeners.length; i++) { + const listener = bubbleListeners[i]; + const {callback} = listener; + dispatchListeners.push(callback); + dispatchInstances.push(instance); + dispatchCurrentTargets.push(lastCurrentTarget); + } + } + } + } + instance = instance.return; + } + + // To prevent allocation to the event unless we actually + // have listeners we check the length of one of the arrays. + if (dispatchListeners.length > 0) { + event._dispatchListeners = dispatchListeners; + event._dispatchInstances = dispatchInstances; + event._dispatchCurrentTargets = dispatchCurrentTargets; + } +} + +export function accumulateEventTargetListeners( + event: ReactSyntheticEvent, + currentTarget: EventTarget, +): void { + const dispatchListeners = []; + const dispatchInstances: Array = []; + const dispatchCurrentTargets = []; + + const eventTypeMap = eventTargetEventListenerStore.get(currentTarget); + if (eventTypeMap !== undefined) { + const type = ((event.type: any): DOMTopLevelEventType); + const listeners = eventTypeMap.get(type); + if (listeners !== undefined) { + const isCapturePhase = (event: any).eventPhase === 1; + + if (isCapturePhase) { + const captureListeners = Array.from(listeners.captured); + + for (let i = captureListeners.length - 1; i >= 0; i--) { + const listener = captureListeners[i]; + const {callback} = listener; + dispatchListeners.push(callback); + // EventTarget listeners do not have instances, as there + // is no backing Fiber instance for them (window, document etc). + dispatchInstances.push(null); + dispatchCurrentTargets.push(currentTarget); + } + } else { + const bubbleListeners = Array.from(listeners.bubbled); + + for (let i = 0; i < bubbleListeners.length; i++) { + const listener = bubbleListeners[i]; + const {callback} = listener; + dispatchListeners.push(callback); + // EventTarget listeners do not have instances, as there + // is no backing Fiber instance for them (window, document etc). + dispatchInstances.push(null); + dispatchCurrentTargets.push(currentTarget); + } + } + } + } + // To prevent allocation to the event unless we actually + // have listeners we check the length of one of the arrays. + if (dispatchListeners.length > 0) { + event._dispatchListeners = dispatchListeners; + event._dispatchInstances = dispatchInstances; + event._dispatchCurrentTargets = dispatchCurrentTargets; + } +} + +function getParent(inst: Fiber | null): Fiber | null { + if (inst === null) { + return null; + } + do { + inst = inst.return; + // TODO: If this is a HostRoot we might want to bail out. + // That is depending on if we want nested subtrees (layers) to bubble + // events to their parent. We could also go through parentNode on the + // host node but that wouldn't work for React Native and doesn't let us + // do the portal feature. + } while (inst && inst.tag !== HostComponent); + if (inst) { + return inst; + } + return null; +} + +/** + * Return the lowest common ancestor of A and B, or null if they are in + * different trees. + */ +function getLowestCommonAncestor(instA: Fiber, instB: Fiber): Fiber | null { + let nodeA = instA; + let nodeB = instB; + let depthA = 0; + for (let tempA = nodeA; tempA; tempA = getParent(tempA)) { + depthA++; + } + let depthB = 0; + for (let tempB = nodeB; tempB; tempB = getParent(tempB)) { + depthB++; + } + + // If A is deeper, crawl up. + while (depthA - depthB > 0) { + nodeA = getParent(nodeA); + depthA--; + } + + // If B is deeper, crawl up. + while (depthB - depthA > 0) { + nodeB = getParent(nodeB); + depthB--; + } + + // Walk in lockstep until we find a match. + let depth = depthA; + while (depth--) { + if (nodeA === nodeB || (nodeB !== null && nodeA === nodeB.alternate)) { + return nodeA; + } + nodeA = getParent(nodeA); + nodeB = getParent(nodeB); + } + return null; +} + +function accumulateEnterLeaveListenersForEvent( + event: ReactSyntheticEvent, + target: Fiber, + common: Fiber | null, + capture: boolean, +): void { + const registrationName = event.dispatchConfig.registrationName; + if (registrationName === undefined) { + return; + } + const dispatchListeners = []; + const dispatchInstances: Array = []; + const dispatchCurrentTargets = []; + + let instance = target; + while (instance !== null) { + if (instance === common) { + break; + } + const {alternate, stateNode, tag} = instance; + if (alternate !== null && alternate === common) { + break; + } + if (tag === HostComponent && stateNode !== null) { + const currentTarget = stateNode; + if (capture) { + const captureListener = getListener(instance, registrationName); + if (captureListener != null) { + // Capture listeners/instances should go at the start, so we + // unshift them to the start of the array. + dispatchListeners.unshift(captureListener); + dispatchInstances.unshift(instance); + dispatchCurrentTargets.unshift(currentTarget); + } + } else { + const bubbleListener = getListener(instance, registrationName); + if (bubbleListener != null) { + // Bubble listeners/instances should go at the end, so we + // push them to the end of the array. + dispatchListeners.push(bubbleListener); + dispatchInstances.push(instance); + dispatchCurrentTargets.push(currentTarget); + } + } + } + instance = instance.return; + } + // To prevent allocation to the event unless we actually + // have listeners we check the length of one of the arrays. + if (dispatchListeners.length > 0) { + event._dispatchListeners = dispatchListeners; + event._dispatchInstances = dispatchInstances; + event._dispatchCurrentTargets = dispatchCurrentTargets; + } +} + +export function accumulateEnterLeaveListeners( + leaveEvent: ReactSyntheticEvent, + enterEvent: ReactSyntheticEvent, + from: Fiber | null, + to: Fiber | null, +): void { + const common = from && to ? getLowestCommonAncestor(from, to) : null; + + if (from !== null) { + accumulateEnterLeaveListenersForEvent(leaveEvent, from, common, false); + } + if (to !== null) { + accumulateEnterLeaveListenersForEvent(enterEvent, to, common, true); + } +} diff --git a/packages/react-dom/src/events/accumulateEnterLeaveListeners.js b/packages/react-dom/src/events/accumulateEnterLeaveListeners.js deleted file mode 100644 index cb5d448199..0000000000 --- a/packages/react-dom/src/events/accumulateEnterLeaveListeners.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; -import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType'; - -import {HostComponent} from 'react-reconciler/src/ReactWorkTags'; -import getListener from './getListener'; - -function getParent(inst: Fiber | null): Fiber | null { - if (inst === null) { - return null; - } - do { - inst = inst.return; - // TODO: If this is a HostRoot we might want to bail out. - // That is depending on if we want nested subtrees (layers) to bubble - // events to their parent. We could also go through parentNode on the - // host node but that wouldn't work for React Native and doesn't let us - // do the portal feature. - } while (inst && inst.tag !== HostComponent); - if (inst) { - return inst; - } - return null; -} - -/** - * Return the lowest common ancestor of A and B, or null if they are in - * different trees. - */ -function getLowestCommonAncestor(instA: Fiber, instB: Fiber): Fiber | null { - let nodeA = instA; - let nodeB = instB; - let depthA = 0; - for (let tempA = nodeA; tempA; tempA = getParent(tempA)) { - depthA++; - } - let depthB = 0; - for (let tempB = nodeB; tempB; tempB = getParent(tempB)) { - depthB++; - } - - // If A is deeper, crawl up. - while (depthA - depthB > 0) { - nodeA = getParent(nodeA); - depthA--; - } - - // If B is deeper, crawl up. - while (depthB - depthA > 0) { - nodeB = getParent(nodeB); - depthB--; - } - - // Walk in lockstep until we find a match. - let depth = depthA; - while (depth--) { - if (nodeA === nodeB || (nodeB !== null && nodeA === nodeB.alternate)) { - return nodeA; - } - nodeA = getParent(nodeA); - nodeB = getParent(nodeB); - } - return null; -} - -function accumulateEnterLeaveListenersForEvent( - event: ReactSyntheticEvent, - target: Fiber, - common: Fiber | null, - capture: boolean, -): void { - const registrationName = event.dispatchConfig.registrationName; - if (registrationName === undefined) { - return; - } - const dispatchListeners = []; - const dispatchInstances: Array = []; - const dispatchCurrentTargets = []; - - let instance = target; - while (instance !== null) { - if (instance === common) { - break; - } - const {alternate, stateNode, tag} = instance; - if (alternate !== null && alternate === common) { - break; - } - if (tag === HostComponent && stateNode !== null) { - const currentTarget = stateNode; - if (capture) { - const captureListener = getListener(instance, registrationName); - if (captureListener != null) { - // Capture listeners/instances should go at the start, so we - // unshift them to the start of the array. - dispatchListeners.unshift(captureListener); - dispatchInstances.unshift(instance); - dispatchCurrentTargets.unshift(currentTarget); - } - } else { - const bubbleListener = getListener(instance, registrationName); - if (bubbleListener != null) { - // Bubble listeners/instances should go at the end, so we - // push them to the end of the array. - dispatchListeners.push(bubbleListener); - dispatchInstances.push(instance); - dispatchCurrentTargets.push(currentTarget); - } - } - } - instance = instance.return; - } - // To prevent allocation to the event unless we actually - // have listeners we check the length of one of the arrays. - if (dispatchListeners.length > 0) { - event._dispatchListeners = dispatchListeners; - event._dispatchInstances = dispatchInstances; - event._dispatchCurrentTargets = dispatchCurrentTargets; - } -} - -export default function accumulateEnterLeaveListeners( - leaveEvent: ReactSyntheticEvent, - enterEvent: ReactSyntheticEvent, - from: Fiber | null, - to: Fiber | null, -): void { - const common = from && to ? getLowestCommonAncestor(from, to) : null; - - if (from !== null) { - accumulateEnterLeaveListenersForEvent(leaveEvent, from, common, false); - } - if (to !== null) { - accumulateEnterLeaveListenersForEvent(enterEvent, to, common, true); - } -} diff --git a/packages/react-dom/src/events/accumulateEventTargetListeners.js b/packages/react-dom/src/events/accumulateEventTargetListeners.js deleted file mode 100644 index 41aee46931..0000000000 --- a/packages/react-dom/src/events/accumulateEventTargetListeners.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; -import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes'; -import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType'; - -import {eventTargetEventListenerStore} from './DOMModernPluginEventSystem'; - -export default function accumulateEventTargetListeners( - event: ReactSyntheticEvent, - currentTarget: EventTarget, -): void { - const dispatchListeners = []; - const dispatchInstances: Array = []; - const dispatchCurrentTargets = []; - - const eventTypeMap = eventTargetEventListenerStore.get(currentTarget); - if (eventTypeMap !== undefined) { - const type = ((event.type: any): DOMTopLevelEventType); - const listeners = eventTypeMap.get(type); - if (listeners !== undefined) { - const isCapturePhase = (event: any).eventPhase === 1; - - if (isCapturePhase) { - const captureListeners = Array.from(listeners.captured); - - for (let i = captureListeners.length - 1; i >= 0; i--) { - const listener = captureListeners[i]; - const {callback} = listener; - dispatchListeners.push(callback); - // EventTarget listeners do not have instances, as there - // is no backing Fiber instance for them (window, document etc). - dispatchInstances.push(null); - dispatchCurrentTargets.push(currentTarget); - } - } else { - const bubbleListeners = Array.from(listeners.bubbled); - - for (let i = 0; i < bubbleListeners.length; i++) { - const listener = bubbleListeners[i]; - const {callback} = listener; - dispatchListeners.push(callback); - // EventTarget listeners do not have instances, as there - // is no backing Fiber instance for them (window, document etc). - dispatchInstances.push(null); - dispatchCurrentTargets.push(currentTarget); - } - } - } - } - // To prevent allocation to the event unless we actually - // have listeners we check the length of one of the arrays. - if (dispatchListeners.length > 0) { - event._dispatchListeners = dispatchListeners; - event._dispatchInstances = dispatchInstances; - event._dispatchCurrentTargets = dispatchCurrentTargets; - } -} diff --git a/packages/react-dom/src/events/accumulateTwoPhaseListeners.js b/packages/react-dom/src/events/accumulateTwoPhaseListeners.js deleted file mode 100644 index aa39f1ab98..0000000000 --- a/packages/react-dom/src/events/accumulateTwoPhaseListeners.js +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; -import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes'; -import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType'; - -import { - HostComponent, - ScopeComponent, -} from 'react-reconciler/src/ReactWorkTags'; -import { - enableUseEventAPI, - enableScopeAPI, - enableModernEventSystem, -} from 'shared/ReactFeatureFlags'; - -import getListener from './getListener'; -import {getListenersFromTarget} from '../client/ReactDOMComponentTree'; -import {reactScopeListenerStore} from './DOMModernPluginEventSystem'; - -export default function accumulateTwoPhaseListeners( - event: ReactSyntheticEvent, - accumulateUseEventListeners?: boolean, -): void { - const phasedRegistrationNames = event.dispatchConfig.phasedRegistrationNames; - const dispatchListeners = []; - const dispatchInstances: Array = []; - const dispatchCurrentTargets = []; - - const {bubbled, captured} = phasedRegistrationNames; - // If we are not handling EventTarget only phase, then we're doing the - // usual two phase accumulation using the React fiber tree to pick up - // all relevant useEvent and on* prop events. - let instance = event._targetInst; - let lastHostComponent = null; - - // Accumulate all instances and listeners via the target -> root path. - while (instance !== null) { - const {stateNode, tag} = instance; - // Handle listeners that are on HostComponents (i.e.
) - if (tag === HostComponent && stateNode !== null) { - const currentTarget = stateNode; - lastHostComponent = currentTarget; - // For useEvent listenrs - if ( - enableModernEventSystem && - enableUseEventAPI && - accumulateUseEventListeners - ) { - // useEvent event listeners - const targetType = event.type; - const listeners = getListenersFromTarget(currentTarget); - - if (listeners !== null) { - const listenersArr = Array.from(listeners); - for (let i = 0; i < listenersArr.length; i++) { - const listener = listenersArr[i]; - const { - callback, - event: {capture, type}, - } = listener; - if (type === targetType) { - if (capture === true) { - dispatchListeners.unshift(callback); - dispatchInstances.unshift(instance); - dispatchCurrentTargets.unshift(currentTarget); - } else { - dispatchListeners.push(callback); - dispatchInstances.push(instance); - dispatchCurrentTargets.push(currentTarget); - } - } - } - } - } - // Standard React on* listeners, i.e. onClick prop - if (captured !== null) { - const captureListener = getListener(instance, captured); - if (captureListener != null) { - // Capture listeners/instances should go at the start, so we - // unshift them to the start of the array. - dispatchListeners.unshift(captureListener); - dispatchInstances.unshift(instance); - dispatchCurrentTargets.unshift(currentTarget); - } - } - if (bubbled !== null) { - const bubbleListener = getListener(instance, bubbled); - if (bubbleListener != null) { - // Bubble listeners/instances should go at the end, so we - // push them to the end of the array. - dispatchListeners.push(bubbleListener); - dispatchInstances.push(instance); - dispatchCurrentTargets.push(currentTarget); - } - } - } - if ( - enableModernEventSystem && - enableUseEventAPI && - enableScopeAPI && - accumulateUseEventListeners && - tag === ScopeComponent && - lastHostComponent !== null - ) { - const reactScope = stateNode.methods; - const eventTypeMap = reactScopeListenerStore.get(reactScope); - if (eventTypeMap !== undefined) { - const type = ((event.type: any): DOMTopLevelEventType); - const listeners = eventTypeMap.get(type); - if (listeners !== undefined) { - const captureListeners = Array.from(listeners.captured); - const bubbleListeners = Array.from(listeners.bubbled); - const lastCurrentTarget = ((lastHostComponent: any): Element); - - for (let i = 0; i < captureListeners.length; i++) { - const listener = captureListeners[i]; - const {callback} = listener; - dispatchListeners.unshift(callback); - dispatchInstances.unshift(instance); - dispatchCurrentTargets.unshift(lastCurrentTarget); - } - for (let i = 0; i < bubbleListeners.length; i++) { - const listener = bubbleListeners[i]; - const {callback} = listener; - dispatchListeners.push(callback); - dispatchInstances.push(instance); - dispatchCurrentTargets.push(lastCurrentTarget); - } - } - } - } - instance = instance.return; - } - - // To prevent allocation to the event unless we actually - // have listeners we check the length of one of the arrays. - if (dispatchListeners.length > 0) { - event._dispatchListeners = dispatchListeners; - event._dispatchInstances = dispatchInstances; - event._dispatchCurrentTargets = dispatchCurrentTargets; - } -} diff --git a/packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js b/packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js index 96685f7c81..167a117e8a 100644 --- a/packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js @@ -28,7 +28,7 @@ import { } from '../FallbackCompositionState'; import SyntheticCompositionEvent from '../SyntheticCompositionEvent'; import SyntheticInputEvent from '../SyntheticInputEvent'; -import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners'; +import {accumulateTwoPhaseListeners} from '../DOMModernPluginEventSystem'; const END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space const START_KEYCODE = 229; diff --git a/packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js b/packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js index dbe3685f36..82c0ab6a80 100644 --- a/packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import {runEventsInBatch} from 'legacy-events/EventBatching'; import SyntheticEvent from 'legacy-events/SyntheticEvent'; import isTextInputElement from '../isTextInputElement'; import {canUseDOM} from 'shared/ExecutionEnvironment'; @@ -27,13 +26,12 @@ import {updateValueIfChanged} from '../../client/inputValueTracking'; import {setDefaultValue} from '../../client/ReactDOMInput'; import {enqueueStateRestore} from '../ReactDOMControlledComponent'; -import { - disableInputAttributeSyncing, - enableModernEventSystem, -} from 'shared/ReactFeatureFlags'; -import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners'; +import {disableInputAttributeSyncing} from 'shared/ReactFeatureFlags'; import {batchedUpdates} from '../ReactDOMUpdateBatching'; -import {dispatchEventsInBatch} from '../DOMModernPluginEventSystem'; +import { + dispatchEventsInBatch, + accumulateTwoPhaseListeners, +} from '../DOMModernPluginEventSystem'; const eventTypes = { change: { @@ -105,11 +103,7 @@ function manualDispatchChangeEvent(nativeEvent) { } function runEventInBatch(event) { - if (enableModernEventSystem) { - dispatchEventsInBatch([event]); - } else { - runEventsInBatch(event); - } + dispatchEventsInBatch([event]); } function getInstIfValueChanged(targetInst) { diff --git a/packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js b/packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js index cb51ed4546..14a18d8610 100644 --- a/packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js @@ -11,20 +11,17 @@ import { TOP_POINTER_OUT, TOP_POINTER_OVER, } from '../DOMTopLevelEventTypes'; -import { - IS_REPLAYED, - IS_FIRST_ANCESTOR, -} from 'react-dom/src/events/EventSystemFlags'; +import {IS_REPLAYED} from 'react-dom/src/events/EventSystemFlags'; import SyntheticMouseEvent from '../SyntheticMouseEvent'; import SyntheticPointerEvent from '../SyntheticPointerEvent'; import { getClosestInstanceFromNode, getNodeFromInstance, } from '../../client/ReactDOMComponentTree'; +import {accumulateEnterLeaveListeners} from '../DOMModernPluginEventSystem'; + import {HostComponent, HostText} from 'react-reconciler/src/ReactWorkTags'; import {getNearestMountedFiber} from 'react-reconciler/src/ReactFiberTreeReflection'; -import {enableModernEventSystem} from 'shared/ReactFeatureFlags'; -import accumulateEnterLeaveListeners from '../accumulateEnterLeaveListeners'; const eventTypes = { mouseEnter: { @@ -70,20 +67,12 @@ const EnterLeaveEventPlugin = { if (isOverEvent && (eventSystemFlags & IS_REPLAYED) === 0) { const related = nativeEvent.relatedTarget || nativeEvent.fromElement; if (related) { - if (enableModernEventSystem) { - // Due to the fact we don't add listeners to the document with the - // modern event system and instead attach listeners to roots, we - // need to handle the over event case. To ensure this, we just need to - // make sure the node that we're coming from is managed by React. - const inst = getClosestInstanceFromNode(related); - if (inst !== null) { - return null; - } - } else { - // If this is an over event with a target, then we've already dispatched - // the event in the out event of the other target. If this is replayed, - // then it's because we couldn't dispatch against this target previously - // so we have to do it now instead. + // Due to the fact we don't add listeners to the document with the + // modern event system and instead attach listeners to roots, we + // need to handle the over event case. To ensure this, we just need to + // make sure the node that we're coming from is managed by React. + const inst = getClosestInstanceFromNode(related); + if (inst !== null) { return null; } } @@ -176,15 +165,6 @@ const EnterLeaveEventPlugin = { accumulateEnterLeaveListeners(leave, enter, from, to); - if (!enableModernEventSystem) { - // If we are not processing the first ancestor, then we - // should not process the same nativeEvent again, as we - // will have already processed it in the first ancestor. - if ((eventSystemFlags & IS_FIRST_ANCESTOR) === 0) { - return [leave]; - } - } - return [leave, enter]; }, }; diff --git a/packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js b/packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js index 0d1266b0bc..e280916fed 100644 --- a/packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js @@ -26,7 +26,7 @@ import {getNodeFromInstance} from '../../client/ReactDOMComponentTree'; import {hasSelectionCapabilities} from '../../client/ReactInputSelection'; import {DOCUMENT_NODE} from '../../shared/HTMLNodeType'; import {isListeningToAllDependencies} from '../DOMEventListenerMap'; -import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners'; +import {accumulateTwoPhaseListeners} from '../DOMModernPluginEventSystem'; const skipSelectionChangeEvent = canUseDOM && 'documentMode' in document && document.documentMode <= 11; diff --git a/packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js b/packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js index cd61625518..d4e5765d96 100644 --- a/packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js @@ -24,6 +24,10 @@ import { topLevelEventsToDispatchConfig, simpleEventPluginEventTypes, } from '../DOMEventProperties'; +import { + accumulateEventTargetListeners, + accumulateTwoPhaseListeners, +} from '../DOMModernPluginEventSystem'; import SyntheticAnimationEvent from '../SyntheticAnimationEvent'; import SyntheticClipboardEvent from '../SyntheticClipboardEvent'; @@ -37,8 +41,6 @@ import SyntheticTransitionEvent from '../SyntheticTransitionEvent'; import SyntheticUIEvent from '../SyntheticUIEvent'; import SyntheticWheelEvent from '../SyntheticWheelEvent'; import getEventCharCode from '../getEventCharCode'; -import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners'; -import accumulateEventTargetListeners from '../accumulateEventTargetListeners'; import {enableUseEventAPI} from 'shared/ReactFeatureFlags'; diff --git a/packages/react-dom/src/events/plugins/__tests__/ModernBeforeInputEventPlugin-test.internal.js b/packages/react-dom/src/events/plugins/__tests__/ModernBeforeInputEventPlugin-test.internal.js index ad4ecd7b81..87cde4eebe 100644 --- a/packages/react-dom/src/events/plugins/__tests__/ModernBeforeInputEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/plugins/__tests__/ModernBeforeInputEventPlugin-test.internal.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let ReactFeatureFlags; describe('BeforeInputEventPlugin', () => { let container; @@ -77,6 +78,8 @@ describe('BeforeInputEventPlugin', () => { } beforeEach(() => { + ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFeatureFlags.enableModernEventSystem = true; React = require('react'); container = document.createElement('div'); document.body.appendChild(container); diff --git a/packages/react-dom/src/events/plugins/__tests__/ModernChangeEventPlugin-test.internal.js b/packages/react-dom/src/events/plugins/__tests__/ModernChangeEventPlugin-test.internal.js index c83cfc4548..7ada7be88e 100644 --- a/packages/react-dom/src/events/plugins/__tests__/ModernChangeEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/plugins/__tests__/ModernChangeEventPlugin-test.internal.js @@ -470,6 +470,7 @@ describe('ChangeEventPlugin', () => { beforeEach(() => { jest.resetModules(); ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFeatureFlags.enableModernEventSystem = true; React = require('react'); ReactDOM = require('react-dom'); @@ -720,6 +721,7 @@ describe('ChangeEventPlugin', () => { it('mouse enter/leave should be user-blocking but not discrete', async () => { // This is currently behind a feature flag jest.resetModules(); + ReactFeatureFlags.enableModernEventSystem = true; React = require('react'); ReactDOM = require('react-dom'); TestUtils = require('react-dom/test-utils'); diff --git a/packages/react-dom/src/events/plugins/__tests__/ModernEnterLeaveEventPlugin-test.internal.js b/packages/react-dom/src/events/plugins/__tests__/ModernEnterLeaveEventPlugin-test.internal.js index b7dcab6142..beda6392b1 100644 --- a/packages/react-dom/src/events/plugins/__tests__/ModernEnterLeaveEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/plugins/__tests__/ModernEnterLeaveEventPlugin-test.internal.js @@ -11,6 +11,7 @@ let React; let ReactDOM; +let ReactFeatureFlags; describe('EnterLeaveEventPlugin', () => { let container; @@ -18,6 +19,8 @@ describe('EnterLeaveEventPlugin', () => { beforeEach(() => { jest.resetModules(); + ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFeatureFlags.enableModernEventSystem = true; React = require('react'); ReactDOM = require('react-dom'); diff --git a/packages/react-dom/src/events/plugins/__tests__/ModernSelectEventPlugin-test.internal.js b/packages/react-dom/src/events/plugins/__tests__/ModernSelectEventPlugin-test.internal.js index 8ab7eccf75..84afb834c1 100644 --- a/packages/react-dom/src/events/plugins/__tests__/ModernSelectEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/plugins/__tests__/ModernSelectEventPlugin-test.internal.js @@ -11,11 +11,14 @@ let React; let ReactDOM; +let ReactFeatureFlags; describe('SelectEventPlugin', () => { let container; beforeEach(() => { + ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFeatureFlags.enableModernEventSystem = true; React = require('react'); ReactDOM = require('react-dom'); diff --git a/packages/react-dom/src/events/plugins/__tests__/ModernSimpleEventPlugin-test.internal.js b/packages/react-dom/src/events/plugins/__tests__/ModernSimpleEventPlugin-test.internal.js index f015689703..598101683d 100644 --- a/packages/react-dom/src/events/plugins/__tests__/ModernSimpleEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/plugins/__tests__/ModernSimpleEventPlugin-test.internal.js @@ -13,6 +13,7 @@ describe('SimpleEventPlugin', function() { let React; let ReactDOM; let Scheduler; + let ReactFeatureFlags; let onClick; let container; @@ -36,6 +37,8 @@ describe('SimpleEventPlugin', function() { beforeEach(function() { jest.resetModules(); + ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFeatureFlags.enableModernEventSystem = true; React = require('react'); ReactDOM = require('react-dom'); Scheduler = require('scheduler');