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 {Source} from 'shared/ReactElementType';
    
  11. import type {
    
  12.   RefObject,
    
  13.   ReactContext,
    
  14.   StartTransitionOptions,
    
  15.   Wakeable,
    
  16.   Usable,
    
  17.   ReactFormState,
    
  18.   Awaited,
    
  19. } from 'shared/ReactTypes';
    
  20. import type {WorkTag} from './ReactWorkTags';
    
  21. import type {TypeOfMode} from './ReactTypeOfMode';
    
  22. import type {Flags} from './ReactFiberFlags';
    
  23. import type {Lane, Lanes, LaneMap} from './ReactFiberLane';
    
  24. import type {RootTag} from './ReactRootTags';
    
  25. import type {
    
  26.   Container,
    
  27.   TimeoutHandle,
    
  28.   NoTimeout,
    
  29.   SuspenseInstance,
    
  30.   TransitionStatus,
    
  31. } from './ReactFiberConfig';
    
  32. import type {Cache} from './ReactFiberCacheComponent';
    
  33. import type {
    
  34.   TracingMarkerInstance,
    
  35.   Transition,
    
  36. } from './ReactFiberTracingMarkerComponent';
    
  37. import type {ConcurrentUpdate} from './ReactFiberConcurrentUpdates';
    
  38. 
    
  39. // Unwind Circular: moved from ReactFiberHooks.old
    
  40. export type HookType =
    
  41.   | 'useState'
    
  42.   | 'useReducer'
    
  43.   | 'useContext'
    
  44.   | 'useRef'
    
  45.   | 'useEffect'
    
  46.   | 'useEffectEvent'
    
  47.   | 'useInsertionEffect'
    
  48.   | 'useLayoutEffect'
    
  49.   | 'useCallback'
    
  50.   | 'useMemo'
    
  51.   | 'useImperativeHandle'
    
  52.   | 'useDebugValue'
    
  53.   | 'useDeferredValue'
    
  54.   | 'useTransition'
    
  55.   | 'useSyncExternalStore'
    
  56.   | 'useId'
    
  57.   | 'useCacheRefresh'
    
  58.   | 'useOptimistic'
    
  59.   | 'useFormState';
    
  60. 
    
  61. export type ContextDependency<T> = {
    
  62.   context: ReactContext<T>,
    
  63.   next: ContextDependency<mixed> | null,
    
  64.   memoizedValue: T,
    
  65.   ...
    
  66. };
    
  67. 
    
  68. export type Dependencies = {
    
  69.   lanes: Lanes,
    
  70.   firstContext: ContextDependency<mixed> | null,
    
  71.   ...
    
  72. };
    
  73. 
    
  74. export type MemoCache = {
    
  75.   data: Array<Array<any>>,
    
  76.   index: number,
    
  77. };
    
  78. 
    
  79. // A Fiber is work on a Component that needs to be done or was done. There can
    
  80. // be more than one per component.
    
  81. export type Fiber = {
    
  82.   // These first fields are conceptually members of an Instance. This used to
    
  83.   // be split into a separate type and intersected with the other Fiber fields,
    
  84.   // but until Flow fixes its intersection bugs, we've merged them into a
    
  85.   // single type.
    
  86. 
    
  87.   // An Instance is shared between all versions of a component. We can easily
    
  88.   // break this out into a separate object to avoid copying so much to the
    
  89.   // alternate versions of the tree. We put this on a single object for now to
    
  90.   // minimize the number of objects created during the initial render.
    
  91. 
    
  92.   // Tag identifying the type of fiber.
    
  93.   tag: WorkTag,
    
  94. 
    
  95.   // Unique identifier of this child.
    
  96.   key: null | string,
    
  97. 
    
  98.   // The value of element.type which is used to preserve the identity during
    
  99.   // reconciliation of this child.
    
  100.   elementType: any,
    
  101. 
    
  102.   // The resolved function/class/ associated with this fiber.
    
  103.   type: any,
    
  104. 
    
  105.   // The local state associated with this fiber.
    
  106.   stateNode: any,
    
  107. 
    
  108.   // Conceptual aliases
    
  109.   // parent : Instance -> return The parent happens to be the same as the
    
  110.   // return fiber since we've merged the fiber and instance.
    
  111. 
    
  112.   // Remaining fields belong to Fiber
    
  113. 
    
  114.   // The Fiber to return to after finishing processing this one.
    
  115.   // This is effectively the parent, but there can be multiple parents (two)
    
  116.   // so this is only the parent of the thing we're currently processing.
    
  117.   // It is conceptually the same as the return address of a stack frame.
    
  118.   return: Fiber | null,
    
  119. 
    
  120.   // Singly Linked List Tree Structure.
    
  121.   child: Fiber | null,
    
  122.   sibling: Fiber | null,
    
  123.   index: number,
    
  124. 
    
  125.   // The ref last used to attach this node.
    
  126.   // I'll avoid adding an owner field for prod and model that as functions.
    
  127.   ref:
    
  128.     | null
    
  129.     | (((handle: mixed) => void) & {_stringRef: ?string, ...})
    
  130.     | RefObject,
    
  131. 
    
  132.   refCleanup: null | (() => void),
    
  133. 
    
  134.   // Input is the data coming into process this fiber. Arguments. Props.
    
  135.   pendingProps: any, // This type will be more specific once we overload the tag.
    
  136.   memoizedProps: any, // The props used to create the output.
    
  137. 
    
  138.   // A queue of state updates and callbacks.
    
  139.   updateQueue: mixed,
    
  140. 
    
  141.   // The state used to create the output
    
  142.   memoizedState: any,
    
  143. 
    
  144.   // Dependencies (contexts, events) for this fiber, if it has any
    
  145.   dependencies: Dependencies | null,
    
  146. 
    
  147.   // Bitfield that describes properties about the fiber and its subtree. E.g.
    
  148.   // the ConcurrentMode flag indicates whether the subtree should be async-by-
    
  149.   // default. When a fiber is created, it inherits the mode of its
    
  150.   // parent. Additional flags can be set at creation time, but after that the
    
  151.   // value should remain unchanged throughout the fiber's lifetime, particularly
    
  152.   // before its child fibers are created.
    
  153.   mode: TypeOfMode,
    
  154. 
    
  155.   // Effect
    
  156.   flags: Flags,
    
  157.   subtreeFlags: Flags,
    
  158.   deletions: Array<Fiber> | null,
    
  159. 
    
  160.   // Singly linked list fast path to the next fiber with side-effects.
    
  161.   nextEffect: Fiber | null,
    
  162. 
    
  163.   // The first and last fiber with side-effect within this subtree. This allows
    
  164.   // us to reuse a slice of the linked list when we reuse the work done within
    
  165.   // this fiber.
    
  166.   firstEffect: Fiber | null,
    
  167.   lastEffect: Fiber | null,
    
  168. 
    
  169.   lanes: Lanes,
    
  170.   childLanes: Lanes,
    
  171. 
    
  172.   // This is a pooled version of a Fiber. Every fiber that gets updated will
    
  173.   // eventually have a pair. There are cases when we can clean up pairs to save
    
  174.   // memory if we need to.
    
  175.   alternate: Fiber | null,
    
  176. 
    
  177.   // Time spent rendering this Fiber and its descendants for the current update.
    
  178.   // This tells us how well the tree makes use of sCU for memoization.
    
  179.   // It is reset to 0 each time we render and only updated when we don't bailout.
    
  180.   // This field is only set when the enableProfilerTimer flag is enabled.
    
  181.   actualDuration?: number,
    
  182. 
    
  183.   // If the Fiber is currently active in the "render" phase,
    
  184.   // This marks the time at which the work began.
    
  185.   // This field is only set when the enableProfilerTimer flag is enabled.
    
  186.   actualStartTime?: number,
    
  187. 
    
  188.   // Duration of the most recent render time for this Fiber.
    
  189.   // This value is not updated when we bailout for memoization purposes.
    
  190.   // This field is only set when the enableProfilerTimer flag is enabled.
    
  191.   selfBaseDuration?: number,
    
  192. 
    
  193.   // Sum of base times for all descendants of this Fiber.
    
  194.   // This value bubbles up during the "complete" phase.
    
  195.   // This field is only set when the enableProfilerTimer flag is enabled.
    
  196.   treeBaseDuration?: number,
    
  197. 
    
  198.   // Conceptual aliases
    
  199.   // workInProgress : Fiber ->  alternate The alternate used for reuse happens
    
  200.   // to be the same as work in progress.
    
  201.   // __DEV__ only
    
  202. 
    
  203.   _debugSource?: Source | null,
    
  204.   _debugOwner?: Fiber | null,
    
  205.   _debugIsCurrentlyTiming?: boolean,
    
  206.   _debugNeedsRemount?: boolean,
    
  207. 
    
  208.   // Used to verify that the order of hooks does not change between renders.
    
  209.   _debugHookTypes?: Array<HookType> | null,
    
  210. };
    
  211. 
    
  212. type BaseFiberRootProperties = {
    
  213.   // The type of root (legacy, batched, concurrent, etc.)
    
  214.   tag: RootTag,
    
  215. 
    
  216.   // Any additional information from the host associated with this root.
    
  217.   containerInfo: Container,
    
  218.   // Used only by persistent updates.
    
  219.   pendingChildren: any,
    
  220.   // The currently active root fiber. This is the mutable root of the tree.
    
  221.   current: Fiber,
    
  222. 
    
  223.   pingCache: WeakMap<Wakeable, Set<mixed>> | Map<Wakeable, Set<mixed>> | null,
    
  224. 
    
  225.   // A finished work-in-progress HostRoot that's ready to be committed.
    
  226.   finishedWork: Fiber | null,
    
  227.   // Timeout handle returned by setTimeout. Used to cancel a pending timeout, if
    
  228.   // it's superseded by a new one.
    
  229.   timeoutHandle: TimeoutHandle | NoTimeout,
    
  230.   // When a root has a pending commit scheduled, calling this function will
    
  231.   // cancel it.
    
  232.   // TODO: Can this be consolidated with timeoutHandle?
    
  233.   cancelPendingCommit: null | (() => void),
    
  234.   // Top context object, used by renderSubtreeIntoContainer
    
  235.   context: Object | null,
    
  236.   pendingContext: Object | null,
    
  237. 
    
  238.   // Used to create a linked list that represent all the roots that have
    
  239.   // pending work scheduled on them.
    
  240.   next: FiberRoot | null,
    
  241. 
    
  242.   // Node returned by Scheduler.scheduleCallback. Represents the next rendering
    
  243.   // task that the root will work on.
    
  244.   callbackNode: any,
    
  245.   callbackPriority: Lane,
    
  246.   expirationTimes: LaneMap<number>,
    
  247.   hiddenUpdates: LaneMap<Array<ConcurrentUpdate> | null>,
    
  248. 
    
  249.   pendingLanes: Lanes,
    
  250.   suspendedLanes: Lanes,
    
  251.   pingedLanes: Lanes,
    
  252.   expiredLanes: Lanes,
    
  253.   errorRecoveryDisabledLanes: Lanes,
    
  254.   shellSuspendCounter: number,
    
  255. 
    
  256.   finishedLanes: Lanes,
    
  257. 
    
  258.   entangledLanes: Lanes,
    
  259.   entanglements: LaneMap<Lanes>,
    
  260. 
    
  261.   pooledCache: Cache | null,
    
  262.   pooledCacheLanes: Lanes,
    
  263. 
    
  264.   // TODO: In Fizz, id generation is specific to each server config. Maybe we
    
  265.   // should do this in Fiber, too? Deferring this decision for now because
    
  266.   // there's no other place to store the prefix except for an internal field on
    
  267.   // the public createRoot object, which the fiber tree does not currently have
    
  268.   // a reference to.
    
  269.   identifierPrefix: string,
    
  270. 
    
  271.   onRecoverableError: (
    
  272.     error: mixed,
    
  273.     errorInfo: {digest?: ?string, componentStack?: ?string},
    
  274.   ) => void,
    
  275. 
    
  276.   formState: ReactFormState<any, any> | null,
    
  277. };
    
  278. 
    
  279. // The following attributes are only used by DevTools and are only present in DEV builds.
    
  280. // They enable DevTools Profiler UI to show which Fiber(s) scheduled a given commit.
    
  281. type UpdaterTrackingOnlyFiberRootProperties = {
    
  282.   memoizedUpdaters: Set<Fiber>,
    
  283.   pendingUpdatersLaneMap: LaneMap<Set<Fiber>>,
    
  284. };
    
  285. 
    
  286. export type SuspenseHydrationCallbacks = {
    
  287.   onHydrated?: (suspenseInstance: SuspenseInstance) => void,
    
  288.   onDeleted?: (suspenseInstance: SuspenseInstance) => void,
    
  289.   ...
    
  290. };
    
  291. 
    
  292. // The follow fields are only used by enableSuspenseCallback for hydration.
    
  293. type SuspenseCallbackOnlyFiberRootProperties = {
    
  294.   hydrationCallbacks: null | SuspenseHydrationCallbacks,
    
  295. };
    
  296. 
    
  297. export type TransitionTracingCallbacks = {
    
  298.   onTransitionStart?: (transitionName: string, startTime: number) => void,
    
  299.   onTransitionProgress?: (
    
  300.     transitionName: string,
    
  301.     startTime: number,
    
  302.     currentTime: number,
    
  303.     pending: Array<{name: null | string}>,
    
  304.   ) => void,
    
  305.   onTransitionIncomplete?: (
    
  306.     transitionName: string,
    
  307.     startTime: number,
    
  308.     deletions: Array<{
    
  309.       type: string,
    
  310.       name?: string | null,
    
  311.       endTime: number,
    
  312.     }>,
    
  313.   ) => void,
    
  314.   onTransitionComplete?: (
    
  315.     transitionName: string,
    
  316.     startTime: number,
    
  317.     endTime: number,
    
  318.   ) => void,
    
  319.   onMarkerProgress?: (
    
  320.     transitionName: string,
    
  321.     marker: string,
    
  322.     startTime: number,
    
  323.     currentTime: number,
    
  324.     pending: Array<{name: null | string}>,
    
  325.   ) => void,
    
  326.   onMarkerIncomplete?: (
    
  327.     transitionName: string,
    
  328.     marker: string,
    
  329.     startTime: number,
    
  330.     deletions: Array<{
    
  331.       type: string,
    
  332.       name?: string | null,
    
  333.       endTime: number,
    
  334.     }>,
    
  335.   ) => void,
    
  336.   onMarkerComplete?: (
    
  337.     transitionName: string,
    
  338.     marker: string,
    
  339.     startTime: number,
    
  340.     endTime: number,
    
  341.   ) => void,
    
  342. };
    
  343. 
    
  344. // The following fields are only used in transition tracing in Profile builds
    
  345. type TransitionTracingOnlyFiberRootProperties = {
    
  346.   transitionCallbacks: null | TransitionTracingCallbacks,
    
  347.   transitionLanes: Array<Set<Transition> | null>,
    
  348.   // Transitions on the root can be represented as a bunch of tracing markers.
    
  349.   // Each entangled group of transitions can be treated as a tracing marker.
    
  350.   // It will have a set of pending suspense boundaries. These transitions
    
  351.   // are considered complete when the pending suspense boundaries set is
    
  352.   // empty. We can represent this as a Map of transitions to suspense
    
  353.   // boundary sets
    
  354.   incompleteTransitions: Map<Transition, TracingMarkerInstance>,
    
  355. };
    
  356. 
    
  357. // Exported FiberRoot type includes all properties,
    
  358. // To avoid requiring potentially error-prone :any casts throughout the project.
    
  359. // The types are defined separately within this file to ensure they stay in sync.
    
  360. export type FiberRoot = {
    
  361.   ...BaseFiberRootProperties,
    
  362.   ...SuspenseCallbackOnlyFiberRootProperties,
    
  363.   ...UpdaterTrackingOnlyFiberRootProperties,
    
  364.   ...TransitionTracingOnlyFiberRootProperties,
    
  365.   ...
    
  366. };
    
  367. 
    
  368. type BasicStateAction<S> = (S => S) | S;
    
  369. type Dispatch<A> = A => void;
    
  370. 
    
  371. export type Dispatcher = {
    
  372.   use: <T>(Usable<T>) => T,
    
  373.   readContext<T>(context: ReactContext<T>): T,
    
  374.   useState<S>(initialState: (() => S) | S): [S, Dispatch<BasicStateAction<S>>],
    
  375.   useReducer<S, I, A>(
    
  376.     reducer: (S, A) => S,
    
  377.     initialArg: I,
    
  378.     init?: (I) => S,
    
  379.   ): [S, Dispatch<A>],
    
  380.   useContext<T>(context: ReactContext<T>): T,
    
  381.   useRef<T>(initialValue: T): {current: T},
    
  382.   useEffect(
    
  383.     create: () => (() => void) | void,
    
  384.     deps: Array<mixed> | void | null,
    
  385.   ): void,
    
  386.   useEffectEvent?: <Args, F: (...Array<Args>) => mixed>(callback: F) => F,
    
  387.   useInsertionEffect(
    
  388.     create: () => (() => void) | void,
    
  389.     deps: Array<mixed> | void | null,
    
  390.   ): void,
    
  391.   useLayoutEffect(
    
  392.     create: () => (() => void) | void,
    
  393.     deps: Array<mixed> | void | null,
    
  394.   ): void,
    
  395.   useCallback<T>(callback: T, deps: Array<mixed> | void | null): T,
    
  396.   useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T,
    
  397.   useImperativeHandle<T>(
    
  398.     ref: {current: T | null} | ((inst: T | null) => mixed) | null | void,
    
  399.     create: () => T,
    
  400.     deps: Array<mixed> | void | null,
    
  401.   ): void,
    
  402.   useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void,
    
  403.   useDeferredValue<T>(value: T, initialValue?: T): T,
    
  404.   useTransition(): [
    
  405.     boolean,
    
  406.     (callback: () => void, options?: StartTransitionOptions) => void,
    
  407.   ],
    
  408.   useSyncExternalStore<T>(
    
  409.     subscribe: (() => void) => () => void,
    
  410.     getSnapshot: () => T,
    
  411.     getServerSnapshot?: () => T,
    
  412.   ): T,
    
  413.   useId(): string,
    
  414.   useCacheRefresh?: () => <T>(?() => T, ?T) => void,
    
  415.   useMemoCache?: (size: number) => Array<any>,
    
  416.   useHostTransitionStatus?: () => TransitionStatus,
    
  417.   useOptimistic?: <S, A>(
    
  418.     passthrough: S,
    
  419.     reducer: ?(S, A) => S,
    
  420.   ) => [S, (A) => void],
    
  421.   useFormState?: <S, P>(
    
  422.     action: (Awaited<S>, P) => S,
    
  423.     initialState: Awaited<S>,
    
  424.     permalink?: string,
    
  425.   ) => [Awaited<S>, (P) => void],
    
  426. };
    
  427. 
    
  428. export type CacheDispatcher = {
    
  429.   getCacheSignal: () => AbortSignal,
    
  430.   getCacheForType: <T>(resourceType: () => T) => T,
    
  431. };