@samitouri / QOS-React-2 / commits / 1f8583de8c

Offscreen: Use JS stack to track hidden/unhidden subtree state (#21192)

Brian Vaughn committed Apr 7, 2021 at 17:45 UTC 1f8583de8c5e69f27a871a2069dcb5aecac02f40
2 files changed +56 -46
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+28 -23
@@ -156,9 +156,7 @@ if (__DEV__) {
156 // Allows us to avoid traversing the return path to find the nearest Offscreen ancestor.
157 // Only used when enableSuspenseLayoutEffectSemantics is enabled.
158 let offscreenSubtreeIsHidden: boolean = false;
159 -const offscreenSubtreeIsHiddenStack: Array<boolean> = [];
159 let offscreenSubtreeWasHidden: boolean = false;
161 -const offscreenSubtreeWasHiddenStack: Array<boolean> = [];
160
161 const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
162
@@ -2305,11 +2303,35 @@ function commitLayoutEffects_begin(
2303 const wasHidden = current !== null && current.memoizedState !== null;
2304 const isHidden = fiber.memoizedState !== null;
2305
2308 - offscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
2309 - offscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
2306 + const newOffscreenSubtreeIsHidden =
2307 + isHidden || offscreenSubtreeIsHidden;
2308 + const newOffscreenSubtreeWasHidden =
2309 + wasHidden || offscreenSubtreeWasHidden;
2310
2311 - offscreenSubtreeWasHiddenStack.push(wasHidden);
2312 - offscreenSubtreeIsHiddenStack.push(isHidden);
2311 + if (
2312 + newOffscreenSubtreeIsHidden !== offscreenSubtreeIsHidden ||
2313 + newOffscreenSubtreeWasHidden !== offscreenSubtreeWasHidden
2314 + ) {
2315 + const prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden;
2316 + const prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;
2317 +
2318 + nextEffect = fiber;
2319 + offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden;
2320 + offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden;
2321 +
2322 + // Traverse the Offscreen subtree with the current Offscreen as the root.
2323 + commitLayoutEffects_begin(
2324 + fiber, // New root; bubble back up to here and stop.
2325 + root,
2326 + committedLanes,
2327 + );
2328 +
2329 + nextEffect = fiber.sibling;
2330 + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;
2331 + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;
2332 +
2333 + continue;
2334 + }
2335 }
2336 }
2337
@@ -2350,23 +2372,6 @@ function commitLayoutMountEffects_complete(
2372 while (nextEffect !== null) {
2373 const fiber = nextEffect;
2374
2353 - if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
2354 - if (fiber.tag === OffscreenComponent) {
2355 - offscreenSubtreeWasHiddenStack.pop();
2356 - offscreenSubtreeIsHiddenStack.pop();
2357 - offscreenSubtreeWasHidden =
2358 - offscreenSubtreeWasHiddenStack.length > 0 &&
2359 - offscreenSubtreeWasHiddenStack[
2360 - offscreenSubtreeWasHiddenStack.length - 1
2361 - ];
2362 - offscreenSubtreeIsHidden =
2363 - offscreenSubtreeIsHiddenStack.length > 0 &&
2364 - offscreenSubtreeIsHiddenStack[
2365 - offscreenSubtreeIsHiddenStack.length - 1
2366 - ];
2367 - }
2368 - }
2369 -
2375 if (
2376 enableSuspenseLayoutEffectSemantics &&
2377 isModernRoot &&
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+28 -23
@@ -156,9 +156,7 @@ if (__DEV__) {
156 // Allows us to avoid traversing the return path to find the nearest Offscreen ancestor.
157 // Only used when enableSuspenseLayoutEffectSemantics is enabled.
158 let offscreenSubtreeIsHidden: boolean = false;
159 -const offscreenSubtreeIsHiddenStack: Array<boolean> = [];
159 let offscreenSubtreeWasHidden: boolean = false;
161 -const offscreenSubtreeWasHiddenStack: Array<boolean> = [];
160
161 const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
162
@@ -2305,11 +2303,35 @@ function commitLayoutEffects_begin(
2303 const wasHidden = current !== null && current.memoizedState !== null;
2304 const isHidden = fiber.memoizedState !== null;
2305
2308 - offscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
2309 - offscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
2306 + const newOffscreenSubtreeIsHidden =
2307 + isHidden || offscreenSubtreeIsHidden;
2308 + const newOffscreenSubtreeWasHidden =
2309 + wasHidden || offscreenSubtreeWasHidden;
2310
2311 - offscreenSubtreeWasHiddenStack.push(wasHidden);
2312 - offscreenSubtreeIsHiddenStack.push(isHidden);
2311 + if (
2312 + newOffscreenSubtreeIsHidden !== offscreenSubtreeIsHidden ||
2313 + newOffscreenSubtreeWasHidden !== offscreenSubtreeWasHidden
2314 + ) {
2315 + const prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden;
2316 + const prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;
2317 +
2318 + nextEffect = fiber;
2319 + offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden;
2320 + offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden;
2321 +
2322 + // Traverse the Offscreen subtree with the current Offscreen as the root.
2323 + commitLayoutEffects_begin(
2324 + fiber, // New root; bubble back up to here and stop.
2325 + root,
2326 + committedLanes,
2327 + );
2328 +
2329 + nextEffect = fiber.sibling;
2330 + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;
2331 + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;
2332 +
2333 + continue;
2334 + }
2335 }
2336 }
2337
@@ -2350,23 +2372,6 @@ function commitLayoutMountEffects_complete(
2372 while (nextEffect !== null) {
2373 const fiber = nextEffect;
2374
2353 - if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
2354 - if (fiber.tag === OffscreenComponent) {
2355 - offscreenSubtreeWasHiddenStack.pop();
2356 - offscreenSubtreeIsHiddenStack.pop();
2357 - offscreenSubtreeWasHidden =
2358 - offscreenSubtreeWasHiddenStack.length > 0 &&
2359 - offscreenSubtreeWasHiddenStack[
2360 - offscreenSubtreeWasHiddenStack.length - 1
2361 - ];
2362 - offscreenSubtreeIsHidden =
2363 - offscreenSubtreeIsHiddenStack.length > 0 &&
2364 - offscreenSubtreeIsHiddenStack[
2365 - offscreenSubtreeIsHiddenStack.length - 1
2366 - ];
2367 - }
2368 - }
2369 -
2375 if (
2376 enableSuspenseLayoutEffectSemantics &&
2377 isModernRoot &&