From 179e40ef0d6f0dec9d912175929345a6184d6769 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 2 Feb 2022 18:34:11 -0500 Subject: [PATCH 1/2] remove dependency on updateQueue for React Cache --- .../src/ReactFiberBeginWork.new.js | 15 +++++------- .../src/ReactFiberBeginWork.old.js | 15 +++++------- .../src/ReactFiberCompleteWork.new.js | 12 +++++++--- .../src/ReactFiberCompleteWork.old.js | 12 +++++++--- .../src/ReactFiberUnwindWork.new.js | 23 +++++++++++++++---- .../src/ReactFiberUnwindWork.old.js | 23 +++++++++++++++---- 6 files changed, 66 insertions(+), 34 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index 521a75d11dcb7..ca59103b6eb3b 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -664,10 +664,13 @@ function updateOffscreenComponent( nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); if (enableCache) { // Save the cache pool so we can resume later. + const prevCachePool = prevState.cachePool; + if (prevCachePool !== null) { + // push the cache pool even though we're going to bail out + // because otherwise there'd be a context mismatch + restoreSpawnedCachePool(workInProgress, prevCachePool); + } 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; @@ -759,12 +762,6 @@ function updateOffscreenComponent( 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 diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index 471bb11d941da..fedb04074e27e 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -664,10 +664,13 @@ function updateOffscreenComponent( nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); if (enableCache) { // Save the cache pool so we can resume later. + const prevCachePool = prevState.cachePool; + if (prevCachePool !== null) { + // push the cache pool even though we're going to bail out + // because otherwise there'd be a context mismatch + restoreSpawnedCachePool(workInProgress, prevCachePool); + } 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; @@ -759,12 +762,6 @@ function updateOffscreenComponent( 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 diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js index 39f724c76df92..54b291157b526 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js @@ -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, @@ -1550,8 +1550,14 @@ function completeWork( // Run passive effects to retain/release the cache. workInProgress.flags |= Passive; } - const spawnedCachePool: SpawnedCachePool | null = (workInProgress.updateQueue: any); - if (spawnedCachePool !== null) { + let prevState: OffscreenState | null = null; + if ( + workInProgress.alternate !== null && + workInProgress.alternate.memoizedState !== null + ) { + prevState = workInProgress.alternate.memoizedState; + } + if (prevState !== null && prevState.cachePool !== null) { popCachePool(workInProgress); } } diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js index c7baf36d16c47..134c610ef5c6f 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js @@ -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, @@ -1550,8 +1550,14 @@ function completeWork( // Run passive effects to retain/release the cache. workInProgress.flags |= Passive; } - const spawnedCachePool: SpawnedCachePool | null = (workInProgress.updateQueue: any); - if (spawnedCachePool !== null) { + let prevState: OffscreenState | null = null; + if ( + workInProgress.alternate !== null && + workInProgress.alternate.memoizedState !== null + ) { + prevState = workInProgress.alternate.memoizedState; + } + if (prevState !== null && prevState.cachePool !== null) { popCachePool(workInProgress); } } diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js index a43c021d987e5..808c6de80464d 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js @@ -11,7 +11,8 @@ 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 type {OffscreenState} from './ReactFiberOffscreenComponent'; import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.new'; import { @@ -152,9 +153,15 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) { case OffscreenComponent: case LegacyHiddenComponent: popRenderLanes(workInProgress); + let prevState: OffscreenState | null = null; if (enableCache) { - const spawnedCachePool: SpawnedCachePool | null = (workInProgress.updateQueue: any); - if (spawnedCachePool !== null) { + if ( + workInProgress.alternate !== null && + workInProgress.alternate.memoizedState !== null + ) { + prevState = workInProgress.alternate.memoizedState; + } + if (prevState !== null && prevState.cachePool !== null) { popCachePool(workInProgress); } } @@ -218,8 +225,14 @@ function unwindInterruptedWork(interruptedWork: Fiber, renderLanes: Lanes) { case LegacyHiddenComponent: popRenderLanes(interruptedWork); if (enableCache) { - const spawnedCachePool: SpawnedCachePool | null = (interruptedWork.updateQueue: any); - if (spawnedCachePool !== null) { + let prevState: OffscreenState | null = null; + if ( + interruptedWork.alternate !== null && + interruptedWork.alternate.memoizedState !== null + ) { + prevState = interruptedWork.alternate.memoizedState; + } + if (prevState !== null && prevState.cachePool !== null) { popCachePool(interruptedWork); } } diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js index e0cf7cc2f0fcc..f318751f06ee5 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js @@ -11,7 +11,8 @@ 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 type {OffscreenState} from './ReactFiberOffscreenComponent'; import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.old'; import { @@ -152,9 +153,15 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) { case OffscreenComponent: case LegacyHiddenComponent: popRenderLanes(workInProgress); + let prevState: OffscreenState | null = null; if (enableCache) { - const spawnedCachePool: SpawnedCachePool | null = (workInProgress.updateQueue: any); - if (spawnedCachePool !== null) { + if ( + workInProgress.alternate !== null && + workInProgress.alternate.memoizedState !== null + ) { + prevState = workInProgress.alternate.memoizedState; + } + if (prevState !== null && prevState.cachePool !== null) { popCachePool(workInProgress); } } @@ -218,8 +225,14 @@ function unwindInterruptedWork(interruptedWork: Fiber, renderLanes: Lanes) { case LegacyHiddenComponent: popRenderLanes(interruptedWork); if (enableCache) { - const spawnedCachePool: SpawnedCachePool | null = (interruptedWork.updateQueue: any); - if (spawnedCachePool !== null) { + let prevState: OffscreenState | null = null; + if ( + interruptedWork.alternate !== null && + interruptedWork.alternate.memoizedState !== null + ) { + prevState = interruptedWork.alternate.memoizedState; + } + if (prevState !== null && prevState.cachePool !== null) { popCachePool(interruptedWork); } } From c8157b2e8121ee21ff57a42858e6723319274bbf Mon Sep 17 00:00:00 2001 From: Luna Date: Thu, 17 Feb 2022 18:36:28 -0500 Subject: [PATCH 2/2] tmp --- .../src/ReactFiberBeginWork.new.js | 67 ++++++++++--------- .../src/ReactFiberBeginWork.old.js | 67 ++++++++++--------- .../src/ReactFiberCacheComponent.new.js | 26 +++---- .../src/ReactFiberCacheComponent.old.js | 26 +++---- .../src/ReactFiberCompleteWork.new.js | 25 +++---- .../src/ReactFiberCompleteWork.old.js | 25 +++---- .../src/ReactFiberUnwindWork.new.js | 31 ++++----- .../src/ReactFiberUnwindWork.old.js | 31 ++++----- .../src/ReactFiberWorkLoop.new.js | 11 ++- .../src/ReactFiberWorkLoop.old.js | 11 ++- 10 files changed, 146 insertions(+), 174 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index ca59103b6eb3b..8bf7e78bc2c77 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -236,7 +236,7 @@ import { pushRootCachePool, CacheContext, getSuspendedCachePool, - restoreSpawnedCachePool, + pushSpawnedCachePool, getOffscreenDeferredCachePool, } from './ReactFiberCacheComponent.new'; import {createCapturedValue} from './ReactCapturedValue'; @@ -637,11 +637,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' @@ -654,8 +649,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; @@ -664,12 +667,6 @@ function updateOffscreenComponent( nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); if (enableCache) { // Save the cache pool so we can resume later. - const prevCachePool = prevState.cachePool; - if (prevCachePool !== null) { - // push the cache pool even though we're going to bail out - // because otherwise there'd be a context mismatch - restoreSpawnedCachePool(workInProgress, prevCachePool); - } spawnedCachePool = getOffscreenDeferredCachePool(); } } else { @@ -686,6 +683,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); @@ -706,19 +711,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, @@ -728,6 +720,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 { @@ -743,12 +743,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 @@ -758,6 +753,15 @@ 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); } @@ -2071,6 +2075,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { const nextPrimaryChildren = nextProps.children; const nextFallbackChildren = nextProps.fallback; + if (showFallback) { const fallbackFragment = mountSuspenseFallbackChildren( workInProgress, diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index fedb04074e27e..1febc036f7219 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -236,7 +236,7 @@ import { pushRootCachePool, CacheContext, getSuspendedCachePool, - restoreSpawnedCachePool, + pushSpawnedCachePool, getOffscreenDeferredCachePool, } from './ReactFiberCacheComponent.old'; import {createCapturedValue} from './ReactCapturedValue'; @@ -637,11 +637,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' @@ -654,8 +649,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; @@ -664,12 +667,6 @@ function updateOffscreenComponent( nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); if (enableCache) { // Save the cache pool so we can resume later. - const prevCachePool = prevState.cachePool; - if (prevCachePool !== null) { - // push the cache pool even though we're going to bail out - // because otherwise there'd be a context mismatch - restoreSpawnedCachePool(workInProgress, prevCachePool); - } spawnedCachePool = getOffscreenDeferredCachePool(); } } else { @@ -686,6 +683,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); @@ -706,19 +711,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, @@ -728,6 +720,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 { @@ -743,12 +743,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 @@ -758,6 +753,15 @@ 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); } @@ -2071,6 +2075,7 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) { const nextPrimaryChildren = nextProps.children; const nextFallbackChildren = nextProps.fallback; + if (showFallback) { const fallbackFragment = mountSuspenseFallbackChildren( workInProgress, diff --git a/packages/react-reconciler/src/ReactFiberCacheComponent.new.js b/packages/react-reconciler/src/ReactFiberCacheComponent.new.js index cf851af6e3de3..3d1db8124b692 100644 --- a/packages/react-reconciler/src/ReactFiberCacheComponent.new.js +++ b/packages/react-reconciler/src/ReactFiberCacheComponent.new.js @@ -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; + + if (prevCachePool === null) { + push(resumedCache, resumedCache.current, offscreenWorkInProgress); } 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; } } @@ -228,6 +217,7 @@ export function popCachePool(workInProgress: Fiber) { if (!enableCache) { return; } + pop(resumedCache, workInProgress); } diff --git a/packages/react-reconciler/src/ReactFiberCacheComponent.old.js b/packages/react-reconciler/src/ReactFiberCacheComponent.old.js index 692dba781302e..74dc9a449a507 100644 --- a/packages/react-reconciler/src/ReactFiberCacheComponent.old.js +++ b/packages/react-reconciler/src/ReactFiberCacheComponent.old.js @@ -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; + + if (prevCachePool === null) { + push(resumedCache, resumedCache.current, offscreenWorkInProgress); } 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; } } @@ -228,6 +217,7 @@ export function popCachePool(workInProgress: Fiber) { if (!enableCache) { return; } + pop(resumedCache, workInProgress); } diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js index 54b291157b526..bb01e2b8a2a26 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js @@ -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,14 +1550,7 @@ function completeWork( // Run passive effects to retain/release the cache. workInProgress.flags |= Passive; } - let prevState: OffscreenState | null = null; - if ( - workInProgress.alternate !== null && - workInProgress.alternate.memoizedState !== null - ) { - prevState = workInProgress.alternate.memoizedState; - } - if (prevState !== null && prevState.cachePool !== null) { + if (current !== null) { popCachePool(workInProgress); } } @@ -1567,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) { diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js index 134c610ef5c6f..0d9de679a0f43 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js @@ -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,14 +1550,7 @@ function completeWork( // Run passive effects to retain/release the cache. workInProgress.flags |= Passive; } - let prevState: OffscreenState | null = null; - if ( - workInProgress.alternate !== null && - workInProgress.alternate.memoizedState !== null - ) { - prevState = workInProgress.alternate.memoizedState; - } - if (prevState !== null && prevState.cachePool !== null) { + if (current !== null) { popCachePool(workInProgress); } } @@ -1567,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) { diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js index 808c6de80464d..aa1b391b0367f 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js @@ -12,7 +12,6 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes'; import type {Lanes} from './ReactFiberLane.new'; import type {SuspenseState} from './ReactFiberSuspenseComponent.new'; import type {Cache} from './ReactFiberCacheComponent.new'; -import type {OffscreenState} from './ReactFiberOffscreenComponent'; import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.new'; import { @@ -53,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,15 +156,8 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) { case OffscreenComponent: case LegacyHiddenComponent: popRenderLanes(workInProgress); - let prevState: OffscreenState | null = null; if (enableCache) { - if ( - workInProgress.alternate !== null && - workInProgress.alternate.memoizedState !== null - ) { - prevState = workInProgress.alternate.memoizedState; - } - if (prevState !== null && prevState.cachePool !== null) { + if (current !== null) { popCachePool(workInProgress); } } @@ -177,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 @@ -225,14 +225,7 @@ function unwindInterruptedWork(interruptedWork: Fiber, renderLanes: Lanes) { case LegacyHiddenComponent: popRenderLanes(interruptedWork); if (enableCache) { - let prevState: OffscreenState | null = null; - if ( - interruptedWork.alternate !== null && - interruptedWork.alternate.memoizedState !== null - ) { - prevState = interruptedWork.alternate.memoizedState; - } - if (prevState !== null && prevState.cachePool !== null) { + if (current !== null) { popCachePool(interruptedWork); } } diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js index f318751f06ee5..cb5df61782bc3 100644 --- a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js +++ b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js @@ -12,7 +12,6 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes'; import type {Lanes} from './ReactFiberLane.old'; import type {SuspenseState} from './ReactFiberSuspenseComponent.old'; import type {Cache} from './ReactFiberCacheComponent.old'; -import type {OffscreenState} from './ReactFiberOffscreenComponent'; import {resetWorkInProgressVersions as resetMutableSourceWorkInProgressVersions} from './ReactMutableSource.old'; import { @@ -53,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,15 +156,8 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) { case OffscreenComponent: case LegacyHiddenComponent: popRenderLanes(workInProgress); - let prevState: OffscreenState | null = null; if (enableCache) { - if ( - workInProgress.alternate !== null && - workInProgress.alternate.memoizedState !== null - ) { - prevState = workInProgress.alternate.memoizedState; - } - if (prevState !== null && prevState.cachePool !== null) { + if (current !== null) { popCachePool(workInProgress); } } @@ -177,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 @@ -225,14 +225,7 @@ function unwindInterruptedWork(interruptedWork: Fiber, renderLanes: Lanes) { case LegacyHiddenComponent: popRenderLanes(interruptedWork); if (enableCache) { - let prevState: OffscreenState | null = null; - if ( - interruptedWork.alternate !== null && - interruptedWork.alternate.memoizedState !== null - ) { - prevState = interruptedWork.alternate.memoizedState; - } - if (prevState !== null && prevState.cachePool !== null) { + if (current !== null) { popCachePool(interruptedWork); } } diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js index 4a1880e0cf848..540d5625c891e 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js @@ -1397,7 +1397,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; } } @@ -1821,7 +1826,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. @@ -2817,7 +2822,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); diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js index b9fada5bd00b0..d24ba77bdff3f 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js @@ -1397,7 +1397,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; } } @@ -1821,7 +1826,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. @@ -2817,7 +2822,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);