1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and 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. 
    
  10. import type {Fiber} from './ReactInternalTypes';
    
  11. import type {StackCursor} from './ReactFiberStack';
    
  12. import type {Lanes} from './ReactFiberLane';
    
  13. 
    
  14. import {createCursor, push, pop} from './ReactFiberStack';
    
  15. 
    
  16. import {
    
  17.   getEntangledRenderLanes,
    
  18.   setEntangledRenderLanes,
    
  19. } from './ReactFiberWorkLoop';
    
  20. import {NoLanes, mergeLanes} from './ReactFiberLane';
    
  21. 
    
  22. // TODO: Remove `renderLanes` context in favor of hidden context
    
  23. type HiddenContext = {
    
  24.   // Represents the lanes that must be included when processing updates in
    
  25.   // order to reveal the hidden content.
    
  26.   // TODO: Remove `subtreeLanes` context from work loop in favor of this one.
    
  27.   baseLanes: number,
    
  28.   ...
    
  29. };
    
  30. 
    
  31. // TODO: This isn't being used yet, but it's intended to replace the
    
  32. // InvisibleParentContext that is currently managed by SuspenseContext.
    
  33. export const currentTreeHiddenStackCursor: StackCursor<HiddenContext | null> =
    
  34.   createCursor(null);
    
  35. export const prevEntangledRenderLanesCursor: StackCursor<Lanes> =
    
  36.   createCursor(NoLanes);
    
  37. 
    
  38. export function pushHiddenContext(fiber: Fiber, context: HiddenContext): void {
    
  39.   const prevEntangledRenderLanes = getEntangledRenderLanes();
    
  40.   push(prevEntangledRenderLanesCursor, prevEntangledRenderLanes, fiber);
    
  41.   push(currentTreeHiddenStackCursor, context, fiber);
    
  42. 
    
  43.   // When rendering a subtree that's currently hidden, we must include all
    
  44.   // lanes that would have rendered if the hidden subtree hadn't been deferred.
    
  45.   // That is, in order to reveal content from hidden -> visible, we must commit
    
  46.   // all the updates that we skipped when we originally hid the tree.
    
  47.   setEntangledRenderLanes(
    
  48.     mergeLanes(prevEntangledRenderLanes, context.baseLanes),
    
  49.   );
    
  50. }
    
  51. 
    
  52. export function reuseHiddenContextOnStack(fiber: Fiber): void {
    
  53.   // This subtree is not currently hidden, so we don't need to add any lanes
    
  54.   // to the render lanes. But we still need to push something to avoid a
    
  55.   // context mismatch. Reuse the existing context on the stack.
    
  56.   push(prevEntangledRenderLanesCursor, getEntangledRenderLanes(), fiber);
    
  57.   push(
    
  58.     currentTreeHiddenStackCursor,
    
  59.     currentTreeHiddenStackCursor.current,
    
  60.     fiber,
    
  61.   );
    
  62. }
    
  63. 
    
  64. export function popHiddenContext(fiber: Fiber): void {
    
  65.   // Restore the previous render lanes from the stack
    
  66.   setEntangledRenderLanes(prevEntangledRenderLanesCursor.current);
    
  67. 
    
  68.   pop(currentTreeHiddenStackCursor, fiber);
    
  69.   pop(prevEntangledRenderLanesCursor, fiber);
    
  70. }
    
  71. 
    
  72. export function isCurrentTreeHidden(): boolean {
    
  73.   return currentTreeHiddenStackCursor.current !== null;
    
  74. }