/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {Fiber} from './ReactInternalTypes';
import type {StackCursor} from './ReactFiberStack';
import type {Lanes} from './ReactFiberLane';
import {createCursor, push, pop} from './ReactFiberStack';
import {
getEntangledRenderLanes,
setEntangledRenderLanes,
} from './ReactFiberWorkLoop';
import {NoLanes, mergeLanes} from './ReactFiberLane';
// TODO: Remove `renderLanes` context in favor of hidden context
type HiddenContext = {
// Represents the lanes that must be included when processing updates in
// order to reveal the hidden content.
// TODO: Remove `subtreeLanes` context from work loop in favor of this one.
baseLanes: number,
...
};
// TODO: This isn't being used yet, but it's intended to replace the
// InvisibleParentContext that is currently managed by SuspenseContext.
export const currentTreeHiddenStackCursor: StackCursor<HiddenContext | null> =
createCursor(null);
export const prevEntangledRenderLanesCursor: StackCursor<Lanes> =
createCursor(NoLanes);
export function pushHiddenContext(fiber: Fiber, context: HiddenContext): void {
const prevEntangledRenderLanes = getEntangledRenderLanes();
push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber);
push(currentTreeHiddenStackCursor, context, fiber);
// When rendering a subtree that's currently hidden, we must include all
// lanes that would have rendered if the hidden subtree hadn't been deferred.
// That is, in order to reveal content from hidden -> visible, we must commit
// all the updates that we skipped when we originally hid the tree.
setEntangledRenderLanes(
mergeLanes(prevEntangledRenderLanes, context.baseLanes),
);
}
export function reuseHiddenContextOnStack(fiber: Fiber): void {
// This subtree is not currently hidden, so we don't need to add any lanes
// to the render lanes. But we still need to push something to avoid a
// context mismatch. Reuse the existing context on the stack.
push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber);
push(
currentTreeHiddenStackCursor,
currentTreeHiddenStackCursor.current,
fiber,
);
}
export function popHiddenContext(fiber: Fiber): void {
// Restore the previous render lanes from the stack
setEntangledRenderLanes(prevEntangledRenderLanesCursor.current);
pop(currentTreeHiddenStackCursor, fiber);
pop(prevEntangledRenderLanesCursor, fiber);
}
export function isCurrentTreeHidden(): boolean {
return currentTreeHiddenStackCursor.current !== null;
}