mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Clean up Selective Hydration / Event Replay flag (#24156)
* clean up selective hydration / replay flag * dont export return_targetInst
This commit is contained in:
@@ -2418,18 +2418,8 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(clicks).toBe(0);
|
||||
expect(container.textContent).toBe('Click meHello');
|
||||
} else {
|
||||
expect(clicks).toBe(1);
|
||||
expect(container.textContent).toBe('Hello');
|
||||
}
|
||||
expect(clicks).toBe(0);
|
||||
expect(container.textContent).toBe('Click meHello');
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
@@ -2511,17 +2501,7 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(onEvent).toHaveBeenCalledTimes(0);
|
||||
} else {
|
||||
expect(onEvent).toHaveBeenCalledTimes(2);
|
||||
}
|
||||
|
||||
expect(onEvent).toHaveBeenCalledTimes(0);
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
@@ -2601,16 +2581,7 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(clicks).toBe(0);
|
||||
} else {
|
||||
expect(clicks).toBe(2);
|
||||
}
|
||||
expect(clicks).toBe(0);
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
@@ -2695,17 +2666,7 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
resolve();
|
||||
await promise;
|
||||
});
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(onEvent).toHaveBeenCalledTimes(0);
|
||||
} else {
|
||||
expect(onEvent).toHaveBeenCalledTimes(2);
|
||||
}
|
||||
|
||||
expect(onEvent).toHaveBeenCalledTimes(0);
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
@@ -2776,19 +2737,8 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(clicksOnChild).toBe(0);
|
||||
expect(clicksOnParent).toBe(0);
|
||||
} else {
|
||||
expect(clicksOnChild).toBe(1);
|
||||
// This will be zero due to the stopPropagation.
|
||||
expect(clicksOnParent).toBe(0);
|
||||
}
|
||||
expect(clicksOnChild).toBe(0);
|
||||
expect(clicksOnParent).toBe(0);
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
@@ -2864,16 +2814,7 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
});
|
||||
|
||||
// We're now full hydrated.
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(clicks).toBe(0);
|
||||
} else {
|
||||
expect(clicks).toBe(1);
|
||||
}
|
||||
expect(clicks).toBe(0);
|
||||
|
||||
document.body.removeChild(parentContainer);
|
||||
});
|
||||
@@ -3142,19 +3083,9 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
// discrete event not replayed
|
||||
expect(submits).toBe(0);
|
||||
expect(container.textContent).toBe('Click meHello');
|
||||
} else {
|
||||
expect(submits).toBe(1);
|
||||
expect(container.textContent).toBe('Hello');
|
||||
}
|
||||
// discrete event not replayed
|
||||
expect(submits).toBe(0);
|
||||
expect(container.textContent).toBe('Click meHello');
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
+46
-176
@@ -268,18 +268,7 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(Scheduler).toHaveYielded(['D', 'A']);
|
||||
} else {
|
||||
// After the click, we should prioritize D and the Click first,
|
||||
// and only after that render A and C.
|
||||
expect(Scheduler).toHaveYielded(['D', 'Clicked D', 'A']);
|
||||
}
|
||||
expect(Scheduler).toHaveYielded(['D', 'A']);
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
@@ -353,16 +342,7 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
dispatchClickEvent(spanC);
|
||||
dispatchClickEvent(spanD);
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(Scheduler).toHaveYielded(['App', 'C', 'Clicked C']);
|
||||
} else {
|
||||
expect(Scheduler).toHaveYielded(['App']);
|
||||
}
|
||||
expect(Scheduler).toHaveYielded(['App', 'C', 'Clicked C']);
|
||||
|
||||
await act(async () => {
|
||||
suspend = false;
|
||||
@@ -370,29 +350,12 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
ReactFeatureFlags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay
|
||||
) {
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'A',
|
||||
'D',
|
||||
// B should render last since it wasn't clicked.
|
||||
'B',
|
||||
]);
|
||||
} else {
|
||||
// We should prioritize hydrating A, C and D first since we clicked in
|
||||
// them. Only after they're done will we hydrate B.
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'A',
|
||||
'Clicked A',
|
||||
'C',
|
||||
'Clicked C',
|
||||
'D',
|
||||
'Clicked D',
|
||||
// B should render last since it wasn't clicked.
|
||||
'B',
|
||||
]);
|
||||
}
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'A',
|
||||
'D',
|
||||
// B should render last since it wasn't clicked.
|
||||
'B',
|
||||
]);
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
@@ -546,17 +509,8 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
resolve();
|
||||
await promise;
|
||||
});
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
// no replay
|
||||
expect(Scheduler).toHaveYielded(['D', 'A']);
|
||||
} else {
|
||||
expect(Scheduler).toHaveYielded(['D', 'Clicked D', 'A']);
|
||||
}
|
||||
// no replay
|
||||
expect(Scheduler).toHaveYielded(['D', 'A']);
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
@@ -635,42 +589,19 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
createEventTarget(spanC).virtualclick();
|
||||
createEventTarget(spanD).virtualclick();
|
||||
|
||||
if (
|
||||
ReactFeatureFlags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay
|
||||
) {
|
||||
expect(Scheduler).toHaveYielded(['App', 'C', 'Clicked C']);
|
||||
} else {
|
||||
expect(Scheduler).toHaveYielded(['App']);
|
||||
}
|
||||
expect(Scheduler).toHaveYielded(['App', 'C', 'Clicked C']);
|
||||
await act(async () => {
|
||||
suspend = false;
|
||||
resolve();
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
ReactFeatureFlags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay
|
||||
) {
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'A',
|
||||
'D',
|
||||
// B should render last since it wasn't clicked.
|
||||
'B',
|
||||
]);
|
||||
} else {
|
||||
// We should prioritize hydrating A, C and D first since we clicked in
|
||||
// them. Only after they're done will we hydrate B.
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'A',
|
||||
'Clicked A',
|
||||
'C',
|
||||
'Clicked C',
|
||||
'D',
|
||||
'Clicked D',
|
||||
// B should render last since it wasn't clicked.
|
||||
'B',
|
||||
]);
|
||||
}
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'A',
|
||||
'D',
|
||||
// B should render last since it wasn't clicked.
|
||||
'B',
|
||||
]);
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
@@ -750,37 +681,15 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
resolve();
|
||||
await promise;
|
||||
});
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
// We should prioritize hydrating D first because we clicked it.
|
||||
// but event isnt replayed
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'D',
|
||||
'B', // Ideally this should be later.
|
||||
'C',
|
||||
'Hover C',
|
||||
'A',
|
||||
]);
|
||||
} else {
|
||||
// We should prioritize hydrating D first because we clicked it.
|
||||
// Next we should hydrate C since that's the current hover target.
|
||||
// To simplify implementation details we hydrate both B and C at
|
||||
// the same time since B was already scheduled.
|
||||
// This is ok because it will at least not continue for nested
|
||||
// boundary. See the next test below.
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'D',
|
||||
'Clicked D',
|
||||
'B', // Ideally this should be later.
|
||||
'C',
|
||||
'Hover C',
|
||||
'A',
|
||||
]);
|
||||
}
|
||||
// We should prioritize hydrating D first because we clicked it.
|
||||
// but event isnt replayed
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'D',
|
||||
'B', // Ideally this should be later.
|
||||
'C',
|
||||
'Hover C',
|
||||
'A',
|
||||
]);
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
@@ -904,47 +813,22 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
await promise;
|
||||
});
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
// We should prioritize hydrating D first because we clicked it.
|
||||
// but event isnt replayed
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'D',
|
||||
'B', // Ideally this should be later.
|
||||
'C',
|
||||
// Mouse out events aren't replayed
|
||||
// 'Mouse Out Capture B',
|
||||
// 'Mouse Out B',
|
||||
'Mouse Over Capture Parent',
|
||||
'Mouse Over Capture C',
|
||||
// Stop propagation stops these
|
||||
// 'Mouse Over Capture Inner C',
|
||||
// 'Mouse Over C',
|
||||
'A',
|
||||
]);
|
||||
} else {
|
||||
// We should prioritize hydrating D first because we clicked it.
|
||||
// Next we should hydrate C since that's the current hover target.
|
||||
// To simplify implementation details we hydrate both B and C at
|
||||
// the same time since B was already scheduled.
|
||||
// This is ok because it will at least not continue for nested
|
||||
// boundary. See the next test below.
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'D',
|
||||
'Clicked D',
|
||||
'B', // Ideally this should be later.
|
||||
'C',
|
||||
// Capture phase isn't replayed
|
||||
// Mouseout isn't replayed
|
||||
'Mouse Over C',
|
||||
'Mouse Enter C',
|
||||
'A',
|
||||
]);
|
||||
}
|
||||
// We should prioritize hydrating D first because we clicked it.
|
||||
// but event isnt replayed
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'D',
|
||||
'B', // Ideally this should be later.
|
||||
'C',
|
||||
// Mouse out events aren't replayed
|
||||
// 'Mouse Out Capture B',
|
||||
// 'Mouse Out B',
|
||||
'Mouse Over Capture Parent',
|
||||
'Mouse Over Capture C',
|
||||
// Stop propagation stops these
|
||||
// 'Mouse Over Capture Inner C',
|
||||
// 'Mouse Over C',
|
||||
'A',
|
||||
]);
|
||||
|
||||
// This test shows existing quirk where stopPropagation on mouseout
|
||||
// prevents mouseEnter from firing
|
||||
@@ -1091,19 +975,10 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
});
|
||||
|
||||
expect(OuterScheduler).toHaveYielded(['Suspend Outer']);
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
// InnerApp doesn't see the event because OuterApp calls stopPropagation in
|
||||
// capture phase since the event is blocked on suspended component
|
||||
expect(InnerScheduler).toHaveYielded([]);
|
||||
} else {
|
||||
// no stopPropagation
|
||||
expect(InnerScheduler).toHaveYielded(['Suspend Inner']);
|
||||
}
|
||||
|
||||
// InnerApp doesn't see the event because OuterApp calls stopPropagation in
|
||||
// capture phase since the event is blocked on suspended component
|
||||
expect(InnerScheduler).toHaveYielded([]);
|
||||
|
||||
expect(Scheduler).toHaveYielded([]);
|
||||
});
|
||||
@@ -1111,7 +986,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
// @gate enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay
|
||||
it('Inner hydrates first then Outer', async () => {
|
||||
dispatchMouseHoverEvent(innerDiv);
|
||||
|
||||
@@ -1168,7 +1042,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay
|
||||
it('Outer hydrates first then Inner', async () => {
|
||||
dispatchMouseHoverEvent(innerDiv);
|
||||
|
||||
@@ -1230,7 +1103,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// @gate enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay
|
||||
it('replays event with null target when tree is dismounted', async () => {
|
||||
let suspend = false;
|
||||
let resolve;
|
||||
@@ -1549,7 +1421,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
// @gate enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay
|
||||
it('fires capture event handlers and native events if content is hydratable during discrete event', async () => {
|
||||
spyOnDev(console, 'error');
|
||||
function Child({text}) {
|
||||
@@ -1633,7 +1504,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
// @gate enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay
|
||||
it('does not propagate discrete event if it cannot be synchronously hydrated', async () => {
|
||||
let triggeredParent = false;
|
||||
let triggeredChild = false;
|
||||
|
||||
-3
@@ -37,7 +37,6 @@ import {
|
||||
flushControlled,
|
||||
injectIntoDevTools,
|
||||
attemptSynchronousHydration,
|
||||
attemptDiscreteHydration,
|
||||
attemptContinuousHydration,
|
||||
attemptHydrationAtCurrentPriority,
|
||||
} from 'react-reconciler/src/ReactFiberReconciler';
|
||||
@@ -59,7 +58,6 @@ import {
|
||||
import {restoreControlledState} from './ReactDOMComponent';
|
||||
import {
|
||||
setAttemptSynchronousHydration,
|
||||
setAttemptDiscreteHydration,
|
||||
setAttemptContinuousHydration,
|
||||
setAttemptHydrationAtCurrentPriority,
|
||||
setGetCurrentUpdatePriority,
|
||||
@@ -73,7 +71,6 @@ import {
|
||||
} from '../events/ReactDOMControlledComponent';
|
||||
|
||||
setAttemptSynchronousHydration(attemptSynchronousHydration);
|
||||
setAttemptDiscreteHydration(attemptDiscreteHydration);
|
||||
setAttemptContinuousHydration(attemptContinuousHydration);
|
||||
setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
|
||||
setGetCurrentUpdatePriority(getCurrentUpdatePriority);
|
||||
|
||||
+2
-121
@@ -11,11 +11,8 @@ import type {AnyNativeEvent} from '../events/PluginModuleType';
|
||||
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
|
||||
import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
|
||||
import type {DOMEventName} from '../events/DOMEventNames';
|
||||
import {enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay} from 'shared/ReactFeatureFlags';
|
||||
import {
|
||||
isDiscreteEventThatRequiresHydration,
|
||||
queueDiscreteEvent,
|
||||
hasQueuedDiscreteEvents,
|
||||
clearIfContinuousEvent,
|
||||
queueIfContinuousEvent,
|
||||
attemptSynchronousHydration,
|
||||
@@ -146,123 +143,7 @@ function dispatchContinuousEvent(
|
||||
}
|
||||
}
|
||||
|
||||
export function dispatchEvent(
|
||||
domEventName: DOMEventName,
|
||||
eventSystemFlags: EventSystemFlags,
|
||||
targetContainer: EventTarget,
|
||||
nativeEvent: AnyNativeEvent,
|
||||
): void {
|
||||
if (!_enabled) {
|
||||
return;
|
||||
}
|
||||
if (enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay) {
|
||||
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
targetContainer,
|
||||
nativeEvent,
|
||||
);
|
||||
} else {
|
||||
dispatchEventOriginal(
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
targetContainer,
|
||||
nativeEvent,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function dispatchEventOriginal(
|
||||
domEventName: DOMEventName,
|
||||
eventSystemFlags: EventSystemFlags,
|
||||
targetContainer: EventTarget,
|
||||
nativeEvent: AnyNativeEvent,
|
||||
) {
|
||||
// TODO: replaying capture phase events is currently broken
|
||||
// because we used to do it during top-level native bubble handlers
|
||||
// but now we use different bubble and capture handlers.
|
||||
// In eager mode, we attach capture listeners early, so we need
|
||||
// to filter them out until we fix the logic to handle them correctly.
|
||||
const allowReplay = (eventSystemFlags & IS_CAPTURE_PHASE) === 0;
|
||||
|
||||
if (
|
||||
allowReplay &&
|
||||
hasQueuedDiscreteEvents() &&
|
||||
isDiscreteEventThatRequiresHydration(domEventName)
|
||||
) {
|
||||
// If we already have a queue of discrete events, and this is another discrete
|
||||
// event, then we can't dispatch it regardless of its target, since they
|
||||
// need to dispatch in order.
|
||||
queueDiscreteEvent(
|
||||
null, // Flags that we're not actually blocked on anything as far as we know.
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
targetContainer,
|
||||
nativeEvent,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const blockedOn = findInstanceBlockingEvent(
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
targetContainer,
|
||||
nativeEvent,
|
||||
);
|
||||
if (blockedOn === null) {
|
||||
dispatchEventForPluginEventSystem(
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
nativeEvent,
|
||||
return_targetInst,
|
||||
targetContainer,
|
||||
);
|
||||
if (allowReplay) {
|
||||
clearIfContinuousEvent(domEventName, nativeEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowReplay) {
|
||||
if (isDiscreteEventThatRequiresHydration(domEventName)) {
|
||||
// This this to be replayed later once the target is available.
|
||||
queueDiscreteEvent(
|
||||
blockedOn,
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
targetContainer,
|
||||
nativeEvent,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
queueIfContinuousEvent(
|
||||
blockedOn,
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
targetContainer,
|
||||
nativeEvent,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// We need to clear only if we didn't queue because
|
||||
// queueing is accumulative.
|
||||
clearIfContinuousEvent(domEventName, nativeEvent);
|
||||
}
|
||||
|
||||
// This is not replayable so we'll invoke it but without a target,
|
||||
// in case the event system needs to trace it.
|
||||
dispatchEventForPluginEventSystem(
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
nativeEvent,
|
||||
null,
|
||||
targetContainer,
|
||||
);
|
||||
}
|
||||
|
||||
function dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(
|
||||
function dispatchEvent(
|
||||
domEventName: DOMEventName,
|
||||
eventSystemFlags: EventSystemFlags,
|
||||
targetContainer: EventTarget,
|
||||
@@ -348,7 +229,7 @@ function dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEve
|
||||
);
|
||||
}
|
||||
|
||||
export let return_targetInst = null;
|
||||
let return_targetInst = null;
|
||||
|
||||
// Returns a SuspenseInstance or Container if it's blocked.
|
||||
// The return_targetInst field above is conceptually part of the return value.
|
||||
|
||||
+12
-130
@@ -14,10 +14,7 @@ import type {EventSystemFlags} from './EventSystemFlags';
|
||||
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
|
||||
import type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';
|
||||
|
||||
import {
|
||||
enableSelectiveHydration,
|
||||
enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {enableSelectiveHydration} from 'shared/ReactFeatureFlags';
|
||||
import {
|
||||
unstable_scheduleCallback as scheduleCallback,
|
||||
unstable_NormalPriority as NormalPriority,
|
||||
@@ -27,12 +24,8 @@ import {
|
||||
getContainerFromFiber,
|
||||
getSuspenseInstanceFromFiber,
|
||||
} from 'react-reconciler/src/ReactFiberTreeReflection';
|
||||
import {
|
||||
findInstanceBlockingEvent,
|
||||
return_targetInst,
|
||||
} from './ReactDOMEventListener';
|
||||
import {findInstanceBlockingEvent} from './ReactDOMEventListener';
|
||||
import {setReplayingEvent, resetReplayingEvent} from './CurrentReplayingEvent';
|
||||
import {dispatchEventForPluginEventSystem} from './DOMPluginEventSystem';
|
||||
import {
|
||||
getInstanceFromNode,
|
||||
getClosestInstanceFromNode,
|
||||
@@ -51,12 +44,6 @@ export function attemptSynchronousHydration(fiber: Object) {
|
||||
_attemptSynchronousHydration(fiber);
|
||||
}
|
||||
|
||||
let attemptDiscreteHydration: (fiber: Object) => void;
|
||||
|
||||
export function setAttemptDiscreteHydration(fn: (fiber: Object) => void) {
|
||||
attemptDiscreteHydration = fn;
|
||||
}
|
||||
|
||||
let attemptContinuousHydration: (fiber: Object) => void;
|
||||
|
||||
export function setAttemptContinuousHydration(fn: (fiber: Object) => void) {
|
||||
@@ -133,7 +120,7 @@ export function hasQueuedContinuousEvents(): boolean {
|
||||
return hasAnyQueuedContinuousEvents;
|
||||
}
|
||||
|
||||
const discreteReplayableEvents: Array<DOMEventName> = [
|
||||
const synchronouslyHydratedEvents: Array<DOMEventName> = [
|
||||
'mousedown',
|
||||
'mouseup',
|
||||
'touchcancel',
|
||||
@@ -167,7 +154,7 @@ const discreteReplayableEvents: Array<DOMEventName> = [
|
||||
export function isDiscreteEventThatRequiresHydration(
|
||||
eventType: DOMEventName,
|
||||
): boolean {
|
||||
return discreteReplayableEvents.indexOf(eventType) > -1;
|
||||
return synchronouslyHydratedEvents.indexOf(eventType) > -1;
|
||||
}
|
||||
|
||||
function createQueuedReplayableEvent(
|
||||
@@ -186,50 +173,6 @@ function createQueuedReplayableEvent(
|
||||
};
|
||||
}
|
||||
|
||||
export function queueDiscreteEvent(
|
||||
blockedOn: null | Container | SuspenseInstance,
|
||||
domEventName: DOMEventName,
|
||||
eventSystemFlags: EventSystemFlags,
|
||||
targetContainer: EventTarget,
|
||||
nativeEvent: AnyNativeEvent,
|
||||
): void {
|
||||
if (enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay) {
|
||||
return;
|
||||
}
|
||||
const queuedEvent = createQueuedReplayableEvent(
|
||||
blockedOn,
|
||||
domEventName,
|
||||
eventSystemFlags,
|
||||
targetContainer,
|
||||
nativeEvent,
|
||||
);
|
||||
queuedDiscreteEvents.push(queuedEvent);
|
||||
if (enableSelectiveHydration) {
|
||||
if (queuedDiscreteEvents.length === 1) {
|
||||
// If this was the first discrete event, we might be able to
|
||||
// synchronously unblock it so that preventDefault still works.
|
||||
while (queuedEvent.blockedOn !== null) {
|
||||
const fiber = getInstanceFromNode(queuedEvent.blockedOn);
|
||||
if (fiber === null) {
|
||||
break;
|
||||
}
|
||||
attemptSynchronousHydration(fiber);
|
||||
if (queuedEvent.blockedOn === null) {
|
||||
// We got unblocked by hydration. Let's try again.
|
||||
replayUnblockedEvents();
|
||||
// If we're reblocked, on an inner boundary, we might need
|
||||
// to attempt hydrating that one.
|
||||
continue;
|
||||
} else {
|
||||
// We're still blocked from hydration, we have to give up
|
||||
// and replay later.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resets the replaying for this type of continuous event to no event.
|
||||
export function clearIfContinuousEvent(
|
||||
domEventName: DOMEventName,
|
||||
@@ -473,26 +416,14 @@ function attemptReplayContinuousQueuedEvent(
|
||||
queuedEvent.nativeEvent,
|
||||
);
|
||||
if (nextBlockedOn === null) {
|
||||
if (enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay) {
|
||||
const nativeEvent = queuedEvent.nativeEvent;
|
||||
const nativeEventClone = new nativeEvent.constructor(
|
||||
nativeEvent.type,
|
||||
(nativeEvent: any),
|
||||
);
|
||||
setReplayingEvent(nativeEventClone);
|
||||
nativeEvent.target.dispatchEvent(nativeEventClone);
|
||||
resetReplayingEvent();
|
||||
} else {
|
||||
setReplayingEvent(queuedEvent.nativeEvent);
|
||||
dispatchEventForPluginEventSystem(
|
||||
queuedEvent.domEventName,
|
||||
queuedEvent.eventSystemFlags,
|
||||
queuedEvent.nativeEvent,
|
||||
return_targetInst,
|
||||
targetContainer,
|
||||
);
|
||||
resetReplayingEvent();
|
||||
}
|
||||
const nativeEvent = queuedEvent.nativeEvent;
|
||||
const nativeEventClone = new nativeEvent.constructor(
|
||||
nativeEvent.type,
|
||||
(nativeEvent: any),
|
||||
);
|
||||
setReplayingEvent(nativeEventClone);
|
||||
nativeEvent.target.dispatchEvent(nativeEventClone);
|
||||
resetReplayingEvent();
|
||||
} else {
|
||||
// We're still blocked. Try again later.
|
||||
const fiber = getInstanceFromNode(nextBlockedOn);
|
||||
@@ -520,55 +451,6 @@ function attemptReplayContinuousQueuedEventInMap(
|
||||
|
||||
function replayUnblockedEvents() {
|
||||
hasScheduledReplayAttempt = false;
|
||||
if (!enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay) {
|
||||
// First replay discrete events.
|
||||
while (queuedDiscreteEvents.length > 0) {
|
||||
const nextDiscreteEvent = queuedDiscreteEvents[0];
|
||||
if (nextDiscreteEvent.blockedOn !== null) {
|
||||
// We're still blocked.
|
||||
// Increase the priority of this boundary to unblock
|
||||
// the next discrete event.
|
||||
const fiber = getInstanceFromNode(nextDiscreteEvent.blockedOn);
|
||||
if (fiber !== null) {
|
||||
attemptDiscreteHydration(fiber);
|
||||
}
|
||||
break;
|
||||
}
|
||||
const targetContainers = nextDiscreteEvent.targetContainers;
|
||||
while (targetContainers.length > 0) {
|
||||
const targetContainer = targetContainers[0];
|
||||
const nextBlockedOn = findInstanceBlockingEvent(
|
||||
nextDiscreteEvent.domEventName,
|
||||
nextDiscreteEvent.eventSystemFlags,
|
||||
targetContainer,
|
||||
nextDiscreteEvent.nativeEvent,
|
||||
);
|
||||
if (nextBlockedOn === null) {
|
||||
// This whole function is in !enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
// so we don't need the new replay behavior code branch.
|
||||
setReplayingEvent(nextDiscreteEvent.nativeEvent);
|
||||
dispatchEventForPluginEventSystem(
|
||||
nextDiscreteEvent.domEventName,
|
||||
nextDiscreteEvent.eventSystemFlags,
|
||||
nextDiscreteEvent.nativeEvent,
|
||||
return_targetInst,
|
||||
targetContainer,
|
||||
);
|
||||
resetReplayingEvent();
|
||||
} else {
|
||||
// We're still blocked. Try again later.
|
||||
nextDiscreteEvent.blockedOn = nextBlockedOn;
|
||||
break;
|
||||
}
|
||||
// This target container was successfully dispatched. Try the next.
|
||||
targetContainers.shift();
|
||||
}
|
||||
if (nextDiscreteEvent.blockedOn === null) {
|
||||
// We've successfully replayed the first event. Let's try the next one.
|
||||
queuedDiscreteEvents.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Next replay any continuous events.
|
||||
if (queuedFocus !== null && attemptReplayContinuousQueuedEvent(queuedFocus)) {
|
||||
queuedFocus = null;
|
||||
|
||||
@@ -650,16 +650,7 @@ describe('DOMPluginEventSystem', () => {
|
||||
|
||||
// We're now full hydrated.
|
||||
|
||||
if (
|
||||
gate(
|
||||
flags =>
|
||||
flags.enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
)
|
||||
) {
|
||||
expect(clicks).toBe(0);
|
||||
} else {
|
||||
expect(clicks).toBe(1);
|
||||
}
|
||||
expect(clicks).toBe(0);
|
||||
|
||||
document.body.removeChild(parentContainer);
|
||||
});
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
flushPassiveEffects as flushPassiveEffects_old,
|
||||
getPublicRootInstance as getPublicRootInstance_old,
|
||||
attemptSynchronousHydration as attemptSynchronousHydration_old,
|
||||
attemptDiscreteHydration as attemptDiscreteHydration_old,
|
||||
attemptContinuousHydration as attemptContinuousHydration_old,
|
||||
attemptHydrationAtCurrentPriority as attemptHydrationAtCurrentPriority_old,
|
||||
findHostInstance as findHostInstance_old,
|
||||
@@ -65,7 +64,6 @@ import {
|
||||
flushPassiveEffects as flushPassiveEffects_new,
|
||||
getPublicRootInstance as getPublicRootInstance_new,
|
||||
attemptSynchronousHydration as attemptSynchronousHydration_new,
|
||||
attemptDiscreteHydration as attemptDiscreteHydration_new,
|
||||
attemptContinuousHydration as attemptContinuousHydration_new,
|
||||
attemptHydrationAtCurrentPriority as attemptHydrationAtCurrentPriority_new,
|
||||
findHostInstance as findHostInstance_new,
|
||||
@@ -124,9 +122,6 @@ export const getPublicRootInstance = enableNewReconciler
|
||||
export const attemptSynchronousHydration = enableNewReconciler
|
||||
? attemptSynchronousHydration_new
|
||||
: attemptSynchronousHydration_old;
|
||||
export const attemptDiscreteHydration = enableNewReconciler
|
||||
? attemptDiscreteHydration_new
|
||||
: attemptDiscreteHydration_old;
|
||||
export const attemptContinuousHydration = enableNewReconciler
|
||||
? attemptContinuousHydration_new
|
||||
: attemptContinuousHydration_old;
|
||||
|
||||
@@ -452,20 +452,6 @@ function markRetryLaneIfNotHydrated(fiber: Fiber, retryLane: Lane) {
|
||||
}
|
||||
}
|
||||
|
||||
export function attemptDiscreteHydration(fiber: Fiber): void {
|
||||
if (fiber.tag !== SuspenseComponent) {
|
||||
// We ignore HostRoots here because we can't increase
|
||||
// their priority and they should not suspend on I/O,
|
||||
// since you have to wrap anything that might suspend in
|
||||
// Suspense.
|
||||
return;
|
||||
}
|
||||
const eventTime = requestEventTime();
|
||||
const lane = SyncLane;
|
||||
scheduleUpdateOnFiber(fiber, lane, eventTime);
|
||||
markRetryLaneIfNotHydrated(fiber, lane);
|
||||
}
|
||||
|
||||
export function attemptContinuousHydration(fiber: Fiber): void {
|
||||
if (fiber.tag !== SuspenseComponent) {
|
||||
// We ignore HostRoots here because we can't increase
|
||||
|
||||
@@ -452,20 +452,6 @@ function markRetryLaneIfNotHydrated(fiber: Fiber, retryLane: Lane) {
|
||||
}
|
||||
}
|
||||
|
||||
export function attemptDiscreteHydration(fiber: Fiber): void {
|
||||
if (fiber.tag !== SuspenseComponent) {
|
||||
// We ignore HostRoots here because we can't increase
|
||||
// their priority and they should not suspend on I/O,
|
||||
// since you have to wrap anything that might suspend in
|
||||
// Suspense.
|
||||
return;
|
||||
}
|
||||
const eventTime = requestEventTime();
|
||||
const lane = SyncLane;
|
||||
scheduleUpdateOnFiber(fiber, lane, eventTime);
|
||||
markRetryLaneIfNotHydrated(fiber, lane);
|
||||
}
|
||||
|
||||
export function attemptContinuousHydration(fiber: Fiber): void {
|
||||
if (fiber.tag !== SuspenseComponent) {
|
||||
// We ignore HostRoots here because we can't increase
|
||||
|
||||
@@ -47,9 +47,6 @@ export const enableSuspenseLayoutEffectSemantics = true;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = true;
|
||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||
|
||||
// TODO: Need to review this code one more time before landing
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true;
|
||||
|
||||
// Recoil still uses useMutableSource in www, need to delete
|
||||
export const enableUseMutableSource = false;
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableSuspenseAvoidThisFallback = false;
|
||||
export const enableSuspenseAvoidThisFallbackFizz = false;
|
||||
export const enableCPUSuspense = true;
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = true;
|
||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||
export const enableComponentStackLocations = false;
|
||||
|
||||
@@ -43,7 +43,6 @@ export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableSuspenseAvoidThisFallback = false;
|
||||
export const enableSuspenseAvoidThisFallbackFizz = false;
|
||||
export const enableCPUSuspense = false;
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = true;
|
||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||
export const enableComponentStackLocations = false;
|
||||
|
||||
@@ -43,7 +43,6 @@ export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableSuspenseAvoidThisFallback = false;
|
||||
export const enableSuspenseAvoidThisFallbackFizz = false;
|
||||
export const enableCPUSuspense = false;
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = true;
|
||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||
export const enableComponentStackLocations = true;
|
||||
|
||||
@@ -53,7 +53,6 @@ export const deferRenderPhaseUpdateToNextBatch = false;
|
||||
export const enableSuspenseAvoidThisFallback = false;
|
||||
export const enableSuspenseAvoidThisFallbackFizz = false;
|
||||
export const enableCPUSuspense = false;
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = true;
|
||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||
export const enableStrictEffects = false;
|
||||
|
||||
@@ -43,7 +43,6 @@ export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableSuspenseAvoidThisFallback = true;
|
||||
export const enableSuspenseAvoidThisFallbackFizz = false;
|
||||
export const enableCPUSuspense = false;
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = true;
|
||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||
export const enableComponentStackLocations = true;
|
||||
|
||||
@@ -43,7 +43,6 @@ export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableSuspenseAvoidThisFallback = false;
|
||||
export const enableSuspenseAvoidThisFallbackFizz = false;
|
||||
export const enableCPUSuspense = false;
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = true;
|
||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||
export const enableComponentStackLocations = true;
|
||||
|
||||
@@ -43,7 +43,6 @@ export const warnAboutSpreadingKeyToJSX = false;
|
||||
export const enableSuspenseAvoidThisFallback = true;
|
||||
export const enableSuspenseAvoidThisFallbackFizz = false;
|
||||
export const enableCPUSuspense = true;
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = true;
|
||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||
export const enableComponentStackLocations = true;
|
||||
|
||||
@@ -25,7 +25,6 @@ export const disableSchedulerTimeoutInWorkLoop = __VARIANT__;
|
||||
export const enableLazyContextPropagation = __VARIANT__;
|
||||
export const enableSyncDefaultUpdates = __VARIANT__;
|
||||
export const consoleManagedByDevToolsDuringStrictMode = __VARIANT__;
|
||||
export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = __VARIANT__;
|
||||
export const enableClientRenderFallbackOnHydrationMismatch = __VARIANT__;
|
||||
export const enableClientRenderFallbackOnTextMismatch = __VARIANT__;
|
||||
export const enableTransitionTracing = __VARIANT__;
|
||||
|
||||
@@ -31,7 +31,6 @@ export const {
|
||||
disableSchedulerTimeoutInWorkLoop,
|
||||
enableLazyContextPropagation,
|
||||
enableSyncDefaultUpdates,
|
||||
enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
|
||||
enableClientRenderFallbackOnHydrationMismatch,
|
||||
enableClientRenderFallbackOnTextMismatch,
|
||||
} = dynamicFeatureFlags;
|
||||
|
||||
Reference in New Issue
Block a user