Skip to content

Commit

Permalink
Offscreen: Use JS stack to track hidden/unhidden subtree state
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Vaughn committed Apr 7, 2021
1 parent ee6a05c commit b939983
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 62 deletions.
86 changes: 55 additions & 31 deletions packages/react-reconciler/src/ReactFiberCommitWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,6 @@ if (__DEV__) {
didWarnAboutUndefinedSnapshotBeforeUpdate = new Set();
}

// Used during the commit phase to track the state of the Offscreen component stack.
// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor.
// Only used when enableSuspenseLayoutEffectSemantics is enabled.
let offscreenSubtreeIsHidden: boolean = false;
const offscreenSubtreeIsHiddenStack: Array<boolean> = [];
let offscreenSubtreeWasHidden: boolean = false;
const offscreenSubtreeWasHiddenStack: Array<boolean> = [];

const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;

let nextEffect: Fiber | null = null;
Expand Down Expand Up @@ -2283,13 +2275,38 @@ export function commitLayoutEffects(
committedLanes: Lanes,
): void {
nextEffect = finishedWork;
commitLayoutEffects_begin(finishedWork, root, committedLanes);
commitLayoutEffects_intermediate(
finishedWork,
root,
committedLanes,
false,
false,
);
}

export function commitLayoutEffects_intermediate(
finishedWork: Fiber,
root: FiberRoot,
committedLanes: Lanes,
offscreenSubtreeWasHidden: boolean,
offscreenSubtreeIsHidden: boolean,
): void {
nextEffect = finishedWork;
commitLayoutEffects_begin(
finishedWork,
root,
committedLanes,
offscreenSubtreeWasHidden,
offscreenSubtreeIsHidden,
);
}

function commitLayoutEffects_begin(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
offscreenSubtreeWasHidden: boolean,
offscreenSubtreeIsHidden: boolean,
) {
// Suspense layout effects semantics don't change for legacy roots.
const isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode;
Expand All @@ -2305,11 +2322,27 @@ function commitLayoutEffects_begin(
const wasHidden = current !== null && current.memoizedState !== null;
const isHidden = fiber.memoizedState !== null;

offscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
offscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
const newOffscreenSubtreeWasHidden =
wasHidden || offscreenSubtreeWasHidden;
const newOffscreenSubtreeIsHidden =
isHidden || offscreenSubtreeIsHidden;

offscreenSubtreeWasHiddenStack.push(wasHidden);
offscreenSubtreeIsHiddenStack.push(isHidden);
if (
newOffscreenSubtreeWasHidden !== offscreenSubtreeWasHidden ||
newOffscreenSubtreeIsHidden !== offscreenSubtreeIsHidden
) {
// Traverse the Offscreen subtree with the current Offscreen as the root.
nextEffect = fiber.child;
commitLayoutEffects_intermediate(
fiber, // New root; bubble back up to here and stop.
root,
committedLanes,
newOffscreenSubtreeWasHidden,
newOffscreenSubtreeIsHidden,
);
nextEffect = fiber.sibling;
continue;
}
}
}

Expand All @@ -2334,7 +2367,13 @@ function commitLayoutEffects_begin(
}
}

commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
commitLayoutMountEffects_complete(
subtreeRoot,
root,
committedLanes,
offscreenSubtreeWasHidden,
offscreenSubtreeIsHidden,
);
}
}
}
Expand All @@ -2343,30 +2382,15 @@ function commitLayoutMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
offscreenSubtreeWasHidden: boolean,
offscreenSubtreeIsHidden: boolean,
) {
// Suspense layout effects semantics don't change for legacy roots.
const isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode;

while (nextEffect !== null) {
const fiber = nextEffect;

if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
if (fiber.tag === OffscreenComponent) {
offscreenSubtreeWasHiddenStack.pop();
offscreenSubtreeIsHiddenStack.pop();
offscreenSubtreeWasHidden =
offscreenSubtreeWasHiddenStack.length > 0 &&
offscreenSubtreeWasHiddenStack[
offscreenSubtreeWasHiddenStack.length - 1
];
offscreenSubtreeIsHidden =
offscreenSubtreeIsHiddenStack.length > 0 &&
offscreenSubtreeIsHiddenStack[
offscreenSubtreeIsHiddenStack.length - 1
];
}
}

if (
enableSuspenseLayoutEffectSemantics &&
isModernRoot &&
Expand Down
86 changes: 55 additions & 31 deletions packages/react-reconciler/src/ReactFiberCommitWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,6 @@ if (__DEV__) {
didWarnAboutUndefinedSnapshotBeforeUpdate = new Set();
}

// Used during the commit phase to track the state of the Offscreen component stack.
// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor.
// Only used when enableSuspenseLayoutEffectSemantics is enabled.
let offscreenSubtreeIsHidden: boolean = false;
const offscreenSubtreeIsHiddenStack: Array<boolean> = [];
let offscreenSubtreeWasHidden: boolean = false;
const offscreenSubtreeWasHiddenStack: Array<boolean> = [];

const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;

let nextEffect: Fiber | null = null;
Expand Down Expand Up @@ -2283,13 +2275,38 @@ export function commitLayoutEffects(
committedLanes: Lanes,
): void {
nextEffect = finishedWork;
commitLayoutEffects_begin(finishedWork, root, committedLanes);
commitLayoutEffects_intermediate(
finishedWork,
root,
committedLanes,
false,
false,
);
}

export function commitLayoutEffects_intermediate(
finishedWork: Fiber,
root: FiberRoot,
committedLanes: Lanes,
offscreenSubtreeWasHidden: boolean,
offscreenSubtreeIsHidden: boolean,
): void {
nextEffect = finishedWork;
commitLayoutEffects_begin(
finishedWork,
root,
committedLanes,
offscreenSubtreeWasHidden,
offscreenSubtreeIsHidden,
);
}

function commitLayoutEffects_begin(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
offscreenSubtreeWasHidden: boolean,
offscreenSubtreeIsHidden: boolean,
) {
// Suspense layout effects semantics don't change for legacy roots.
const isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode;
Expand All @@ -2305,11 +2322,27 @@ function commitLayoutEffects_begin(
const wasHidden = current !== null && current.memoizedState !== null;
const isHidden = fiber.memoizedState !== null;

offscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
offscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
const newOffscreenSubtreeWasHidden =
wasHidden || offscreenSubtreeWasHidden;
const newOffscreenSubtreeIsHidden =
isHidden || offscreenSubtreeIsHidden;

offscreenSubtreeWasHiddenStack.push(wasHidden);
offscreenSubtreeIsHiddenStack.push(isHidden);
if (
newOffscreenSubtreeWasHidden !== offscreenSubtreeWasHidden ||
newOffscreenSubtreeIsHidden !== offscreenSubtreeIsHidden
) {
// Traverse the Offscreen subtree with the current Offscreen as the root.
nextEffect = fiber.child;
commitLayoutEffects_intermediate(
fiber, // New root; bubble back up to here and stop.
root,
committedLanes,
newOffscreenSubtreeWasHidden,
newOffscreenSubtreeIsHidden,
);
nextEffect = fiber.sibling;
continue;
}
}
}

Expand All @@ -2334,7 +2367,13 @@ function commitLayoutEffects_begin(
}
}

commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
commitLayoutMountEffects_complete(
subtreeRoot,
root,
committedLanes,
offscreenSubtreeWasHidden,
offscreenSubtreeIsHidden,
);
}
}
}
Expand All @@ -2343,30 +2382,15 @@ function commitLayoutMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
offscreenSubtreeWasHidden: boolean,
offscreenSubtreeIsHidden: boolean,
) {
// Suspense layout effects semantics don't change for legacy roots.
const isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode;

while (nextEffect !== null) {
const fiber = nextEffect;

if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
if (fiber.tag === OffscreenComponent) {
offscreenSubtreeWasHiddenStack.pop();
offscreenSubtreeIsHiddenStack.pop();
offscreenSubtreeWasHidden =
offscreenSubtreeWasHiddenStack.length > 0 &&
offscreenSubtreeWasHiddenStack[
offscreenSubtreeWasHiddenStack.length - 1
];
offscreenSubtreeIsHidden =
offscreenSubtreeIsHiddenStack.length > 0 &&
offscreenSubtreeIsHiddenStack[
offscreenSubtreeIsHiddenStack.length - 1
];
}
}

if (
enableSuspenseLayoutEffectSemantics &&
isModernRoot &&
Expand Down

0 comments on commit b939983

Please sign in to comment.