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