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 {ReactNodeList, ReactFormState} from 'shared/ReactTypes';
    
  11. import type {
    
  12.   FiberRoot,
    
  13.   SuspenseHydrationCallbacks,
    
  14.   TransitionTracingCallbacks,
    
  15. } from './ReactInternalTypes';
    
  16. import type {RootTag} from './ReactRootTags';
    
  17. import type {Cache} from './ReactFiberCacheComponent';
    
  18. import type {Container} from './ReactFiberConfig';
    
  19. 
    
  20. import {noTimeout} from './ReactFiberConfig';
    
  21. import {createHostRootFiber} from './ReactFiber';
    
  22. import {
    
  23.   NoLane,
    
  24.   NoLanes,
    
  25.   NoTimestamp,
    
  26.   TotalLanes,
    
  27.   createLaneMap,
    
  28. } from './ReactFiberLane';
    
  29. import {
    
  30.   enableSuspenseCallback,
    
  31.   enableCache,
    
  32.   enableProfilerCommitHooks,
    
  33.   enableProfilerTimer,
    
  34.   enableUpdaterTracking,
    
  35.   enableTransitionTracing,
    
  36. } from 'shared/ReactFeatureFlags';
    
  37. import {initializeUpdateQueue} from './ReactFiberClassUpdateQueue';
    
  38. import {LegacyRoot, ConcurrentRoot} from './ReactRootTags';
    
  39. import {createCache, retainCache} from './ReactFiberCacheComponent';
    
  40. 
    
  41. export type RootState = {
    
  42.   element: any,
    
  43.   isDehydrated: boolean,
    
  44.   cache: Cache,
    
  45. };
    
  46. 
    
  47. function FiberRootNode(
    
  48.   this: $FlowFixMe,
    
  49.   containerInfo: any,
    
  50.   // $FlowFixMe[missing-local-annot]
    
  51.   tag,
    
  52.   hydrate: any,
    
  53.   identifierPrefix: any,
    
  54.   onRecoverableError: any,
    
  55.   formState: ReactFormState<any, any> | null,
    
  56. ) {
    
  57.   this.tag = tag;
    
  58.   this.containerInfo = containerInfo;
    
  59.   this.pendingChildren = null;
    
  60.   this.current = null;
    
  61.   this.pingCache = null;
    
  62.   this.finishedWork = null;
    
  63.   this.timeoutHandle = noTimeout;
    
  64.   this.cancelPendingCommit = null;
    
  65.   this.context = null;
    
  66.   this.pendingContext = null;
    
  67.   this.next = null;
    
  68.   this.callbackNode = null;
    
  69.   this.callbackPriority = NoLane;
    
  70.   this.expirationTimes = createLaneMap(NoTimestamp);
    
  71. 
    
  72.   this.pendingLanes = NoLanes;
    
  73.   this.suspendedLanes = NoLanes;
    
  74.   this.pingedLanes = NoLanes;
    
  75.   this.expiredLanes = NoLanes;
    
  76.   this.finishedLanes = NoLanes;
    
  77.   this.errorRecoveryDisabledLanes = NoLanes;
    
  78.   this.shellSuspendCounter = 0;
    
  79. 
    
  80.   this.entangledLanes = NoLanes;
    
  81.   this.entanglements = createLaneMap(NoLanes);
    
  82. 
    
  83.   this.hiddenUpdates = createLaneMap(null);
    
  84. 
    
  85.   this.identifierPrefix = identifierPrefix;
    
  86.   this.onRecoverableError = onRecoverableError;
    
  87. 
    
  88.   if (enableCache) {
    
  89.     this.pooledCache = null;
    
  90.     this.pooledCacheLanes = NoLanes;
    
  91.   }
    
  92. 
    
  93.   if (enableSuspenseCallback) {
    
  94.     this.hydrationCallbacks = null;
    
  95.   }
    
  96. 
    
  97.   this.formState = formState;
    
  98. 
    
  99.   this.incompleteTransitions = new Map();
    
  100.   if (enableTransitionTracing) {
    
  101.     this.transitionCallbacks = null;
    
  102.     const transitionLanesMap = (this.transitionLanes = []);
    
  103.     for (let i = 0; i < TotalLanes; i++) {
    
  104.       transitionLanesMap.push(null);
    
  105.     }
    
  106.   }
    
  107. 
    
  108.   if (enableProfilerTimer && enableProfilerCommitHooks) {
    
  109.     this.effectDuration = 0;
    
  110.     this.passiveEffectDuration = 0;
    
  111.   }
    
  112. 
    
  113.   if (enableUpdaterTracking) {
    
  114.     this.memoizedUpdaters = new Set();
    
  115.     const pendingUpdatersLaneMap = (this.pendingUpdatersLaneMap = []);
    
  116.     for (let i = 0; i < TotalLanes; i++) {
    
  117.       pendingUpdatersLaneMap.push(new Set());
    
  118.     }
    
  119.   }
    
  120. 
    
  121.   if (__DEV__) {
    
  122.     switch (tag) {
    
  123.       case ConcurrentRoot:
    
  124.         this._debugRootType = hydrate ? 'hydrateRoot()' : 'createRoot()';
    
  125.         break;
    
  126.       case LegacyRoot:
    
  127.         this._debugRootType = hydrate ? 'hydrate()' : 'render()';
    
  128.         break;
    
  129.     }
    
  130.   }
    
  131. }
    
  132. 
    
  133. export function createFiberRoot(
    
  134.   containerInfo: Container,
    
  135.   tag: RootTag,
    
  136.   hydrate: boolean,
    
  137.   initialChildren: ReactNodeList,
    
  138.   hydrationCallbacks: null | SuspenseHydrationCallbacks,
    
  139.   isStrictMode: boolean,
    
  140.   concurrentUpdatesByDefaultOverride: null | boolean,
    
  141.   // TODO: We have several of these arguments that are conceptually part of the
    
  142.   // host config, but because they are passed in at runtime, we have to thread
    
  143.   // them through the root constructor. Perhaps we should put them all into a
    
  144.   // single type, like a DynamicHostConfig that is defined by the renderer.
    
  145.   identifierPrefix: string,
    
  146.   onRecoverableError: null | ((error: mixed) => void),
    
  147.   transitionCallbacks: null | TransitionTracingCallbacks,
    
  148.   formState: ReactFormState<any, any> | null,
    
  149. ): FiberRoot {
    
  150.   // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions
    
  151.   const root: FiberRoot = (new FiberRootNode(
    
  152.     containerInfo,
    
  153.     tag,
    
  154.     hydrate,
    
  155.     identifierPrefix,
    
  156.     onRecoverableError,
    
  157.     formState,
    
  158.   ): any);
    
  159.   if (enableSuspenseCallback) {
    
  160.     root.hydrationCallbacks = hydrationCallbacks;
    
  161.   }
    
  162. 
    
  163.   if (enableTransitionTracing) {
    
  164.     root.transitionCallbacks = transitionCallbacks;
    
  165.   }
    
  166. 
    
  167.   // Cyclic construction. This cheats the type system right now because
    
  168.   // stateNode is any.
    
  169.   const uninitializedFiber = createHostRootFiber(
    
  170.     tag,
    
  171.     isStrictMode,
    
  172.     concurrentUpdatesByDefaultOverride,
    
  173.   );
    
  174.   root.current = uninitializedFiber;
    
  175.   uninitializedFiber.stateNode = root;
    
  176. 
    
  177.   if (enableCache) {
    
  178.     const initialCache = createCache();
    
  179.     retainCache(initialCache);
    
  180. 
    
  181.     // The pooledCache is a fresh cache instance that is used temporarily
    
  182.     // for newly mounted boundaries during a render. In general, the
    
  183.     // pooledCache is always cleared from the root at the end of a render:
    
  184.     // it is either released when render commits, or moved to an Offscreen
    
  185.     // component if rendering suspends. Because the lifetime of the pooled
    
  186.     // cache is distinct from the main memoizedState.cache, it must be
    
  187.     // retained separately.
    
  188.     root.pooledCache = initialCache;
    
  189.     retainCache(initialCache);
    
  190.     const initialState: RootState = {
    
  191.       element: initialChildren,
    
  192.       isDehydrated: hydrate,
    
  193.       cache: initialCache,
    
  194.     };
    
  195.     uninitializedFiber.memoizedState = initialState;
    
  196.   } else {
    
  197.     const initialState: RootState = {
    
  198.       element: initialChildren,
    
  199.       isDehydrated: hydrate,
    
  200.       cache: (null: any), // not enabled yet
    
  201.     };
    
  202.     uninitializedFiber.memoizedState = initialState;
    
  203.   }
    
  204. 
    
  205.   initializeUpdateQueue(uninitializedFiber);
    
  206. 
    
  207.   return root;
    
  208. }