mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Remove dependency on Offscreen Fiber updateQueue for React Cache (#23229)
We need to use the Offscreen Fiber's update queue for interaction tracing. This PR removes the optimization that React Cache uses to not need to push and pop the cache in special circumstances and defaults to always pushing and popping the cache as long as there was a previous cache.
This commit is contained in:
@@ -234,7 +234,7 @@ import {
|
||||
pushRootCachePool,
|
||||
CacheContext,
|
||||
getSuspendedCachePool,
|
||||
restoreSpawnedCachePool,
|
||||
pushSpawnedCachePool,
|
||||
getOffscreenDeferredCachePool,
|
||||
} from './ReactFiberCacheComponent.new';
|
||||
import {createCapturedValue} from './ReactCapturedValue';
|
||||
@@ -635,11 +635,6 @@ function updateOffscreenComponent(
|
||||
const prevState: OffscreenState | null =
|
||||
current !== null ? current.memoizedState : null;
|
||||
|
||||
// If this is not null, this is a cache pool that was carried over from the
|
||||
// previous render. We will push this to the cache pool context so that we can
|
||||
// resume in-flight requests.
|
||||
let spawnedCachePool: SpawnedCachePool | null = null;
|
||||
|
||||
if (
|
||||
nextProps.mode === 'hidden' ||
|
||||
nextProps.mode === 'unstable-defer-without-hiding'
|
||||
@@ -652,8 +647,16 @@ function updateOffscreenComponent(
|
||||
cachePool: null,
|
||||
};
|
||||
workInProgress.memoizedState = nextState;
|
||||
if (enableCache) {
|
||||
// push the cache pool even though we're going to bail out
|
||||
// because otherwise there'd be a context mismatch
|
||||
if (current !== null) {
|
||||
pushSpawnedCachePool(workInProgress, null);
|
||||
}
|
||||
}
|
||||
pushRenderLanes(workInProgress, renderLanes);
|
||||
} else if (!includesSomeLane(renderLanes, (OffscreenLane: Lane))) {
|
||||
let spawnedCachePool: SpawnedCachePool | null = null;
|
||||
// We're hidden, and we're not rendering at Offscreen. We will bail out
|
||||
// and resume this tree later.
|
||||
let nextBaseLanes;
|
||||
@@ -663,9 +666,6 @@ function updateOffscreenComponent(
|
||||
if (enableCache) {
|
||||
// Save the cache pool so we can resume later.
|
||||
spawnedCachePool = getOffscreenDeferredCachePool();
|
||||
// We don't need to push to the cache pool because we're about to
|
||||
// bail out. There won't be a context mismatch because we only pop
|
||||
// the cache pool if `updateQueue` is non-null.
|
||||
}
|
||||
} else {
|
||||
nextBaseLanes = renderLanes;
|
||||
@@ -681,6 +681,14 @@ function updateOffscreenComponent(
|
||||
};
|
||||
workInProgress.memoizedState = nextState;
|
||||
workInProgress.updateQueue = null;
|
||||
if (enableCache) {
|
||||
// push the cache pool even though we're going to bail out
|
||||
// because otherwise there'd be a context mismatch
|
||||
if (current !== null) {
|
||||
pushSpawnedCachePool(workInProgress, null);
|
||||
}
|
||||
}
|
||||
|
||||
// We're about to bail out, but we need to push this to the stack anyway
|
||||
// to avoid a push/pop misalignment.
|
||||
pushRenderLanes(workInProgress, nextBaseLanes);
|
||||
@@ -701,19 +709,6 @@ function updateOffscreenComponent(
|
||||
// This is the second render. The surrounding visible content has already
|
||||
// committed. Now we resume rendering the hidden tree.
|
||||
|
||||
if (enableCache && prevState !== null) {
|
||||
// If the render that spawned this one accessed the cache pool, resume
|
||||
// using the same cache. Unless the parent changed, since that means
|
||||
// there was a refresh.
|
||||
const prevCachePool = prevState.cachePool;
|
||||
if (prevCachePool !== null) {
|
||||
spawnedCachePool = restoreSpawnedCachePool(
|
||||
workInProgress,
|
||||
prevCachePool,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering at offscreen, so we can clear the base lanes.
|
||||
const nextState: OffscreenState = {
|
||||
baseLanes: NoLanes,
|
||||
@@ -723,6 +718,14 @@ function updateOffscreenComponent(
|
||||
// Push the lanes that were skipped when we bailed out.
|
||||
const subtreeRenderLanes =
|
||||
prevState !== null ? prevState.baseLanes : renderLanes;
|
||||
if (enableCache && current !== null) {
|
||||
// If the render that spawned this one accessed the cache pool, resume
|
||||
// using the same cache. Unless the parent changed, since that means
|
||||
// there was a refresh.
|
||||
const prevCachePool = prevState !== null ? prevState.cachePool : null;
|
||||
pushSpawnedCachePool(workInProgress, prevCachePool);
|
||||
}
|
||||
|
||||
pushRenderLanes(workInProgress, subtreeRenderLanes);
|
||||
}
|
||||
} else {
|
||||
@@ -738,12 +741,7 @@ function updateOffscreenComponent(
|
||||
// using the same cache. Unless the parent changed, since that means
|
||||
// there was a refresh.
|
||||
const prevCachePool = prevState.cachePool;
|
||||
if (prevCachePool !== null) {
|
||||
spawnedCachePool = restoreSpawnedCachePool(
|
||||
workInProgress,
|
||||
prevCachePool,
|
||||
);
|
||||
}
|
||||
pushSpawnedCachePool(workInProgress, prevCachePool);
|
||||
}
|
||||
|
||||
// Since we're not hidden anymore, reset the state
|
||||
@@ -753,16 +751,19 @@ function updateOffscreenComponent(
|
||||
// special to do. Need to push to the stack regardless, though, to avoid
|
||||
// a push/pop misalignment.
|
||||
subtreeRenderLanes = renderLanes;
|
||||
|
||||
if (enableCache) {
|
||||
// If the render that spawned this one accessed the cache pool, resume
|
||||
// using the same cache. Unless the parent changed, since that means
|
||||
// there was a refresh.
|
||||
if (current !== null) {
|
||||
pushSpawnedCachePool(workInProgress, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
pushRenderLanes(workInProgress, subtreeRenderLanes);
|
||||
}
|
||||
|
||||
if (enableCache) {
|
||||
// If we have a cache pool from a previous render attempt, then this will be
|
||||
// non-null. We use this to infer whether to push/pop the cache context.
|
||||
workInProgress.updateQueue = spawnedCachePool;
|
||||
}
|
||||
|
||||
if (enablePersistentOffscreenHostContainer && supportsPersistence) {
|
||||
// In persistent mode, the offscreen children are wrapped in a host node.
|
||||
// TODO: Optimize this to use the OffscreenComponent fiber instead of
|
||||
@@ -2072,6 +2073,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
|
||||
|
||||
const nextPrimaryChildren = nextProps.children;
|
||||
const nextFallbackChildren = nextProps.fallback;
|
||||
|
||||
if (showFallback) {
|
||||
const fallbackFragment = mountSuspenseFallbackChildren(
|
||||
workInProgress,
|
||||
|
||||
@@ -234,7 +234,7 @@ import {
|
||||
pushRootCachePool,
|
||||
CacheContext,
|
||||
getSuspendedCachePool,
|
||||
restoreSpawnedCachePool,
|
||||
pushSpawnedCachePool,
|
||||
getOffscreenDeferredCachePool,
|
||||
} from './ReactFiberCacheComponent.old';
|
||||
import {createCapturedValue} from './ReactCapturedValue';
|
||||
@@ -635,11 +635,6 @@ function updateOffscreenComponent(
|
||||
const prevState: OffscreenState | null =
|
||||
current !== null ? current.memoizedState : null;
|
||||
|
||||
// If this is not null, this is a cache pool that was carried over from the
|
||||
// previous render. We will push this to the cache pool context so that we can
|
||||
// resume in-flight requests.
|
||||
let spawnedCachePool: SpawnedCachePool | null = null;
|
||||
|
||||
if (
|
||||
nextProps.mode === 'hidden' ||
|
||||
nextProps.mode === 'unstable-defer-without-hiding'
|
||||
@@ -652,8 +647,16 @@ function updateOffscreenComponent(
|
||||
cachePool: null,
|
||||
};
|
||||
workInProgress.memoizedState = nextState;
|
||||
if (enableCache) {
|
||||
// push the cache pool even though we're going to bail out
|
||||
// because otherwise there'd be a context mismatch
|
||||
if (current !== null) {
|
||||
pushSpawnedCachePool(workInProgress, null);
|
||||
}
|
||||
}
|
||||
pushRenderLanes(workInProgress, renderLanes);
|
||||
} else if (!includesSomeLane(renderLanes, (OffscreenLane: Lane))) {
|
||||
let spawnedCachePool: SpawnedCachePool | null = null;
|
||||
// We're hidden, and we're not rendering at Offscreen. We will bail out
|
||||
// and resume this tree later.
|
||||
let nextBaseLanes;
|
||||
@@ -663,9 +666,6 @@ function updateOffscreenComponent(
|
||||
if (enableCache) {
|
||||
// Save the cache pool so we can resume later.
|
||||
spawnedCachePool = getOffscreenDeferredCachePool();
|
||||
// We don't need to push to the cache pool because we're about to
|
||||
// bail out. There won't be a context mismatch because we only pop
|
||||
// the cache pool if `updateQueue` is non-null.
|
||||
}
|
||||
} else {
|
||||
nextBaseLanes = renderLanes;
|
||||
@@ -681,6 +681,14 @@ function updateOffscreenComponent(
|
||||
};
|
||||
workInProgress.memoizedState = nextState;
|
||||
workInProgress.updateQueue = null;
|
||||
if (enableCache) {
|
||||
// push the cache pool even though we're going to bail out
|
||||
// because otherwise there'd be a context mismatch
|
||||
if (current !== null) {
|
||||
pushSpawnedCachePool(workInProgress, null);
|
||||
}
|
||||
}
|
||||
|
||||
// We're about to bail out, but we need to push this to the stack anyway
|
||||
// to avoid a push/pop misalignment.
|
||||
pushRenderLanes(workInProgress, nextBaseLanes);
|
||||
@@ -701,19 +709,6 @@ function updateOffscreenComponent(
|
||||
// This is the second render. The surrounding visible content has already
|
||||
// committed. Now we resume rendering the hidden tree.
|
||||
|
||||
if (enableCache && prevState !== null) {
|
||||
// If the render that spawned this one accessed the cache pool, resume
|
||||
// using the same cache. Unless the parent changed, since that means
|
||||
// there was a refresh.
|
||||
const prevCachePool = prevState.cachePool;
|
||||
if (prevCachePool !== null) {
|
||||
spawnedCachePool = restoreSpawnedCachePool(
|
||||
workInProgress,
|
||||
prevCachePool,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering at offscreen, so we can clear the base lanes.
|
||||
const nextState: OffscreenState = {
|
||||
baseLanes: NoLanes,
|
||||
@@ -723,6 +718,14 @@ function updateOffscreenComponent(
|
||||
// Push the lanes that were skipped when we bailed out.
|
||||
const subtreeRenderLanes =
|
||||
prevState !== null ? prevState.baseLanes : renderLanes;
|
||||
if (enableCache && current !== null) {
|
||||
// If the render that spawned this one accessed the cache pool, resume
|
||||
// using the same cache. Unless the parent changed, since that means
|
||||
// there was a refresh.
|
||||
const prevCachePool = prevState !== null ? prevState.cachePool : null;
|
||||
pushSpawnedCachePool(workInProgress, prevCachePool);
|
||||
}
|
||||
|
||||
pushRenderLanes(workInProgress, subtreeRenderLanes);
|
||||
}
|
||||
} else {
|
||||
@@ -738,12 +741,7 @@ function updateOffscreenComponent(
|
||||
// using the same cache. Unless the parent changed, since that means
|
||||
// there was a refresh.
|
||||
const prevCachePool = prevState.cachePool;
|
||||
if (prevCachePool !== null) {
|
||||
spawnedCachePool = restoreSpawnedCachePool(
|
||||
workInProgress,
|
||||
prevCachePool,
|
||||
);
|
||||
}
|
||||
pushSpawnedCachePool(workInProgress, prevCachePool);
|
||||
}
|
||||
|
||||
// Since we're not hidden anymore, reset the state
|
||||
@@ -753,16 +751,19 @@ function updateOffscreenComponent(
|
||||
// special to do. Need to push to the stack regardless, though, to avoid
|
||||
// a push/pop misalignment.
|
||||
subtreeRenderLanes = renderLanes;
|
||||
|
||||
if (enableCache) {
|
||||
// If the render that spawned this one accessed the cache pool, resume
|
||||
// using the same cache. Unless the parent changed, since that means
|
||||
// there was a refresh.
|
||||
if (current !== null) {
|
||||
pushSpawnedCachePool(workInProgress, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
pushRenderLanes(workInProgress, subtreeRenderLanes);
|
||||
}
|
||||
|
||||
if (enableCache) {
|
||||
// If we have a cache pool from a previous render attempt, then this will be
|
||||
// non-null. We use this to infer whether to push/pop the cache context.
|
||||
workInProgress.updateQueue = spawnedCachePool;
|
||||
}
|
||||
|
||||
if (enablePersistentOffscreenHostContainer && supportsPersistence) {
|
||||
// In persistent mode, the offscreen children are wrapped in a host node.
|
||||
// TODO: Optimize this to use the OffscreenComponent fiber instead of
|
||||
@@ -2072,6 +2073,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
|
||||
|
||||
const nextPrimaryChildren = nextProps.children;
|
||||
const nextFallbackChildren = nextProps.fallback;
|
||||
|
||||
if (showFallback) {
|
||||
const fallbackFragment = mountSuspenseFallbackChildren(
|
||||
workInProgress,
|
||||
|
||||
@@ -198,29 +198,18 @@ export function popRootCachePool(root: FiberRoot, renderLanes: Lanes) {
|
||||
// code organization purposes in case that changes.
|
||||
}
|
||||
|
||||
export function restoreSpawnedCachePool(
|
||||
export function pushSpawnedCachePool(
|
||||
offscreenWorkInProgress: Fiber,
|
||||
prevCachePool: SpawnedCachePool,
|
||||
): SpawnedCachePool | null {
|
||||
prevCachePool: SpawnedCachePool | null,
|
||||
): void {
|
||||
if (!enableCache) {
|
||||
return (null: any);
|
||||
return;
|
||||
}
|
||||
const nextParentCache = isPrimaryRenderer
|
||||
? CacheContext._currentValue
|
||||
: CacheContext._currentValue2;
|
||||
if (nextParentCache !== prevCachePool.parent) {
|
||||
// There was a refresh. Don't bother restoring anything since the refresh
|
||||
// will override it.
|
||||
return null;
|
||||
} else {
|
||||
// No refresh. Resume with the previous cache. New Cache boundaries in the
|
||||
// subtree use this one instead of requesting a fresh one (see
|
||||
// peekCacheFromPool).
|
||||
push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
|
||||
|
||||
// Return the cache pool to signal that we did in fact push it. We will
|
||||
// assign this to the field on the fiber so we know to pop the context.
|
||||
return prevCachePool;
|
||||
if (prevCachePool === null) {
|
||||
push(resumedCache, resumedCache.current, offscreenWorkInProgress);
|
||||
} else {
|
||||
push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +217,7 @@ export function popCachePool(workInProgress: Fiber) {
|
||||
if (!enableCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
pop(resumedCache, workInProgress);
|
||||
}
|
||||
|
||||
|
||||
@@ -198,29 +198,18 @@ export function popRootCachePool(root: FiberRoot, renderLanes: Lanes) {
|
||||
// code organization purposes in case that changes.
|
||||
}
|
||||
|
||||
export function restoreSpawnedCachePool(
|
||||
export function pushSpawnedCachePool(
|
||||
offscreenWorkInProgress: Fiber,
|
||||
prevCachePool: SpawnedCachePool,
|
||||
): SpawnedCachePool | null {
|
||||
prevCachePool: SpawnedCachePool | null,
|
||||
): void {
|
||||
if (!enableCache) {
|
||||
return (null: any);
|
||||
return;
|
||||
}
|
||||
const nextParentCache = isPrimaryRenderer
|
||||
? CacheContext._currentValue
|
||||
: CacheContext._currentValue2;
|
||||
if (nextParentCache !== prevCachePool.parent) {
|
||||
// There was a refresh. Don't bother restoring anything since the refresh
|
||||
// will override it.
|
||||
return null;
|
||||
} else {
|
||||
// No refresh. Resume with the previous cache. New Cache boundaries in the
|
||||
// subtree use this one instead of requesting a fresh one (see
|
||||
// peekCacheFromPool).
|
||||
push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
|
||||
|
||||
// Return the cache pool to signal that we did in fact push it. We will
|
||||
// assign this to the field on the fiber so we know to pop the context.
|
||||
return prevCachePool;
|
||||
if (prevCachePool === null) {
|
||||
push(resumedCache, resumedCache.current, offscreenWorkInProgress);
|
||||
} else {
|
||||
push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +217,7 @@ export function popCachePool(workInProgress: Fiber) {
|
||||
if (!enableCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
pop(resumedCache, workInProgress);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import type {
|
||||
} from './ReactFiberSuspenseComponent.new';
|
||||
import type {SuspenseContext} from './ReactFiberSuspenseContext.new';
|
||||
import type {OffscreenState} from './ReactFiberOffscreenComponent';
|
||||
import type {Cache, SpawnedCachePool} from './ReactFiberCacheComponent.new';
|
||||
import type {Cache} from './ReactFiberCacheComponent.new';
|
||||
import {
|
||||
enableClientRenderFallbackOnHydrationMismatch,
|
||||
enableSuspenseAvoidThisFallback,
|
||||
@@ -865,8 +865,8 @@ function completeWork(
|
||||
popRootCachePool(fiberRoot, renderLanes);
|
||||
|
||||
let previousCache: Cache | null = null;
|
||||
if (workInProgress.alternate !== null) {
|
||||
previousCache = workInProgress.alternate.memoizedState.cache;
|
||||
if (current !== null) {
|
||||
previousCache = current.memoizedState.cache;
|
||||
}
|
||||
const cache: Cache = workInProgress.memoizedState.cache;
|
||||
if (cache !== previousCache) {
|
||||
@@ -1533,11 +1533,11 @@ function completeWork(
|
||||
if (enableCache) {
|
||||
let previousCache: Cache | null = null;
|
||||
if (
|
||||
workInProgress.alternate !== null &&
|
||||
workInProgress.alternate.memoizedState !== null &&
|
||||
workInProgress.alternate.memoizedState.cachePool !== null
|
||||
current !== null &&
|
||||
current.memoizedState !== null &&
|
||||
current.memoizedState.cachePool !== null
|
||||
) {
|
||||
previousCache = workInProgress.alternate.memoizedState.cachePool.pool;
|
||||
previousCache = current.memoizedState.cachePool.pool;
|
||||
}
|
||||
let cache: Cache | null = null;
|
||||
if (
|
||||
@@ -1550,8 +1550,7 @@ function completeWork(
|
||||
// Run passive effects to retain/release the cache.
|
||||
workInProgress.flags |= Passive;
|
||||
}
|
||||
const spawnedCachePool: SpawnedCachePool | null = (workInProgress.updateQueue: any);
|
||||
if (spawnedCachePool !== null) {
|
||||
if (current !== null) {
|
||||
popCachePool(workInProgress);
|
||||
}
|
||||
}
|
||||
@@ -1561,8 +1560,8 @@ function completeWork(
|
||||
case CacheComponent: {
|
||||
if (enableCache) {
|
||||
let previousCache: Cache | null = null;
|
||||
if (workInProgress.alternate !== null) {
|
||||
previousCache = workInProgress.alternate.memoizedState.cache;
|
||||
if (current !== null) {
|
||||
previousCache = current.memoizedState.cache;
|
||||
}
|
||||
const cache: Cache = workInProgress.memoizedState.cache;
|
||||
if (cache !== previousCache) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import type {
|
||||
} from './ReactFiberSuspenseComponent.old';
|
||||
import type {SuspenseContext} from './ReactFiberSuspenseContext.old';
|
||||
import type {OffscreenState} from './ReactFiberOffscreenComponent';
|
||||
import type {Cache, SpawnedCachePool} from './ReactFiberCacheComponent.old';
|
||||
import type {Cache} from './ReactFiberCacheComponent.old';
|
||||
import {
|
||||
enableClientRenderFallbackOnHydrationMismatch,
|
||||
enableSuspenseAvoidThisFallback,
|
||||
@@ -865,8 +865,8 @@ function completeWork(
|
||||
popRootCachePool(fiberRoot, renderLanes);
|
||||
|
||||
let previousCache: Cache | null = null;
|
||||
if (workInProgress.alternate !== null) {
|
||||
previousCache = workInProgress.alternate.memoizedState.cache;
|
||||
if (current !== null) {
|
||||
previousCache = current.memoizedState.cache;
|
||||
}
|
||||
const cache: Cache = workInProgress.memoizedState.cache;
|
||||
if (cache !== previousCache) {
|
||||
@@ -1533,11 +1533,11 @@ function completeWork(
|
||||
if (enableCache) {
|
||||
let previousCache: Cache | null = null;
|
||||
if (
|
||||
workInProgress.alternate !== null &&
|
||||
workInProgress.alternate.memoizedState !== null &&
|
||||
workInProgress.alternate.memoizedState.cachePool !== null
|
||||
current !== null &&
|
||||
current.memoizedState !== null &&
|
||||
current.memoizedState.cachePool !== null
|
||||
) {
|
||||
previousCache = workInProgress.alternate.memoizedState.cachePool.pool;
|
||||
previousCache = current.memoizedState.cachePool.pool;
|
||||
}
|
||||
let cache: Cache | null = null;
|
||||
if (
|
||||
@@ -1550,8 +1550,7 @@ function completeWork(
|
||||
// Run passive effects to retain/release the cache.
|
||||
workInProgress.flags |= Passive;
|
||||
}
|
||||
const spawnedCachePool: SpawnedCachePool | null = (workInProgress.updateQueue: any);
|
||||
if (spawnedCachePool !== null) {
|
||||
if (current !== null) {
|
||||
popCachePool(workInProgress);
|
||||
}
|
||||
}
|
||||
@@ -1561,8 +1560,8 @@ function completeWork(
|
||||
case CacheComponent: {
|
||||
if (enableCache) {
|
||||
let previousCache: Cache | null = null;
|
||||
if (workInProgress.alternate !== null) {
|
||||
previousCache = workInProgress.alternate.memoizedState.cache;
|
||||
if (current !== null) {
|
||||
previousCache = current.memoizedState.cache;
|
||||
}
|
||||
const cache: Cache = workInProgress.memoizedState.cache;
|
||||
if (cache !== previousCache) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import type {ReactContext} from 'shared/ReactTypes';
|
||||
import type {Fiber, FiberRoot} from './ReactInternalTypes';
|
||||
import type {Lanes} from './ReactFiberLane.new';
|
||||
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
|
||||
import type {Cache, SpawnedCachePool} from './ReactFiberCacheComponent.new';
|
||||
import type {Cache} from './ReactFiberCacheComponent.new';
|
||||
|
||||
import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.new';
|
||||
import {
|
||||
@@ -52,7 +52,11 @@ import {
|
||||
import {transferActualDuration} from './ReactProfilerTimer.new';
|
||||
import {popTreeContext} from './ReactFiberTreeContext.new';
|
||||
|
||||
function unwindWork(workInProgress: Fiber, renderLanes: Lanes) {
|
||||
function unwindWork(
|
||||
current: Fiber | null,
|
||||
workInProgress: Fiber,
|
||||
renderLanes: Lanes,
|
||||
) {
|
||||
// Note: This intentionally doesn't check if we're hydrating because comparing
|
||||
// to the current tree provider fiber is just as fast and less error-prone.
|
||||
// Ideally we would have a special version of the work loop only
|
||||
@@ -153,8 +157,7 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) {
|
||||
case LegacyHiddenComponent:
|
||||
popRenderLanes(workInProgress);
|
||||
if (enableCache) {
|
||||
const spawnedCachePool: SpawnedCachePool | null = (workInProgress.updateQueue: any);
|
||||
if (spawnedCachePool !== null) {
|
||||
if (current !== null) {
|
||||
popCachePool(workInProgress);
|
||||
}
|
||||
}
|
||||
@@ -170,7 +173,11 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) {
|
||||
}
|
||||
}
|
||||
|
||||
function unwindInterruptedWork(interruptedWork: Fiber, renderLanes: Lanes) {
|
||||
function unwindInterruptedWork(
|
||||
current: Fiber | null,
|
||||
interruptedWork: Fiber,
|
||||
renderLanes: Lanes,
|
||||
) {
|
||||
// Note: This intentionally doesn't check if we're hydrating because comparing
|
||||
// to the current tree provider fiber is just as fast and less error-prone.
|
||||
// Ideally we would have a special version of the work loop only
|
||||
@@ -218,8 +225,7 @@ function unwindInterruptedWork(interruptedWork: Fiber, renderLanes: Lanes) {
|
||||
case LegacyHiddenComponent:
|
||||
popRenderLanes(interruptedWork);
|
||||
if (enableCache) {
|
||||
const spawnedCachePool: SpawnedCachePool | null = (interruptedWork.updateQueue: any);
|
||||
if (spawnedCachePool !== null) {
|
||||
if (current !== null) {
|
||||
popCachePool(interruptedWork);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import type {ReactContext} from 'shared/ReactTypes';
|
||||
import type {Fiber, FiberRoot} from './ReactInternalTypes';
|
||||
import type {Lanes} from './ReactFiberLane.old';
|
||||
import type {SuspenseState} from './ReactFiberSuspenseComponent.old';
|
||||
import type {Cache, SpawnedCachePool} from './ReactFiberCacheComponent.old';
|
||||
import type {Cache} from './ReactFiberCacheComponent.old';
|
||||
|
||||
import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.old';
|
||||
import {
|
||||
@@ -52,7 +52,11 @@ import {
|
||||
import {transferActualDuration} from './ReactProfilerTimer.old';
|
||||
import {popTreeContext} from './ReactFiberTreeContext.old';
|
||||
|
||||
function unwindWork(workInProgress: Fiber, renderLanes: Lanes) {
|
||||
function unwindWork(
|
||||
current: Fiber | null,
|
||||
workInProgress: Fiber,
|
||||
renderLanes: Lanes,
|
||||
) {
|
||||
// Note: This intentionally doesn't check if we're hydrating because comparing
|
||||
// to the current tree provider fiber is just as fast and less error-prone.
|
||||
// Ideally we would have a special version of the work loop only
|
||||
@@ -153,8 +157,7 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) {
|
||||
case LegacyHiddenComponent:
|
||||
popRenderLanes(workInProgress);
|
||||
if (enableCache) {
|
||||
const spawnedCachePool: SpawnedCachePool | null = (workInProgress.updateQueue: any);
|
||||
if (spawnedCachePool !== null) {
|
||||
if (current !== null) {
|
||||
popCachePool(workInProgress);
|
||||
}
|
||||
}
|
||||
@@ -170,7 +173,11 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) {
|
||||
}
|
||||
}
|
||||
|
||||
function unwindInterruptedWork(interruptedWork: Fiber, renderLanes: Lanes) {
|
||||
function unwindInterruptedWork(
|
||||
current: Fiber | null,
|
||||
interruptedWork: Fiber,
|
||||
renderLanes: Lanes,
|
||||
) {
|
||||
// Note: This intentionally doesn't check if we're hydrating because comparing
|
||||
// to the current tree provider fiber is just as fast and less error-prone.
|
||||
// Ideally we would have a special version of the work loop only
|
||||
@@ -218,8 +225,7 @@ function unwindInterruptedWork(interruptedWork: Fiber, renderLanes: Lanes) {
|
||||
case LegacyHiddenComponent:
|
||||
popRenderLanes(interruptedWork);
|
||||
if (enableCache) {
|
||||
const spawnedCachePool: SpawnedCachePool | null = (interruptedWork.updateQueue: any);
|
||||
if (spawnedCachePool !== null) {
|
||||
if (current !== null) {
|
||||
popCachePool(interruptedWork);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1405,7 +1405,12 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes) {
|
||||
if (workInProgress !== null) {
|
||||
let interruptedWork = workInProgress.return;
|
||||
while (interruptedWork !== null) {
|
||||
unwindInterruptedWork(interruptedWork, workInProgressRootRenderLanes);
|
||||
const current = interruptedWork.alternate;
|
||||
unwindInterruptedWork(
|
||||
current,
|
||||
interruptedWork,
|
||||
workInProgressRootRenderLanes,
|
||||
);
|
||||
interruptedWork = interruptedWork.return;
|
||||
}
|
||||
}
|
||||
@@ -1829,7 +1834,7 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
|
||||
// This fiber did not complete because something threw. Pop values off
|
||||
// the stack without entering the complete phase. If this is a boundary,
|
||||
// capture values if possible.
|
||||
const next = unwindWork(completedWork, subtreeRenderLanes);
|
||||
const next = unwindWork(current, completedWork, subtreeRenderLanes);
|
||||
|
||||
// Because this fiber did not complete, don't reset its lanes.
|
||||
|
||||
@@ -2814,7 +2819,7 @@ if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
|
||||
// same fiber again.
|
||||
|
||||
// Unwind the failed stack frame
|
||||
unwindInterruptedWork(unitOfWork, workInProgressRootRenderLanes);
|
||||
unwindInterruptedWork(current, unitOfWork, workInProgressRootRenderLanes);
|
||||
|
||||
// Restore the original properties of the fiber.
|
||||
assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);
|
||||
|
||||
@@ -1405,7 +1405,12 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes) {
|
||||
if (workInProgress !== null) {
|
||||
let interruptedWork = workInProgress.return;
|
||||
while (interruptedWork !== null) {
|
||||
unwindInterruptedWork(interruptedWork, workInProgressRootRenderLanes);
|
||||
const current = interruptedWork.alternate;
|
||||
unwindInterruptedWork(
|
||||
current,
|
||||
interruptedWork,
|
||||
workInProgressRootRenderLanes,
|
||||
);
|
||||
interruptedWork = interruptedWork.return;
|
||||
}
|
||||
}
|
||||
@@ -1829,7 +1834,7 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
|
||||
// This fiber did not complete because something threw. Pop values off
|
||||
// the stack without entering the complete phase. If this is a boundary,
|
||||
// capture values if possible.
|
||||
const next = unwindWork(completedWork, subtreeRenderLanes);
|
||||
const next = unwindWork(current, completedWork, subtreeRenderLanes);
|
||||
|
||||
// Because this fiber did not complete, don't reset its lanes.
|
||||
|
||||
@@ -2814,7 +2819,7 @@ if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
|
||||
// same fiber again.
|
||||
|
||||
// Unwind the failed stack frame
|
||||
unwindInterruptedWork(unitOfWork, workInProgressRootRenderLanes);
|
||||
unwindInterruptedWork(current, unitOfWork, workInProgressRootRenderLanes);
|
||||
|
||||
// Restore the original properties of the fiber.
|
||||
assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);
|
||||
|
||||
Reference in New Issue
Block a user