text: /**
   * Copyright (c) Facebook, Inc. and its 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 './ReactFiber';
  import type {ExpirationTime} from './ReactFiberExpirationTime';
  import type {TimeoutHandle, NoTimeout} from './ReactFiberHostConfig';
  import type {Interaction} from 'scheduler/src/Tracing';
  
  import {noTimeout} from './ReactFiberHostConfig';
  import {createHostRootFiber} from './ReactFiber';
  import {NoWork} from './ReactFiberExpirationTime';
  import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
  import {unstable_getThreadID} from 'scheduler/tracing';
  
  // TODO: This should be lifted into the renderer.
  export type Batch = {
    _defer: boolean,
    _expirationTime: ExpirationTime,
    _onComplete: () => mixed,
    _next: Batch | null,
  };
  
  export type PendingInteractionMap = Map<ExpirationTime, Set<Interaction>>;
  
  type BaseFiberRootProperties = {|
    // Any additional information from the host associated with this root.
    containerInfo: any,
    // Used only by persistent updates.
    pendingChildren: any,
    // The currently active root fiber. This is the mutable root of the tree.
    current: Fiber,
  
    // The following priority levels are used to distinguish between 1)
    // uncommitted work, 2) uncommitted work that is suspended, and 3) uncommitted
    // work that may be unsuspended. We choose not to track each individual
    // pending level, trading granularity for performance.
    //
    // The earliest and latest priority levels that are suspended from committing.
    earliestSuspendedTime: ExpirationTime,
    latestSuspendedTime: ExpirationTime,
    // The earliest and latest priority levels that are not known to be suspended.
    earliestPendingTime: ExpirationTime,
    latestPendingTime: ExpirationTime,
    // The latest priority level that was pinged by a resolved promise and can
    // be retried.
    latestPingedTime: ExpirationTime,
  
    // If an error is thrown, and there are no more updates in the queue, we try
    // rendering from the root one more time, synchronously, before handling
    // the error.
    didError: boolean,
  
    pendingCommitExpirationTime: ExpirationTime,
    // 已经完成的任务的FiberRoot对象，如果你只有一个Root，那他永远只可能是这个Root对应的Fiber，或者是null
    // 在commit阶段只会处理这个值对应的任务
    finishedWork: Fiber | null,
    // 在任务被挂起的时候通过setTimeout设置的返回内容，
    // 用来下一次如果有新的任务挂起时清理还没触发的timeout
    timeoutHandle: TimeoutHandle | NoTimeout,
    // Top context object, used by renderSubtreeIntoContainer
    context: Object | null,
    pendingContext: Object | null,
    // Determines if we should attempt to hydrate on the initial mount
    +hydrate: boolean,
    // Remaining expiration time on this root.
    // TODO: Lift this into the renderer
    nextExpirationTimeToWorkOn: ExpirationTime,
    expirationTime: ExpirationTime,
    // List of top-level batches. This list indicates whether a commit should be
    // deferred. Also contains completion callbacks.
    // TODO: Lift this into the renderer
    firstBatch: Batch | null,
    // Linked-list of roots
    nextScheduledRoot: FiberRoot | null,
  |};
  
  // The following attributes are only used by interaction tracing builds.
  // They enable interactions to be associated with their async work,
  // And expose interaction metadata to the React DevTools Profiler plugin.
  // Note that these attributes are only defined when the enableSchedulerTracing flag is enabled.
  type ProfilingOnlyFiberRootProperties = {|
    interactionThreadID: number,
    memoizedInteractions: Set<Interaction>,
    pendingInteractionMap: PendingInteractionMap,
  |};
  
  // Exported FiberRoot type includes all properties,
  // To avoid requiring potentially error-prone :any casts throughout the project.
  // Profiling properties are only safe to access in profiling builds (when enableSchedulerTracing is true).
  // The types are defined separately within this file to ensure they stay in sync.
  // (We don't have to use an inline :any cast when enableSchedulerTracing is disabled.)
  export type FiberRoot = {
    ...BaseFiberRootProperties,
    ...ProfilingOnlyFiberRootProperties,
  };
  
  // 创建fiberRoot对象
  // 内部创建一个rootFiber对象
  // fiberRoot.current = rootFiber;
  // rootFiber.stateNode = filberRoot;
  export function createFiberRoot(
    containerInfo: any,
    isConcurrent: boolean,
    hydrate: boolean,
  ): FiberRoot {
    // 首先创建一个初始的rootFiber对象
    const uninitializedFiber = createHostRootFiber(isConcurrent);
  
    let root;
    // 创建fiberRoot对象
    if (enableSchedulerTracing) {
      root = ({
        current: uninitializedFiber,
        containerInfo: containerInfo,
        pendingChildren: null,
  
        earliestPendingTime: NoWork,
        latestPendingTime: NoWork,
        earliestSuspendedTime: NoWork,
        latestSuspendedTime: NoWork,
        latestPingedTime: NoWork,
  
        didError: false,
  
        pendingCommitExpirationTime: NoWork,
        finishedWork: null,
        timeoutHandle: noTimeout,
        context: null,
        pendingContext: null,
        hydrate,
        nextExpirationTimeToWorkOn: NoWork,
        expirationTime: NoWork,
        firstBatch: null,
        nextScheduledRoot: null,
  
        interactionThreadID: unstable_getThreadID(),
        memoizedInteractions: new Set(),
        pendingInteractionMap: new Map(),
      }: FiberRoot);
    } else {
      root = ({
        current: uninitializedFiber,  // rootFiber对象
        containerInfo: containerInfo, // react应用挂载的dom节点
        pendingChildren: null,
  
        earliestPendingTime: NoWork,
        latestPendingTime: NoWork,
        earliestSuspendedTime: NoWork,
        latestSuspendedTime: NoWork,
        latestPingedTime: NoWork,
  
        didError: false,
  
        pendingCommitExpirationTime: NoWork,
        finishedWork: null,
        timeoutHandle: noTimeout,
        context: null,
        pendingContext: null,
        hydrate,
        nextExpirationTimeToWorkOn: NoWork,
        expirationTime: NoWork,
        firstBatch: null,
        nextScheduledRoot: null,
      }: BaseFiberRootProperties);
    }
    // 为fiberRoot和rootFiber构建联系
    uninitializedFiber.stateNode = root;
    return ((root: any): FiberRoot);
  }
  