@samitouri / QOS-React-2 / commits / feefe437fe

Refactor Cache Code (#23393)

This PR refactors the cache code by moving it out of ReactFiberCacheComponent to ReactFiberTransitionPool in anticipation of it being reused by multiple stacks (ie. transition tracing)

Luna Ruan committed Mar 1, 2022 at 15:39 UTC feefe437fe160cb99facbf9444ad6a32a901c6a3
11 files changed +518 -354
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+18 -19
@@ -229,15 +229,7 @@ import {
229 getWorkInProgressTransitions,
230 } from './ReactFiberWorkLoop.new';
231 import {setWorkInProgressVersion} from './ReactMutableSource.new';
232 -import {
233 - requestCacheFromPool,
234 - pushCacheProvider,
235 - pushRootCachePool,
236 - CacheContext,
237 - getSuspendedCachePool,
238 - pushSpawnedCachePool,
239 - getOffscreenDeferredCachePool,
240 -} from './ReactFiberCacheComponent.new';
232 +import {pushCacheProvider, CacheContext} from './ReactFiberCacheComponent.new';
233 import {createCapturedValue} from './ReactCapturedValue';
234 import {createClassErrorUpdate} from './ReactFiberThrow.new';
235 import {completeSuspendedOffscreenHostContainer} from './ReactFiberCompleteWork.new';
@@ -248,6 +240,13 @@ import {
240 pushTreeId,
241 pushMaterializedTreeId,
242 } from './ReactFiberTreeContext.new';
243 +import {
244 + requestCacheFromPool,
245 + pushRootTransition,
246 + getSuspendedCache,
247 + pushTransition,
248 + getOffscreenDeferredCache,
249 +} from './ReactFiberTransition.new';
250
251 const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
252
@@ -652,7 +651,7 @@ function updateOffscreenComponent(
651 // push the cache pool even though we're going to bail out
652 // because otherwise there'd be a context mismatch
653 if (current !== null) {
655 - pushSpawnedCachePool(workInProgress, null);
654 + pushTransition(workInProgress, null);
655 }
656 }
657 pushRenderLanes(workInProgress, renderLanes);
@@ -666,7 +665,7 @@ function updateOffscreenComponent(
665 nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes);
666 if (enableCache) {
667 // Save the cache pool so we can resume later.
669 - spawnedCachePool = getOffscreenDeferredCachePool();
668 + spawnedCachePool = getOffscreenDeferredCache();
669 }
670 } else {
671 nextBaseLanes = renderLanes;
@@ -686,7 +685,7 @@ function updateOffscreenComponent(
685 // push the cache pool even though we're going to bail out
686 // because otherwise there'd be a context mismatch
687 if (current !== null) {
689 - pushSpawnedCachePool(workInProgress, null);
688 + pushTransition(workInProgress, null);
689 }
690 }
691
@@ -724,7 +723,7 @@ function updateOffscreenComponent(
723 // using the same cache. Unless the parent changed, since that means
724 // there was a refresh.
725 const prevCachePool = prevState !== null ? prevState.cachePool : null;
727 - pushSpawnedCachePool(workInProgress, prevCachePool);
726 + pushTransition(workInProgress, prevCachePool);
727 }
728
729 pushRenderLanes(workInProgress, subtreeRenderLanes);
@@ -742,7 +741,7 @@ function updateOffscreenComponent(
741 // using the same cache. Unless the parent changed, since that means
742 // there was a refresh.
743 const prevCachePool = prevState.cachePool;
745 - pushSpawnedCachePool(workInProgress, prevCachePool);
744 + pushTransition(workInProgress, prevCachePool);
745 }
746
747 // Since we're not hidden anymore, reset the state
@@ -758,7 +757,7 @@ function updateOffscreenComponent(
757 // using the same cache. Unless the parent changed, since that means
758 // there was a refresh.
759 if (current !== null) {
761 - pushSpawnedCachePool(workInProgress, null);
760 + pushTransition(workInProgress, null);
761 }
762 }
763 }
@@ -1329,7 +1328,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1328
1329 if (enableCache) {
1330 const nextCache: Cache = nextState.cache;
1332 - pushRootCachePool(root);
1331 + pushRootTransition(root);
1332 pushCacheProvider(workInProgress, nextCache);
1333 if (nextCache !== prevState.cache) {
1334 // The root cache refreshed.
@@ -1910,7 +1909,7 @@ const SUSPENDED_MARKER: SuspenseState = {
1909 function mountSuspenseOffscreenState(renderLanes: Lanes): OffscreenState {
1910 return {
1911 baseLanes: renderLanes,
1913 - cachePool: getSuspendedCachePool(),
1912 + cachePool: getSuspendedCache(),
1913 };
1914 }
1915
@@ -1939,7 +1938,7 @@ function updateSuspenseOffscreenState(
1938 }
1939 } else {
1940 // If there's no previous cache pool, grab the current one.
1942 - cachePool = getSuspendedCachePool();
1941 + cachePool = getSuspendedCache();
1942 }
1943 }
1944 return {
@@ -3504,7 +3503,7 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3503 if (enableCache) {
3504 const cache: Cache = current.memoizedState.cache;
3505 pushCacheProvider(workInProgress, cache);
3507 - pushRootCachePool(root);
3506 + pushRootTransition(root);
3507 }
3508 if (enableTransitionTracing) {
3509 workInProgress.memoizedState.transitions = getWorkInProgressTransitions();
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+18 -19
@@ -229,15 +229,7 @@ import {
229 getWorkInProgressTransitions,
230 } from './ReactFiberWorkLoop.old';
231 import {setWorkInProgressVersion} from './ReactMutableSource.old';
232 -import {
233 - requestCacheFromPool,
234 - pushCacheProvider,
235 - pushRootCachePool,
236 - CacheContext,
237 - getSuspendedCachePool,
238 - pushSpawnedCachePool,
239 - getOffscreenDeferredCachePool,
240 -} from './ReactFiberCacheComponent.old';
232 +import {pushCacheProvider, CacheContext} from './ReactFiberCacheComponent.old';
233 import {createCapturedValue} from './ReactCapturedValue';
234 import {createClassErrorUpdate} from './ReactFiberThrow.old';
235 import {completeSuspendedOffscreenHostContainer} from './ReactFiberCompleteWork.old';
@@ -248,6 +240,13 @@ import {
240 pushTreeId,
241 pushMaterializedTreeId,
242 } from './ReactFiberTreeContext.old';
243 +import {
244 + requestCacheFromPool,
245 + pushRootTransition,
246 + getSuspendedCache,
247 + pushTransition,
248 + getOffscreenDeferredCache,
249 +} from './ReactFiberTransition.old';
250
251 const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
252
@@ -652,7 +651,7 @@ function updateOffscreenComponent(
651 // push the cache pool even though we're going to bail out
652 // because otherwise there'd be a context mismatch
653 if (current !== null) {
655 - pushSpawnedCachePool(workInProgress, null);
654 + pushTransition(workInProgress, null);
655 }
656 }
657 pushRenderLanes(workInProgress, renderLanes);
@@ -666,7 +665,7 @@ function updateOffscreenComponent(
665 nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes);
666 if (enableCache) {
667 // Save the cache pool so we can resume later.
669 - spawnedCachePool = getOffscreenDeferredCachePool();
668 + spawnedCachePool = getOffscreenDeferredCache();
669 }
670 } else {
671 nextBaseLanes = renderLanes;
@@ -686,7 +685,7 @@ function updateOffscreenComponent(
685 // push the cache pool even though we're going to bail out
686 // because otherwise there'd be a context mismatch
687 if (current !== null) {
689 - pushSpawnedCachePool(workInProgress, null);
688 + pushTransition(workInProgress, null);
689 }
690 }
691
@@ -724,7 +723,7 @@ function updateOffscreenComponent(
723 // using the same cache. Unless the parent changed, since that means
724 // there was a refresh.
725 const prevCachePool = prevState !== null ? prevState.cachePool : null;
727 - pushSpawnedCachePool(workInProgress, prevCachePool);
726 + pushTransition(workInProgress, prevCachePool);
727 }
728
729 pushRenderLanes(workInProgress, subtreeRenderLanes);
@@ -742,7 +741,7 @@ function updateOffscreenComponent(
741 // using the same cache. Unless the parent changed, since that means
742 // there was a refresh.
743 const prevCachePool = prevState.cachePool;
745 - pushSpawnedCachePool(workInProgress, prevCachePool);
744 + pushTransition(workInProgress, prevCachePool);
745 }
746
747 // Since we're not hidden anymore, reset the state
@@ -758,7 +757,7 @@ function updateOffscreenComponent(
757 // using the same cache. Unless the parent changed, since that means
758 // there was a refresh.
759 if (current !== null) {
761 - pushSpawnedCachePool(workInProgress, null);
760 + pushTransition(workInProgress, null);
761 }
762 }
763 }
@@ -1329,7 +1328,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1328
1329 if (enableCache) {
1330 const nextCache: Cache = nextState.cache;
1332 - pushRootCachePool(root);
1331 + pushRootTransition(root);
1332 pushCacheProvider(workInProgress, nextCache);
1333 if (nextCache !== prevState.cache) {
1334 // The root cache refreshed.
@@ -1910,7 +1909,7 @@ const SUSPENDED_MARKER: SuspenseState = {
1909 function mountSuspenseOffscreenState(renderLanes: Lanes): OffscreenState {
1910 return {
1911 baseLanes: renderLanes,
1913 - cachePool: getSuspendedCachePool(),
1912 + cachePool: getSuspendedCache(),
1913 };
1914 }
1915
@@ -1939,7 +1938,7 @@ function updateSuspenseOffscreenState(
1938 }
1939 } else {
1940 // If there's no previous cache pool, grab the current one.
1942 - cachePool = getSuspendedCachePool();
1941 + cachePool = getSuspendedCache();
1942 }
1943 }
1944 return {
@@ -3504,7 +3503,7 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3503 if (enableCache) {
3504 const cache: Cache = current.memoizedState.cache;
3505 pushCacheProvider(workInProgress, cache);
3507 - pushRootCachePool(root);
3506 + pushRootTransition(root);
3507 }
3508 if (enableTransitionTracing) {
3509 workInProgress.memoizedState.transitions = getWorkInProgressTransitions();
packages/react-reconciler/src/ReactFiberCacheComponent.new.js
-142
@@ -8,18 +8,12 @@
8 */
9
10 import type {ReactContext} from 'shared/ReactTypes';
11 -import type {FiberRoot} from './ReactInternalTypes';
12 -import type {Lanes} from './ReactFiberLane.new';
13 -import type {StackCursor} from './ReactFiberStack.new';
11
12 import {enableCache} from 'shared/ReactFeatureFlags';
13 import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
14
18 -import {isPrimaryRenderer} from './ReactFiberHostConfig';
19 -import {createCursor, push, pop} from './ReactFiberStack.new';
15 import {pushProvider, popProvider} from './ReactFiberNewContext.new';
16 import * as Scheduler from 'scheduler';
22 -import {getWorkInProgressRoot} from './ReactFiberWorkLoop.new';
17
18 export type Cache = {|
19 controller: AbortController,
@@ -62,10 +56,6 @@ if (__DEV__ && enableCache) {
56 CacheContext._currentRenderer2 = null;
57 }
58
65 -// When retrying a Suspense/Offscreen boundary, we restore the cache that was
66 -// used during the previous render by placing it here, on the stack.
67 -const resumedCache: StackCursor<Cache | null> = createCursor(null);
68 -
59 // Creates a new empty Cache instance with a ref-count of 0. The caller is responsible
60 // for retaining the cache once it is in use (retainCache), and releasing the cache
61 // once it is no longer needed (releaseCache).
@@ -131,135 +121,3 @@ export function popCacheProvider(workInProgress: Fiber, cache: Cache) {
121 }
122 popProvider(CacheContext, workInProgress);
123 }
134 -
135 -function peekCacheFromPool(): Cache | null {
136 - if (!enableCache) {
137 - return (null: any);
138 - }
139 -
140 - // Check if the cache pool already has a cache we can use.
141 -
142 - // If we're rendering inside a Suspense boundary that is currently hidden,
143 - // we should use the same cache that we used during the previous render, if
144 - // one exists.
145 - const cacheResumedFromPreviousRender = resumedCache.current;
146 - if (cacheResumedFromPreviousRender !== null) {
147 - return cacheResumedFromPreviousRender;
148 - }
149 -
150 - // Otherwise, check the root's cache pool.
151 - const root = (getWorkInProgressRoot(): any);
152 - const cacheFromRootCachePool = root.pooledCache;
153 -
154 - return cacheFromRootCachePool;
155 -}
156 -
157 -export function requestCacheFromPool(renderLanes: Lanes): Cache {
158 - // Similar to previous function, except if there's not already a cache in the
159 - // pool, we allocate a new one.
160 - const cacheFromPool = peekCacheFromPool();
161 - if (cacheFromPool !== null) {
162 - return cacheFromPool;
163 - }
164 -
165 - // Create a fresh cache and add it to the root cache pool. A cache can have
166 - // multiple owners:
167 - // - A cache pool that lives on the FiberRoot. This is where all fresh caches
168 - // are originally created (TODO: except during refreshes, until we implement
169 - // this correctly). The root takes ownership immediately when the cache is
170 - // created. Conceptually, root.pooledCache is an Option<Arc<Cache>> (owned),
171 - // and the return value of this function is a &Arc<Cache> (borrowed).
172 - // - One of several fiber types: host root, cache boundary, suspense
173 - // component. These retain and release in the commit phase.
174 -
175 - const root = (getWorkInProgressRoot(): any);
176 - const freshCache = createCache();
177 - root.pooledCache = freshCache;
178 - retainCache(freshCache);
179 - if (freshCache !== null) {
180 - root.pooledCacheLanes |= renderLanes;
181 - }
182 - return freshCache;
183 -}
184 -
185 -export function pushRootCachePool(root: FiberRoot) {
186 - if (!enableCache) {
187 - return;
188 - }
189 - // Note: This function currently does nothing but I'll leave it here for
190 - // code organization purposes in case that changes.
191 -}
192 -
193 -export function popRootCachePool(root: FiberRoot, renderLanes: Lanes) {
194 - if (!enableCache) {
195 - return;
196 - }
197 - // Note: This function currently does nothing but I'll leave it here for
198 - // code organization purposes in case that changes.
199 -}
200 -
201 -export function pushSpawnedCachePool(
202 - offscreenWorkInProgress: Fiber,
203 - prevCachePool: SpawnedCachePool | null,
204 -): void {
205 - if (!enableCache) {
206 - return;
207 - }
208 -
209 - if (prevCachePool === null) {
210 - push(resumedCache, resumedCache.current, offscreenWorkInProgress);
211 - } else {
212 - push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
213 - }
214 -}
215 -
216 -export function popCachePool(workInProgress: Fiber) {
217 - if (!enableCache) {
218 - return;
219 - }
220 -
221 - pop(resumedCache, workInProgress);
222 -}
223 -
224 -export function getSuspendedCachePool(): SpawnedCachePool | null {
225 - if (!enableCache) {
226 - return null;
227 - }
228 - // This function is called when a Suspense boundary suspends. It returns the
229 - // cache that would have been used to render fresh data during this render,
230 - // if there was any, so that we can resume rendering with the same cache when
231 - // we receive more data.
232 - const cacheFromPool = peekCacheFromPool();
233 - if (cacheFromPool === null) {
234 - return null;
235 - }
236 -
237 - return {
238 - // We must also save the parent, so that when we resume we can detect
239 - // a refresh.
240 - parent: isPrimaryRenderer
241 - ? CacheContext._currentValue
242 - : CacheContext._currentValue2,
243 - pool: cacheFromPool,
244 - };
245 -}
246 -
247 -export function getOffscreenDeferredCachePool(): SpawnedCachePool | null {
248 - if (!enableCache) {
249 - return null;
250 - }
251 -
252 - const cacheFromPool = peekCacheFromPool();
253 - if (cacheFromPool === null) {
254 - return null;
255 - }
256 -
257 - return {
258 - // We must also store the parent, so that when we resume we can detect
259 - // a refresh.
260 - parent: isPrimaryRenderer
261 - ? CacheContext._currentValue
262 - : CacheContext._currentValue2,
263 - pool: cacheFromPool,
264 - };
265 -}
packages/react-reconciler/src/ReactFiberCacheComponent.old.js
-142
@@ -8,18 +8,12 @@
8 */
9
10 import type {ReactContext} from 'shared/ReactTypes';
11 -import type {FiberRoot} from './ReactInternalTypes';
12 -import type {Lanes} from './ReactFiberLane.old';
13 -import type {StackCursor} from './ReactFiberStack.old';
11
12 import {enableCache} from 'shared/ReactFeatureFlags';
13 import {REACT_CONTEXT_TYPE} from 'shared/ReactSymbols';
14
18 -import {isPrimaryRenderer} from './ReactFiberHostConfig';
19 -import {createCursor, push, pop} from './ReactFiberStack.old';
15 import {pushProvider, popProvider} from './ReactFiberNewContext.old';
16 import * as Scheduler from 'scheduler';
22 -import {getWorkInProgressRoot} from './ReactFiberWorkLoop.old';
17
18 export type Cache = {|
19 controller: AbortController,
@@ -62,10 +56,6 @@ if (__DEV__ && enableCache) {
56 CacheContext._currentRenderer2 = null;
57 }
58
65 -// When retrying a Suspense/Offscreen boundary, we restore the cache that was
66 -// used during the previous render by placing it here, on the stack.
67 -const resumedCache: StackCursor<Cache | null> = createCursor(null);
68 -
59 // Creates a new empty Cache instance with a ref-count of 0. The caller is responsible
60 // for retaining the cache once it is in use (retainCache), and releasing the cache
61 // once it is no longer needed (releaseCache).
@@ -131,135 +121,3 @@ export function popCacheProvider(workInProgress: Fiber, cache: Cache) {
121 }
122 popProvider(CacheContext, workInProgress);
123 }
134 -
135 -function peekCacheFromPool(): Cache | null {
136 - if (!enableCache) {
137 - return (null: any);
138 - }
139 -
140 - // Check if the cache pool already has a cache we can use.
141 -
142 - // If we're rendering inside a Suspense boundary that is currently hidden,
143 - // we should use the same cache that we used during the previous render, if
144 - // one exists.
145 - const cacheResumedFromPreviousRender = resumedCache.current;
146 - if (cacheResumedFromPreviousRender !== null) {
147 - return cacheResumedFromPreviousRender;
148 - }
149 -
150 - // Otherwise, check the root's cache pool.
151 - const root = (getWorkInProgressRoot(): any);
152 - const cacheFromRootCachePool = root.pooledCache;
153 -
154 - return cacheFromRootCachePool;
155 -}
156 -
157 -export function requestCacheFromPool(renderLanes: Lanes): Cache {
158 - // Similar to previous function, except if there's not already a cache in the
159 - // pool, we allocate a new one.
160 - const cacheFromPool = peekCacheFromPool();
161 - if (cacheFromPool !== null) {
162 - return cacheFromPool;
163 - }
164 -
165 - // Create a fresh cache and add it to the root cache pool. A cache can have
166 - // multiple owners:
167 - // - A cache pool that lives on the FiberRoot. This is where all fresh caches
168 - // are originally created (TODO: except during refreshes, until we implement
169 - // this correctly). The root takes ownership immediately when the cache is
170 - // created. Conceptually, root.pooledCache is an Option<Arc<Cache>> (owned),
171 - // and the return value of this function is a &Arc<Cache> (borrowed).
172 - // - One of several fiber types: host root, cache boundary, suspense
173 - // component. These retain and release in the commit phase.
174 -
175 - const root = (getWorkInProgressRoot(): any);
176 - const freshCache = createCache();
177 - root.pooledCache = freshCache;
178 - retainCache(freshCache);
179 - if (freshCache !== null) {
180 - root.pooledCacheLanes |= renderLanes;
181 - }
182 - return freshCache;
183 -}
184 -
185 -export function pushRootCachePool(root: FiberRoot) {
186 - if (!enableCache) {
187 - return;
188 - }
189 - // Note: This function currently does nothing but I'll leave it here for
190 - // code organization purposes in case that changes.
191 -}
192 -
193 -export function popRootCachePool(root: FiberRoot, renderLanes: Lanes) {
194 - if (!enableCache) {
195 - return;
196 - }
197 - // Note: This function currently does nothing but I'll leave it here for
198 - // code organization purposes in case that changes.
199 -}
200 -
201 -export function pushSpawnedCachePool(
202 - offscreenWorkInProgress: Fiber,
203 - prevCachePool: SpawnedCachePool | null,
204 -): void {
205 - if (!enableCache) {
206 - return;
207 - }
208 -
209 - if (prevCachePool === null) {
210 - push(resumedCache, resumedCache.current, offscreenWorkInProgress);
211 - } else {
212 - push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
213 - }
214 -}
215 -
216 -export function popCachePool(workInProgress: Fiber) {
217 - if (!enableCache) {
218 - return;
219 - }
220 -
221 - pop(resumedCache, workInProgress);
222 -}
223 -
224 -export function getSuspendedCachePool(): SpawnedCachePool | null {
225 - if (!enableCache) {
226 - return null;
227 - }
228 - // This function is called when a Suspense boundary suspends. It returns the
229 - // cache that would have been used to render fresh data during this render,
230 - // if there was any, so that we can resume rendering with the same cache when
231 - // we receive more data.
232 - const cacheFromPool = peekCacheFromPool();
233 - if (cacheFromPool === null) {
234 - return null;
235 - }
236 -
237 - return {
238 - // We must also save the parent, so that when we resume we can detect
239 - // a refresh.
240 - parent: isPrimaryRenderer
241 - ? CacheContext._currentValue
242 - : CacheContext._currentValue2,
243 - pool: cacheFromPool,
244 - };
245 -}
246 -
247 -export function getOffscreenDeferredCachePool(): SpawnedCachePool | null {
248 - if (!enableCache) {
249 - return null;
250 - }
251 -
252 - const cacheFromPool = peekCacheFromPool();
253 - if (cacheFromPool === null) {
254 - return null;
255 - }
256 -
257 - return {
258 - // We must also store the parent, so that when we resume we can detect
259 - // a refresh.
260 - parent: isPrimaryRenderer
261 - ? CacheContext._currentValue
262 - : CacheContext._currentValue2,
263 - pool: cacheFromPool,
264 - };
265 -}
packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+4 -7
@@ -162,12 +162,9 @@ import {
162 import {resetChildFibers} from './ReactChildFiber.new';
163 import {createScopeInstance} from './ReactFiberScope.new';
164 import {transferActualDuration} from './ReactProfilerTimer.new';
165 -import {
166 - popCacheProvider,
167 - popRootCachePool,
168 - popCachePool,
169 -} from './ReactFiberCacheComponent.new';
165 +import {popCacheProvider} from './ReactFiberCacheComponent.new';
166 import {popTreeContext} from './ReactFiberTreeContext.new';
167 +import {popRootTransition, popTransition} from './ReactFiberTransition.new';
168
169 function markUpdate(workInProgress: Fiber) {
170 // Tag the fiber with an update effect. This turns a Placement into
@@ -864,7 +861,7 @@ function completeWork(
861 case HostRoot: {
862 const fiberRoot = (workInProgress.stateNode: FiberRoot);
863 if (enableCache) {
867 - popRootCachePool(fiberRoot, renderLanes);
864 + popRootTransition(fiberRoot, renderLanes);
865
866 let previousCache: Cache | null = null;
867 if (current !== null) {
@@ -1553,7 +1550,7 @@ function completeWork(
1550 workInProgress.flags |= Passive;
1551 }
1552 if (current !== null) {
1556 - popCachePool(workInProgress);
1553 + popTransition(workInProgress);
1554 }
1555 }
1556
packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+4 -7
@@ -162,12 +162,9 @@ import {
162 import {resetChildFibers} from './ReactChildFiber.old';
163 import {createScopeInstance} from './ReactFiberScope.old';
164 import {transferActualDuration} from './ReactProfilerTimer.old';
165 -import {
166 - popCacheProvider,
167 - popRootCachePool,
168 - popCachePool,
169 -} from './ReactFiberCacheComponent.old';
165 +import {popCacheProvider} from './ReactFiberCacheComponent.old';
166 import {popTreeContext} from './ReactFiberTreeContext.old';
167 +import {popRootTransition, popTransition} from './ReactFiberTransition.old';
168
169 function markUpdate(workInProgress: Fiber) {
170 // Tag the fiber with an update effect. This turns a Placement into
@@ -864,7 +861,7 @@ function completeWork(
861 case HostRoot: {
862 const fiberRoot = (workInProgress.stateNode: FiberRoot);
863 if (enableCache) {
867 - popRootCachePool(fiberRoot, renderLanes);
864 + popRootTransition(fiberRoot, renderLanes);
865
866 let previousCache: Cache | null = null;
867 if (current !== null) {
@@ -1553,7 +1550,7 @@ function completeWork(
1550 workInProgress.flags |= Passive;
1551 }
1552 if (current !== null) {
1556 - popCachePool(workInProgress);
1553 + popTransition(workInProgress);
1554 }
1555 }
1556
packages/react-reconciler/src/ReactFiberTransition.new.js new
+154
@@ -0,0 +1,154 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +import type {FiberRoot} from './ReactInternalTypes';
10 +import type {Lanes} from './ReactFiberLane.new';
11 +import type {StackCursor} from './ReactFiberStack.new';
12 +import type {Cache, SpawnedCachePool} from './ReactFiberCacheComponent.new';
13 +
14 +import {enableCache} from 'shared/ReactFeatureFlags';
15 +import {isPrimaryRenderer} from './ReactFiberHostConfig';
16 +import {createCursor, push, pop} from './ReactFiberStack.new';
17 +import {getWorkInProgressRoot} from './ReactFiberWorkLoop.new';
18 +import {
19 + createCache,
20 + retainCache,
21 + CacheContext,
22 +} from './ReactFiberCacheComponent.new';
23 +
24 +// When retrying a Suspense/Offscreen boundary, we restore the cache that was
25 +// used during the previous render by placing it here, on the stack.
26 +const resumedCache: StackCursor<Cache | null> = createCursor(null);
27 +
28 +function peekCacheFromPool(): Cache | null {
29 + if (!enableCache) {
30 + return (null: any);
31 + }
32 +
33 + // Check if the cache pool already has a cache we can use.
34 +
35 + // If we're rendering inside a Suspense boundary that is currently hidden,
36 + // we should use the same cache that we used during the previous render, if
37 + // one exists.
38 + const cacheResumedFromPreviousRender = resumedCache.current;
39 + if (cacheResumedFromPreviousRender !== null) {
40 + return cacheResumedFromPreviousRender;
41 + }
42 +
43 + // Otherwise, check the root's cache pool.
44 + const root = (getWorkInProgressRoot(): any);
45 + const cacheFromRootCachePool = root.pooledCache;
46 +
47 + return cacheFromRootCachePool;
48 +}
49 +
50 +export function requestCacheFromPool(renderLanes: Lanes): Cache {
51 + // Similar to previous function, except if there's not already a cache in the
52 + // pool, we allocate a new one.
53 + const cacheFromPool = peekCacheFromPool();
54 + if (cacheFromPool !== null) {
55 + return cacheFromPool;
56 + }
57 +
58 + // Create a fresh cache and add it to the root cache pool. A cache can have
59 + // multiple owners:
60 + // - A cache pool that lives on the FiberRoot. This is where all fresh caches
61 + // are originally created (TODO: except during refreshes, until we implement
62 + // this correctly). The root takes ownership immediately when the cache is
63 + // created. Conceptually, root.pooledCache is an Option<Arc<Cache>> (owned),
64 + // and the return value of this function is a &Arc<Cache> (borrowed).
65 + // - One of several fiber types: host root, cache boundary, suspense
66 + // component. These retain and release in the commit phase.
67 +
68 + const root = (getWorkInProgressRoot(): any);
69 + const freshCache = createCache();
70 + root.pooledCache = freshCache;
71 + retainCache(freshCache);
72 + if (freshCache !== null) {
73 + root.pooledCacheLanes |= renderLanes;
74 + }
75 + return freshCache;
76 +}
77 +
78 +export function pushRootTransition(root: FiberRoot) {
79 + if (enableCache) {
80 + return;
81 + }
82 + // Note: This function currently does nothing but I'll leave it here for
83 + // code organization purposes in case that changes.
84 +}
85 +
86 +export function popRootTransition(root: FiberRoot, renderLanes: Lanes) {
87 + if (enableCache) {
88 + return;
89 + }
90 + // Note: This function currently does nothing but I'll leave it here for
91 + // code organization purposes in case that changes.
92 +}
93 +
94 +export function pushTransition(
95 + offscreenWorkInProgress: Fiber,
96 + prevCachePool: SpawnedCachePool | null,
97 +): void {
98 + if (enableCache) {
99 + if (prevCachePool === null) {
100 + push(resumedCache, resumedCache.current, offscreenWorkInProgress);
101 + } else {
102 + push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
103 + }
104 + }
105 +}
106 +
107 +export function popTransition(workInProgress: Fiber) {
108 + if (enableCache) {
109 + pop(resumedCache, workInProgress);
110 + }
111 +}
112 +
113 +export function getSuspendedCache(): SpawnedCachePool | null {
114 + if (!enableCache) {
115 + return null;
116 + }
117 + // This function is called when a Suspense boundary suspends. It returns the
118 + // cache that would have been used to render fresh data during this render,
119 + // if there was any, so that we can resume rendering with the same cache when
120 + // we receive more data.
121 + const cacheFromPool = peekCacheFromPool();
122 + if (cacheFromPool === null) {
123 + return null;
124 + }
125 +
126 + return {
127 + // We must also save the parent, so that when we resume we can detect
128 + // a refresh.
129 + parent: isPrimaryRenderer
130 + ? CacheContext._currentValue
131 + : CacheContext._currentValue2,
132 + pool: cacheFromPool,
133 + };
134 +}
135 +
136 +export function getOffscreenDeferredCache(): SpawnedCachePool | null {
137 + if (!enableCache) {
138 + return null;
139 + }
140 +
141 + const cacheFromPool = peekCacheFromPool();
142 + if (cacheFromPool === null) {
143 + return null;
144 + }
145 +
146 + return {
147 + // We must also store the parent, so that when we resume we can detect
148 + // a refresh.
149 + parent: isPrimaryRenderer
150 + ? CacheContext._currentValue
151 + : CacheContext._currentValue2,
152 + pool: cacheFromPool,
153 + };
154 +}
packages/react-reconciler/src/ReactFiberTransition.old.js new
+154
@@ -0,0 +1,154 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +import type {FiberRoot} from './ReactInternalTypes';
10 +import type {Lanes} from './ReactFiberLane.old';
11 +import type {StackCursor} from './ReactFiberStack.old';
12 +import type {Cache, SpawnedCachePool} from './ReactFiberCacheComponent.old';
13 +
14 +import {enableCache} from 'shared/ReactFeatureFlags';
15 +import {isPrimaryRenderer} from './ReactFiberHostConfig';
16 +import {createCursor, push, pop} from './ReactFiberStack.old';
17 +import {getWorkInProgressRoot} from './ReactFiberWorkLoop.old';
18 +import {
19 + createCache,
20 + retainCache,
21 + CacheContext,
22 +} from './ReactFiberCacheComponent.old';
23 +
24 +// When retrying a Suspense/Offscreen boundary, we restore the cache that was
25 +// used during the previous render by placing it here, on the stack.
26 +const resumedCache: StackCursor<Cache | null> = createCursor(null);
27 +
28 +function peekCacheFromPool(): Cache | null {
29 + if (!enableCache) {
30 + return (null: any);
31 + }
32 +
33 + // Check if the cache pool already has a cache we can use.
34 +
35 + // If we're rendering inside a Suspense boundary that is currently hidden,
36 + // we should use the same cache that we used during the previous render, if
37 + // one exists.
38 + const cacheResumedFromPreviousRender = resumedCache.current;
39 + if (cacheResumedFromPreviousRender !== null) {
40 + return cacheResumedFromPreviousRender;
41 + }
42 +
43 + // Otherwise, check the root's cache pool.
44 + const root = (getWorkInProgressRoot(): any);
45 + const cacheFromRootCachePool = root.pooledCache;
46 +
47 + return cacheFromRootCachePool;
48 +}
49 +
50 +export function requestCacheFromPool(renderLanes: Lanes): Cache {
51 + // Similar to previous function, except if there's not already a cache in the
52 + // pool, we allocate a new one.
53 + const cacheFromPool = peekCacheFromPool();
54 + if (cacheFromPool !== null) {
55 + return cacheFromPool;
56 + }
57 +
58 + // Create a fresh cache and add it to the root cache pool. A cache can have
59 + // multiple owners:
60 + // - A cache pool that lives on the FiberRoot. This is where all fresh caches
61 + // are originally created (TODO: except during refreshes, until we implement
62 + // this correctly). The root takes ownership immediately when the cache is
63 + // created. Conceptually, root.pooledCache is an Option<Arc<Cache>> (owned),
64 + // and the return value of this function is a &Arc<Cache> (borrowed).
65 + // - One of several fiber types: host root, cache boundary, suspense
66 + // component. These retain and release in the commit phase.
67 +
68 + const root = (getWorkInProgressRoot(): any);
69 + const freshCache = createCache();
70 + root.pooledCache = freshCache;
71 + retainCache(freshCache);
72 + if (freshCache !== null) {
73 + root.pooledCacheLanes |= renderLanes;
74 + }
75 + return freshCache;
76 +}
77 +
78 +export function pushRootTransition(root: FiberRoot) {
79 + if (enableCache) {
80 + return;
81 + }
82 + // Note: This function currently does nothing but I'll leave it here for
83 + // code organization purposes in case that changes.
84 +}
85 +
86 +export function popRootTransition(root: FiberRoot, renderLanes: Lanes) {
87 + if (enableCache) {
88 + return;
89 + }
90 + // Note: This function currently does nothing but I'll leave it here for
91 + // code organization purposes in case that changes.
92 +}
93 +
94 +export function pushTransition(
95 + offscreenWorkInProgress: Fiber,
96 + prevCachePool: SpawnedCachePool | null,
97 +): void {
98 + if (enableCache) {
99 + if (prevCachePool === null) {
100 + push(resumedCache, resumedCache.current, offscreenWorkInProgress);
101 + } else {
102 + push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
103 + }
104 + }
105 +}
106 +
107 +export function popTransition(workInProgress: Fiber) {
108 + if (enableCache) {
109 + pop(resumedCache, workInProgress);
110 + }
111 +}
112 +
113 +export function getSuspendedCache(): SpawnedCachePool | null {
114 + if (!enableCache) {
115 + return null;
116 + }
117 + // This function is called when a Suspense boundary suspends. It returns the
118 + // cache that would have been used to render fresh data during this render,
119 + // if there was any, so that we can resume rendering with the same cache when
120 + // we receive more data.
121 + const cacheFromPool = peekCacheFromPool();
122 + if (cacheFromPool === null) {
123 + return null;
124 + }
125 +
126 + return {
127 + // We must also save the parent, so that when we resume we can detect
128 + // a refresh.
129 + parent: isPrimaryRenderer
130 + ? CacheContext._currentValue
131 + : CacheContext._currentValue2,
132 + pool: cacheFromPool,
133 + };
134 +}
135 +
136 +export function getOffscreenDeferredCache(): SpawnedCachePool | null {
137 + if (!enableCache) {
138 + return null;
139 + }
140 +
141 + const cacheFromPool = peekCacheFromPool();
142 + if (cacheFromPool === null) {
143 + return null;
144 + }
145 +
146 + return {
147 + // We must also store the parent, so that when we resume we can detect
148 + // a refresh.
149 + parent: isPrimaryRenderer
150 + ? CacheContext._currentValue
151 + : CacheContext._currentValue2,
152 + pool: cacheFromPool,
153 + };
154 +}
packages/react-reconciler/src/ReactFiberTransitionPool.old.js new
+154
@@ -0,0 +1,154 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +import type {FiberRoot} from './ReactInternalTypes';
10 +import type {Lanes} from './ReactFiberLane.old';
11 +import type {StackCursor} from './ReactFiberStack.old';
12 +import type {Cache, SpawnedCachePool} from './ReactFiberCacheComponent.old';
13 +
14 +import {enableCache} from 'shared/ReactFeatureFlags';
15 +import {isPrimaryRenderer} from './ReactFiberHostConfig';
16 +import {createCursor, push, pop} from './ReactFiberStack.old';
17 +import {getWorkInProgressRoot} from './ReactFiberWorkLoop.old';
18 +import {
19 + createCache,
20 + retainCache,
21 + CacheContext,
22 +} from './ReactFiberCacheComponent.old';
23 +
24 +// When retrying a Suspense/Offscreen boundary, we restore the cache that was
25 +// used during the previous render by placing it here, on the stack.
26 +const resumedCache: StackCursor<Cache | null> = createCursor(null);
27 +
28 +function peekCacheFromPool(): Cache | null {
29 + if (!enableCache) {
30 + return (null: any);
31 + }
32 +
33 + // Check if the cache pool already has a cache we can use.
34 +
35 + // If we're rendering inside a Suspense boundary that is currently hidden,
36 + // we should use the same cache that we used during the previous render, if
37 + // one exists.
38 + const cacheResumedFromPreviousRender = resumedCache.current;
39 + if (cacheResumedFromPreviousRender !== null) {
40 + return cacheResumedFromPreviousRender;
41 + }
42 +
43 + // Otherwise, check the root's cache pool.
44 + const root = (getWorkInProgressRoot(): any);
45 + const cacheFromRootCachePool = root.pooledCache;
46 +
47 + return cacheFromRootCachePool;
48 +}
49 +
50 +export function requestCacheFromPool(renderLanes: Lanes): Cache {
51 + // Similar to previous function, except if there's not already a cache in the
52 + // pool, we allocate a new one.
53 + const cacheFromPool = peekCacheFromPool();
54 + if (cacheFromPool !== null) {
55 + return cacheFromPool;
56 + }
57 +
58 + // Create a fresh cache and add it to the root cache pool. A cache can have
59 + // multiple owners:
60 + // - A cache pool that lives on the FiberRoot. This is where all fresh caches
61 + // are originally created (TODO: except during refreshes, until we implement
62 + // this correctly). The root takes ownership immediately when the cache is
63 + // created. Conceptually, root.pooledCache is an Option<Arc<Cache>> (owned),
64 + // and the return value of this function is a &Arc<Cache> (borrowed).
65 + // - One of several fiber types: host root, cache boundary, suspense
66 + // component. These retain and release in the commit phase.
67 +
68 + const root = (getWorkInProgressRoot(): any);
69 + const freshCache = createCache();
70 + root.pooledCache = freshCache;
71 + retainCache(freshCache);
72 + if (freshCache !== null) {
73 + root.pooledCacheLanes |= renderLanes;
74 + }
75 + return freshCache;
76 +}
77 +
78 +export function pushRootTransitionPool(root: FiberRoot) {
79 + if (enableCache) {
80 + return;
81 + }
82 + // Note: This function currently does nothing but I'll leave it here for
83 + // code organization purposes in case that changes.
84 +}
85 +
86 +export function popRootTransitionPool(root: FiberRoot, renderLanes: Lanes) {
87 + if (enableCache) {
88 + return;
89 + }
90 + // Note: This function currently does nothing but I'll leave it here for
91 + // code organization purposes in case that changes.
92 +}
93 +
94 +export function pushTransitionPool(
95 + offscreenWorkInProgress: Fiber,
96 + prevCachePool: SpawnedCachePool | null,
97 +): void {
98 + if (enableCache) {
99 + if (prevCachePool === null) {
100 + push(resumedCache, resumedCache.current, offscreenWorkInProgress);
101 + } else {
102 + push(resumedCache, prevCachePool.pool, offscreenWorkInProgress);
103 + }
104 + }
105 +}
106 +
107 +export function popTransitionPool(workInProgress: Fiber) {
108 + if (enableCache) {
109 + pop(resumedCache, workInProgress);
110 + }
111 +}
112 +
113 +export function getSuspendedCachePool(): SpawnedCachePool | null {
114 + if (!enableCache) {
115 + return null;
116 + }
117 + // This function is called when a Suspense boundary suspends. It returns the
118 + // cache that would have been used to render fresh data during this render,
119 + // if there was any, so that we can resume rendering with the same cache when
120 + // we receive more data.
121 + const cacheFromPool = peekCacheFromPool();
122 + if (cacheFromPool === null) {
123 + return null;
124 + }
125 +
126 + return {
127 + // We must also save the parent, so that when we resume we can detect
128 + // a refresh.
129 + parent: isPrimaryRenderer
130 + ? CacheContext._currentValue
131 + : CacheContext._currentValue2,
132 + pool: cacheFromPool,
133 + };
134 +}
135 +
136 +export function getOffscreenDeferredCachePool(): SpawnedCachePool | null {
137 + if (!enableCache) {
138 + return null;
139 + }
140 +
141 + const cacheFromPool = peekCacheFromPool();
142 + if (cacheFromPool === null) {
143 + return null;
144 + }
145 +
146 + return {
147 + // We must also store the parent, so that when we resume we can detect
148 + // a refresh.
149 + parent: isPrimaryRenderer
150 + ? CacheContext._currentValue
151 + : CacheContext._currentValue2,
152 + pool: cacheFromPool,
153 + };
154 +}
packages/react-reconciler/src/ReactFiberUnwindWork.new.js
+6 -9
@@ -44,13 +44,10 @@ import {
44 } from './ReactFiberContext.new';
45 import {popProvider} from './ReactFiberNewContext.new';
46 import {popRenderLanes} from './ReactFiberWorkLoop.new';
47 -import {
48 - popCacheProvider,
49 - popRootCachePool,
50 - popCachePool,
51 -} from './ReactFiberCacheComponent.new';
47 +import {popCacheProvider} from './ReactFiberCacheComponent.new';
48 import {transferActualDuration} from './ReactProfilerTimer.new';
49 import {popTreeContext} from './ReactFiberTreeContext.new';
50 +import {popRootTransition, popTransition} from './ReactFiberTransition.new';
51
52 function unwindWork(
53 current: Fiber | null,
@@ -84,7 +81,7 @@ function unwindWork(
81 case HostRoot: {
82 if (enableCache) {
83 const root: FiberRoot = workInProgress.stateNode;
87 - popRootCachePool(root, renderLanes);
84 + popRootTransition(root, renderLanes);
85
86 const cache: Cache = workInProgress.memoizedState.cache;
87 popCacheProvider(workInProgress, cache);
@@ -158,7 +155,7 @@ function unwindWork(
155 popRenderLanes(workInProgress);
156 if (enableCache) {
157 if (current !== null) {
161 - popCachePool(workInProgress);
158 + popTransition(workInProgress);
159 }
160 }
161 return null;
@@ -194,7 +191,7 @@ function unwindInterruptedWork(
191 case HostRoot: {
192 if (enableCache) {
193 const root: FiberRoot = interruptedWork.stateNode;
197 - popRootCachePool(root, renderLanes);
194 + popRootTransition(root, renderLanes);
195
196 const cache: Cache = interruptedWork.memoizedState.cache;
197 popCacheProvider(interruptedWork, cache);
@@ -226,7 +223,7 @@ function unwindInterruptedWork(
223 popRenderLanes(interruptedWork);
224 if (enableCache) {
225 if (current !== null) {
229 - popCachePool(interruptedWork);
226 + popTransition(interruptedWork);
227 }
228 }
229
packages/react-reconciler/src/ReactFiberUnwindWork.old.js
+6 -9
@@ -44,13 +44,10 @@ import {
44 } from './ReactFiberContext.old';
45 import {popProvider} from './ReactFiberNewContext.old';
46 import {popRenderLanes} from './ReactFiberWorkLoop.old';
47 -import {
48 - popCacheProvider,
49 - popRootCachePool,
50 - popCachePool,
51 -} from './ReactFiberCacheComponent.old';
47 +import {popCacheProvider} from './ReactFiberCacheComponent.old';
48 import {transferActualDuration} from './ReactProfilerTimer.old';
49 import {popTreeContext} from './ReactFiberTreeContext.old';
50 +import {popRootTransition, popTransition} from './ReactFiberTransition.old';
51
52 function unwindWork(
53 current: Fiber | null,
@@ -84,7 +81,7 @@ function unwindWork(
81 case HostRoot: {
82 if (enableCache) {
83 const root: FiberRoot = workInProgress.stateNode;
87 - popRootCachePool(root, renderLanes);
84 + popRootTransition(root, renderLanes);
85
86 const cache: Cache = workInProgress.memoizedState.cache;
87 popCacheProvider(workInProgress, cache);
@@ -158,7 +155,7 @@ function unwindWork(
155 popRenderLanes(workInProgress);
156 if (enableCache) {
157 if (current !== null) {
161 - popCachePool(workInProgress);
158 + popTransition(workInProgress);
159 }
160 }
161 return null;
@@ -194,7 +191,7 @@ function unwindInterruptedWork(
191 case HostRoot: {
192 if (enableCache) {
193 const root: FiberRoot = interruptedWork.stateNode;
197 - popRootCachePool(root, renderLanes);
194 + popRootTransition(root, renderLanes);
195
196 const cache: Cache = interruptedWork.memoizedState.cache;
197 popCacheProvider(interruptedWork, cache);
@@ -226,7 +223,7 @@ function unwindInterruptedWork(
223 popRenderLanes(interruptedWork);
224 if (enableCache) {
225 if (current !== null) {
229 - popCachePool(interruptedWork);
226 + popTransition(interruptedWork);
227 }
228 }
229