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

This commit is contained in:
Dominic Gannaway
2020-04-16 20:10:23 +01:00
committed by GitHub
parent 0301f3e24f
commit 32bb44c80a
14 changed files with 345 additions and 407 deletions
+310 -3
View File
@@ -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<Fiber | null> = [];
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. <div>)
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<Fiber | null> = [];
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<Fiber | null> = [];
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);
}
}
@@ -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<Fiber | null> = [];
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);
}
}
@@ -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<Fiber | null> = [];
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;
}
}
@@ -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<Fiber | null> = [];
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. <div>)
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;
}
}
@@ -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;
@@ -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) {
@@ -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];
},
};
@@ -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;
@@ -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';
@@ -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);
@@ -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');
@@ -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');
@@ -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');
@@ -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');