mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Modern Event System: refactor legacy FB support logic (#18336)
This commit is contained in:
@@ -16,3 +16,4 @@ export const IS_ACTIVE = 1 << 3;
|
||||
export const PASSIVE_NOT_SUPPORTED = 1 << 4;
|
||||
export const IS_REPLAYED = 1 << 5;
|
||||
export const IS_FIRST_ANCESTOR = 1 << 6;
|
||||
export const LEGACY_FB_SUPPORT = 1 << 7;
|
||||
|
||||
@@ -1365,7 +1365,6 @@ export function listenToEventResponderEventTypes(
|
||||
(targetEventType: any),
|
||||
true,
|
||||
passiveItem.listener,
|
||||
true,
|
||||
);
|
||||
listenerMap.delete(passiveKey);
|
||||
}
|
||||
|
||||
+29
-39
@@ -24,6 +24,7 @@ import {registrationNameDependencies} from 'legacy-events/EventPluginRegistry';
|
||||
import {batchedEventUpdates} from 'legacy-events/ReactGenericBatching';
|
||||
import {executeDispatchesInOrder} from 'legacy-events/EventPluginUtils';
|
||||
import {plugins} from 'legacy-events/EventPluginRegistry';
|
||||
import {LEGACY_FB_SUPPORT, IS_REPLAYED} from 'legacy-events/EventSystemFlags';
|
||||
|
||||
import {HostRoot, HostPortal} from 'shared/ReactWorkTags';
|
||||
|
||||
@@ -66,6 +67,7 @@ import {
|
||||
TOP_RATE_CHANGE,
|
||||
TOP_PROGRESS,
|
||||
TOP_PLAYING,
|
||||
TOP_CLICK,
|
||||
} from './DOMTopLevelEventTypes';
|
||||
import {
|
||||
getClosestInstanceFromNode,
|
||||
@@ -78,7 +80,7 @@ import {
|
||||
ELEMENT_NODE,
|
||||
} from '../shared/HTMLNodeType';
|
||||
|
||||
import {enableLegacyFBPrimerSupport} from 'shared/ReactFeatureFlags';
|
||||
import {enableLegacyFBSupport} from 'shared/ReactFeatureFlags';
|
||||
|
||||
const capturePhaseEvents = new Set([
|
||||
TOP_FOCUS,
|
||||
@@ -197,7 +199,6 @@ export function listenToTopLevelEvent(
|
||||
topLevelType,
|
||||
isCapturePhase,
|
||||
((listenerEntry: any): ElementListenerMapEntry).listener,
|
||||
((listenerEntry: any): ElementListenerMapEntry).passive,
|
||||
);
|
||||
}
|
||||
const listener = addTrappedEventListener(
|
||||
@@ -225,42 +226,24 @@ export function listenToEvent(
|
||||
}
|
||||
}
|
||||
|
||||
const validFBLegacyPrimerRels = new Set([
|
||||
'dialog',
|
||||
'dialog-post',
|
||||
'async',
|
||||
'async-post',
|
||||
'theater',
|
||||
'toggle',
|
||||
]);
|
||||
|
||||
function willDeferLaterForFBLegacyPrimer(nativeEvent: any): boolean {
|
||||
let node = nativeEvent.target;
|
||||
const type = nativeEvent.type;
|
||||
if (type !== 'click') {
|
||||
function willDeferLaterForLegacyFBSupport(
|
||||
topLevelType: DOMTopLevelEventType,
|
||||
targetContainer: EventTarget,
|
||||
): boolean {
|
||||
if (topLevelType !== TOP_CLICK) {
|
||||
return false;
|
||||
}
|
||||
while (node !== null) {
|
||||
// Primer works by intercepting a click event on an <a> element
|
||||
// that has a "rel" attribute that matches one of the valid ones
|
||||
// in the Set above. If we intercept this before Primer does, we
|
||||
// will need to defer the current event till later and discontinue
|
||||
// execution of the current event. To do this we can add a document
|
||||
// event listener and continue again later after propagation.
|
||||
if (node.tagName === 'A' && validFBLegacyPrimerRels.has(node.rel)) {
|
||||
const legacyFBSupport = true;
|
||||
const isCapture = nativeEvent.eventPhase === 1;
|
||||
addTrappedEventListener(
|
||||
null,
|
||||
((type: any): DOMTopLevelEventType),
|
||||
isCapture,
|
||||
legacyFBSupport,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
return false;
|
||||
// We defer all click events with legacy FB support mode on.
|
||||
// This means we add a one time event listener to trigger
|
||||
// after the FB delegated listeners fire.
|
||||
const isDeferredListenerForLegacyFBSupport = true;
|
||||
addTrappedEventListener(
|
||||
targetContainer,
|
||||
topLevelType,
|
||||
false,
|
||||
isDeferredListenerForLegacyFBSupport,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
function isMatchingRootContainer(
|
||||
@@ -303,12 +286,19 @@ export function dispatchEventForPluginEventSystem(
|
||||
// TODO: useEvent for document and window
|
||||
return;
|
||||
}
|
||||
// If we detect the FB legacy primer system, we
|
||||
// If we are using the legacy FB support flag, we
|
||||
// defer the event to the null with a one
|
||||
// time event listener so we can defer the event.
|
||||
if (
|
||||
enableLegacyFBPrimerSupport &&
|
||||
willDeferLaterForFBLegacyPrimer(nativeEvent)
|
||||
enableLegacyFBSupport &&
|
||||
// We do not want to defer if the event system has already been
|
||||
// set to LEGACY_FB_SUPPORT. LEGACY_FB_SUPPORT only gets set when
|
||||
// we call willDeferLaterForLegacyFBSupport, thus not bailing out
|
||||
// will result in endless cycles like an infinite loop.
|
||||
(eventSystemFlags & LEGACY_FB_SUPPORT) === 0 &&
|
||||
// We also don't want to defer during event replaying.
|
||||
(eventSystemFlags & IS_REPLAYED) === 0 &&
|
||||
willDeferLaterForLegacyFBSupport(topLevelType, targetContainer)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
+20
-13
@@ -42,6 +42,7 @@ import {
|
||||
IS_PASSIVE,
|
||||
IS_ACTIVE,
|
||||
PASSIVE_NOT_SUPPORTED,
|
||||
LEGACY_FB_SUPPORT,
|
||||
} from 'legacy-events/EventSystemFlags';
|
||||
|
||||
import {
|
||||
@@ -59,7 +60,7 @@ import {passiveBrowserEventsSupported} from './checkPassiveEvents';
|
||||
import {
|
||||
enableDeprecatedFlareAPI,
|
||||
enableModernEventSystem,
|
||||
enableLegacyFBPrimerSupport,
|
||||
enableLegacyFBSupport,
|
||||
enableUseEventAPI,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {
|
||||
@@ -129,10 +130,10 @@ export function addResponderEventSystemEvent(
|
||||
}
|
||||
|
||||
export function addTrappedEventListener(
|
||||
targetContainer: null | EventTarget,
|
||||
targetContainer: EventTarget,
|
||||
topLevelType: DOMTopLevelEventType,
|
||||
capture: boolean,
|
||||
legacyFBSupport?: boolean,
|
||||
isDeferredListenerForLegacyFBSupport?: boolean,
|
||||
passive?: boolean,
|
||||
priority?: EventPriority,
|
||||
): any => void {
|
||||
@@ -159,11 +160,15 @@ export function addTrappedEventListener(
|
||||
if (passive === true && !passiveBrowserEventsSupported) {
|
||||
passive = false;
|
||||
}
|
||||
const eventSystemFlags =
|
||||
enableLegacyFBSupport && isDeferredListenerForLegacyFBSupport
|
||||
? PLUGIN_EVENT_SYSTEM | LEGACY_FB_SUPPORT
|
||||
: PLUGIN_EVENT_SYSTEM;
|
||||
|
||||
listener = listenerWrapper.bind(
|
||||
null,
|
||||
topLevelType,
|
||||
PLUGIN_EVENT_SYSTEM,
|
||||
eventSystemFlags,
|
||||
targetContainer,
|
||||
);
|
||||
|
||||
@@ -177,14 +182,17 @@ export function addTrappedEventListener(
|
||||
targetContainer = document;
|
||||
}
|
||||
|
||||
const validTargetContainer = ((targetContainer: any): EventTarget);
|
||||
targetContainer =
|
||||
enableLegacyFBSupport && isDeferredListenerForLegacyFBSupport
|
||||
? (targetContainer: any).ownerDocument
|
||||
: targetContainer;
|
||||
|
||||
const rawEventName = getRawEventName(topLevelType);
|
||||
|
||||
let unsubscribeListener;
|
||||
// When legacyFBSupport is enabled, it's for when we
|
||||
// want to add a one time event listener to a container.
|
||||
// This should only be used with enableLegacyFBPrimerSupport
|
||||
// This should only be used with enableLegacyFBSupport
|
||||
// due to requirement to provide compatibility with
|
||||
// internal FB www event tooling. This works by removing
|
||||
// the event listener as soon as it is invoked. We could
|
||||
@@ -193,14 +201,14 @@ export function addTrappedEventListener(
|
||||
// browsers do not support this today, and given this is
|
||||
// to support legacy code patterns, it's likely they'll
|
||||
// need support for such browsers.
|
||||
if (enableLegacyFBPrimerSupport && legacyFBSupport) {
|
||||
if (enableLegacyFBSupport && isDeferredListenerForLegacyFBSupport) {
|
||||
const originalListener = listener;
|
||||
listener = function(...p) {
|
||||
try {
|
||||
return originalListener.apply(this, p);
|
||||
} finally {
|
||||
removeEventListener(
|
||||
validTargetContainer,
|
||||
targetContainer,
|
||||
rawEventName,
|
||||
unsubscribeListener,
|
||||
capture,
|
||||
@@ -212,14 +220,14 @@ export function addTrappedEventListener(
|
||||
if (enableUseEventAPI && passive !== undefined) {
|
||||
// This is only used with passive is either true or false.
|
||||
unsubscribeListener = addEventCaptureListenerWithPassiveFlag(
|
||||
validTargetContainer,
|
||||
targetContainer,
|
||||
rawEventName,
|
||||
listener,
|
||||
passive,
|
||||
);
|
||||
} else {
|
||||
unsubscribeListener = addEventCaptureListener(
|
||||
validTargetContainer,
|
||||
targetContainer,
|
||||
rawEventName,
|
||||
listener,
|
||||
);
|
||||
@@ -228,14 +236,14 @@ export function addTrappedEventListener(
|
||||
if (enableUseEventAPI && passive !== undefined) {
|
||||
// This is only used with passive is either true or false.
|
||||
unsubscribeListener = addEventBubbleListenerWithPassiveFlag(
|
||||
validTargetContainer,
|
||||
targetContainer,
|
||||
rawEventName,
|
||||
listener,
|
||||
passive,
|
||||
);
|
||||
} else {
|
||||
unsubscribeListener = addEventBubbleListener(
|
||||
validTargetContainer,
|
||||
targetContainer,
|
||||
rawEventName,
|
||||
listener,
|
||||
);
|
||||
@@ -249,7 +257,6 @@ export function removeTrappedEventListener(
|
||||
topLevelType: DOMTopLevelEventType,
|
||||
capture: boolean,
|
||||
listener: any => void,
|
||||
passive: void | boolean,
|
||||
): void {
|
||||
const rawEventName = getRawEventName(topLevelType);
|
||||
removeEventListener(targetContainer, rawEventName, listener, capture);
|
||||
|
||||
+1705
-1667
File diff suppressed because it is too large
Load Diff
@@ -140,4 +140,4 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
|
||||
export const enableModernEventSystem = false;
|
||||
|
||||
// Support legacy Primer support on internal FB www
|
||||
export const enableLegacyFBPrimerSupport = false;
|
||||
export const enableLegacyFBSupport = false;
|
||||
|
||||
@@ -47,7 +47,7 @@ export const deferPassiveEffectCleanupDuringUnmount = false;
|
||||
export const runAllPassiveEffectDestroysBeforeCreates = false;
|
||||
export const enableModernEventSystem = false;
|
||||
export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableLegacyFBPrimerSupport = false;
|
||||
export const enableLegacyFBSupport = false;
|
||||
|
||||
// Internal-only attempt to debug a React Native issue. See D20130868.
|
||||
export const throwEarlyForMysteriousError = true;
|
||||
|
||||
@@ -46,7 +46,7 @@ export const deferPassiveEffectCleanupDuringUnmount = false;
|
||||
export const runAllPassiveEffectDestroysBeforeCreates = false;
|
||||
export const enableModernEventSystem = false;
|
||||
export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableLegacyFBPrimerSupport = false;
|
||||
export const enableLegacyFBSupport = false;
|
||||
|
||||
// Internal-only attempt to debug a React Native issue. See D20130868.
|
||||
export const throwEarlyForMysteriousError = false;
|
||||
|
||||
@@ -46,7 +46,7 @@ export const deferPassiveEffectCleanupDuringUnmount = false;
|
||||
export const runAllPassiveEffectDestroysBeforeCreates = false;
|
||||
export const enableModernEventSystem = false;
|
||||
export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableLegacyFBPrimerSupport = false;
|
||||
export const enableLegacyFBSupport = false;
|
||||
|
||||
// Internal-only attempt to debug a React Native issue. See D20130868.
|
||||
export const throwEarlyForMysteriousError = false;
|
||||
|
||||
@@ -46,7 +46,7 @@ export const deferPassiveEffectCleanupDuringUnmount = false;
|
||||
export const runAllPassiveEffectDestroysBeforeCreates = false;
|
||||
export const enableModernEventSystem = false;
|
||||
export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableLegacyFBPrimerSupport = false;
|
||||
export const enableLegacyFBSupport = false;
|
||||
|
||||
// Internal-only attempt to debug a React Native issue. See D20130868.
|
||||
export const throwEarlyForMysteriousError = false;
|
||||
|
||||
@@ -46,7 +46,7 @@ export const deferPassiveEffectCleanupDuringUnmount = false;
|
||||
export const runAllPassiveEffectDestroysBeforeCreates = false;
|
||||
export const enableModernEventSystem = false;
|
||||
export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableLegacyFBPrimerSupport = false;
|
||||
export const enableLegacyFBSupport = false;
|
||||
|
||||
// Internal-only attempt to debug a React Native issue. See D20130868.
|
||||
export const throwEarlyForMysteriousError = false;
|
||||
|
||||
@@ -46,7 +46,7 @@ export const deferPassiveEffectCleanupDuringUnmount = false;
|
||||
export const runAllPassiveEffectDestroysBeforeCreates = false;
|
||||
export const enableModernEventSystem = false;
|
||||
export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableLegacyFBPrimerSupport = !__EXPERIMENTAL__;
|
||||
export const enableLegacyFBSupport = !__EXPERIMENTAL__;
|
||||
|
||||
// Internal-only attempt to debug a React Native issue. See D20130868.
|
||||
export const throwEarlyForMysteriousError = false;
|
||||
|
||||
@@ -104,7 +104,7 @@ export const disableModulePatternComponents = __EXPERIMENTAL__;
|
||||
|
||||
export const warnUnstableRenderSubtreeIntoContainer = false;
|
||||
|
||||
export const enableLegacyFBPrimerSupport = !__EXPERIMENTAL__;
|
||||
export const enableLegacyFBSupport = !__EXPERIMENTAL__;
|
||||
|
||||
// Internal-only attempt to debug a React Native issue. See D20130868.
|
||||
export const throwEarlyForMysteriousError = false;
|
||||
|
||||
Reference in New Issue
Block a user