React19源码系列之渲染阶段performUnitOfWork

news2025/5/26 1:40:36

在 React 内部实现中,将 render 函数分为两个阶段:

  1. 渲染阶段
  2. 提交阶段

其中渲染阶段可以分为 beginWork 和 completeWork 两个阶段,而提交阶段对应着 commitWork。

在之前的root.render过程中,渲染过程无论是并发模式执行还是同步模式执行,都是执行到函数performUnitOfWork,所以,这次,具体看看performUnitOfWork函数的执行过程。

workLoopSync

performUnitOfWork

performUnitOfWork 函数的主要作用是执行单个 Fiber 节点的工作单元。该函数会根据当前 Fiber 节点的状态,调用 beginWork 函数开始处理这个 Fiber 节点,并根据处理结果决定是继续处理下一个 Fiber 节点,还是完成当前 Fiber 节点的工作。

函数参数含义

  • unitOfWork:类型为 Fiber,表示当前要处理的 Fiber 节点,也就是当前的工作单元。

function performUnitOfWork(unitOfWork: Fiber): void {
  // unitOfWork.alternate 指向当前 Fiber 节点的替代节点。在 React 的协调过程中,每个 Fiber 节点都有一个对应的替代节点,用于在双缓冲机制中存储旧的状态。这里将其赋值给 current。
  const current = unitOfWork.alternate;

  // next:用于存储 beginWork 函数返回的下一个要处理的 Fiber 节点。
  let next;


// 调用 beginWork 函数开始处理当前 Fiber 节点,传入当前 Fiber 节点的替代节点 current、当前 Fiber 节点 unitOfWork 以及相关的渲染车道 entangledRenderLanes。beginWork 函数会根据 Fiber 节点的类型和状态,执行相应的工作,如创建新的 Fiber 节点、更新已有 Fiber 节点等,并返回下一个要处理的 Fiber 节点。
  next = beginWork(current, unitOfWork, entangledRenderLanes);
  

  // 将 unitOfWork 的 pendingProps(待处理的属性)赋值给 memoizedProps(记忆化的属性)。这意味着当前 Fiber 节点的属性已经被处理并确定下来。
  unitOfWork.memoizedProps = unitOfWork.pendingProps;

  // 如果 next 为 null,说明 beginWork 函数没有返回下一个要处理的 Fiber 节点,即当前 Fiber 节点的工作没有产生新的工作。
  if (next === null) {
    // If this doesn't spawn new work, complete the current work.
    // 调用 completeUnitOfWork 函数完成当前 Fiber 节点的工作,可能会进行一些清理和提交操作。
    completeUnitOfWork(unitOfWork);
  } else {
    // 如果 next 不为 null,将 next 赋值给 workInProgress,表示下一个要处理的 Fiber 节点成为当前的工作进行中的节点,后续将继续处理这个节点。
    workInProgress = next;
  }
}

渲染阶段一beginWork

beginWork 函数的主要任务是根据不同的 Fiber 节点类型和更新情况,对当前 Fiber 节点进行处理,决定是复用旧的 Fiber 节点,还是创建新的子 Fiber 节点。该函数会根据 Fiber 节点的 tag 属性(表示节点类型),调用不同的处理函数来更新或挂载节点。

beginWork 函数接收三个参数:

  • current:旧的 Fiber 节点,若为 null 则表示没有旧节点。
  • workInProgress:新的 Fiber 节点,也就是要进行处理的节点。
  • renderLanes:渲染优先级车道,用于标识当前渲染任务的优先级。
    function beginWork(
      current: Fiber | null,
      workInProgress: Fiber,
      renderLanes: Lanes,
    ): Fiber | null {
    
      // 有旧节点,非首次渲染
      if (current !== null) {
        // current.memoizedProps 存储了旧 Fiber 节点上一次渲染时使用的属性。
        const oldProps = current.memoizedProps;
    
        // workInProgress.pendingProps 存储了新 Fiber 节点即将使用的属性。
        const newProps = workInProgress.pendingProps;
    
        if (
          oldProps !== newProps ||
          hasLegacyContextChanged() )
        ) {
    
          didReceiveUpdate = true;
          
        } else {
          
          const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(
            current,
            renderLanes,
          );
    
          // 尝试提前退出渲染流程
          if (
            !hasScheduledUpdateOrContext &&
            (workInProgress.flags & DidCapture) === NoFlags
          ) {
            // No pending updates or context. Bail out now.
            didReceiveUpdate = false;
            return attemptEarlyBailoutIfNoScheduledUpdate(
              current,
              workInProgress,
              renderLanes,
            );
          }
    
          if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) {
            didReceiveUpdate = true;
          } else {
            didReceiveUpdate = false;
          }
        }
        
      } else {
        
        // 首次渲染时,将 didReceiveUpdate 标记为 false。
        didReceiveUpdate = false;
      }
      
      // 将 workInProgress.lanes 设置为 NoLanes 时,意味着当前 Fiber 节点没有需要处理的更新任务,或者更新任务已经处理完毕。
      // 会清除当前 workInProgress Fiber 节点上的所有更新标记。
      workInProgress.lanes = NoLanes;
    
      switch (workInProgress.tag) {
          // 省略代码。。。
    
        case Throw: {
          // This represents a Component that threw in the reconciliation phase.
          // So we'll rethrow here. This might be a Thenable.
          throw workInProgress.pendingProps;
        }
      }
    
    
    }

     <Tag>FunctionComponent(常量为0)

    负责解析函数组件的 props,并调用 updateFunctionComponent 执行组件的实际渲染。主要工作包括:

    1. 获取组件类型和待处理的 props。
    2. 解析默认 props(针对非类组件)。
    3. 调用函数组件的更新逻辑。
    case FunctionComponent: {
      // fiber的组件类型
      const Component = workInProgress.type;
      // 待处理props
      const unresolvedProps = workInProgress.pendingProps;
      
      const resolvedProps =
        disableDefaultPropsExceptForClasses ||
        workInProgress.elementType === Component
          ? unresolvedProps
          : resolveDefaultPropsOnNonClassComponent(Component, unresolvedProps);
      
      return updateFunctionComponent(
        current,// 表示当前的 Fiber 节点
        workInProgress,// 正在处理的fiber
        Component,// 函数组件
        resolvedProps,// 解析后的属性props
        renderLanes,// 渲染优先级车道
      );
    }

    updateFunctionComponent 

    updateFunctionComponent 函数负责执行函数组件,处理 Hooks,并根据返回的 JSX 内容生成新的子 Fiber 节点。该函数实现了函数组件的渲染逻辑、状态管理以及性能优化(如 bailout 机制)。 

    function updateFunctionComponent(
      current: null | Fiber,
      workInProgress: Fiber,
      Component: any,
      nextProps: any,
      renderLanes: Lanes,
    ) {
    
      let context;
      if (!disableLegacyContext && !disableLegacyContextForFunctionComponents) {
      //   // 未屏蔽的上下文
        const unmaskedContext = getUnmaskedContext(workInProgress, Component, true);
        // 经过屏蔽的上下文
        context = getMaskedContext(workInProgress, unmaskedContext);
      }
    
      let nextChildren;
      let hasId;
      
      prepareToReadContext(workInProgress, renderLanes);
      
      // 执行hooks
      nextChildren = renderWithHooks(
        current,
        workInProgress,
        Component,
        nextProps,
        context,
        renderLanes,
      );
    
      // 表示组件没有接收到新的更新。
      if (current !== null && !didReceiveUpdate) {
        // bailoutHooks 会跳过 Hooks 的更新
        bailoutHooks(current, workInProgress, renderLanes);
        // 直接复用之前的结果。
        return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
      }
    
      // React DevTools reads this flag.
      // 标记已完成
      workInProgress.flags |= PerformedWork;
      
      //reconcileChildren 函数用于对比新旧子节点,生成新的 Fiber 树结构。
      reconcileChildren(current, workInProgress, nextChildren, renderLanes);
      
      return workInProgress.child;
    }

    工具函数之 resolveDefaultPropsOnNonClassComponent

    resolveDefaultPropsOnNonClassComponent 是 React 中用于处理非类组件(如函数组件)默认 props 的函数。它会将组件定义的 defaultProps 对象与实际传入的 props 合并,确保未显式提供的 props 使用默认值。

    函数参数含义

    • Component:组件本身(函数或类)。
    • baseProps:实际传入的 props 对象。
      function resolveDefaultPropsOnNonClassComponent(
        Component: any,
        baseProps: Object,
      ): Object {
        // 若启用则仅对类组件保留默认 props 支持,函数组件将完全忽略 defaultProps。
        if (disableDefaultPropsExceptForClasses) {
          // Support for defaultProps is removed in React 19 for all types
          // except classes.
          return baseProps;
        }
        // 合并默认 props
        if (Component && Component.defaultProps) {
          // Resolve default props. Taken from ReactElement
          const props = assign({}, baseProps);
          const defaultProps = Component.defaultProps;
          for (const propName in defaultProps) {
            if (props[propName] === undefined) {
              props[propName] = defaultProps[propName];
            }
          }
          return props;
        }
        return baseProps;
      }

      工具函数之 bailoutHooks

      bailoutHooks 函数用于在组件无需重新渲染时跳过 Hooks 的更新。当组件的 props、context 或状态没有变化时,React 会触发 bailout 逻辑,直接复用之前的渲染结果,从而避免不必要的计算和副作用执行。

       function bailoutHooks(
        current: Fiber,
        workInProgress: Fiber,
        lanes: Lanes,
      ): void {
         // 复用 Hooks 更新队列
        workInProgress.updateQueue = current.updateQueue;
      
         // 清除副作用
         // PassiveEffect:表示存在需要异步执行的副作用(如 useEffect)。
      // UpdateEffect:表示存在需要同步执行的副作用(如 useLayoutEffect)。
        workInProgress.flags &= ~(PassiveEffect | UpdateEffect);
      
         // 从当前 Fiber 的 lanes 中移除本次渲染的优先级,表示该优先级的更新已处理完毕。
        current.lanes = removeLanes(current.lanes, lanes);
      }

      bailout 机制通常在以下情况触发:

      1. props 未变化:前后 props 对象通过浅比较(Object.is)相等。
      2. context 未变化:组件依赖的上下文值没有更新。
      3. 被 React.memo 包裹:函数组件被 React.memo 高阶组件包裹,且 props 未变化。
      4. 无状态更新:组件内部状态没有变化。

      工具函数之 bailoutOnAlreadyFinishedWork

      bailoutOnAlreadyFinishedWork 函数用于在组件无需重新渲染时直接复用现有 Fiber 树结构。当组件的 props、状态或上下文没有变化时,React 会触发 bailout 逻辑,跳过该组件及其子树的协调过程,直接复用之前的渲染结果,从而显著提升性能。

      function bailoutOnAlreadyFinishedWork(
        current: Fiber | null,
        workInProgress: Fiber,
        renderLanes: Lanes,
      ): Fiber | null {
        if (current !== null) {
          // 直接将当前 Fiber 的依赖信息复制到新 Fiber,避免重新收集依赖。
          workInProgress.dependencies = current.dependencies;
        }
      
        // 标记跳过的更新优先级
        markSkippedUpdateLanes(workInProgress.lanes);
      
        // Check if the children have any pending work.
        if (!includesSomeLane(renderLanes, workInProgress.childLanes)) {
      
          // 启用延迟上下文传播的
          if (enableLazyContextPropagation && current !== null) {
      
            lazilyPropagateParentContextChanges(current, workInProgress, renderLanes);
            if (!includesSomeLane(renderLanes, workInProgress.childLanes)) {
              return null;
            }
          } else {
            return null;
          }
        }
      
      // 克隆子节点
        cloneChildFibers(current, workInProgress);
        return workInProgress.child;
      }
      

       工具函数之 markSkippedUpdateLanes

      markSkippedUpdateLanes 是 React 性能监控系统中的关键函数,用于记录被跳过的更新优先级。当组件由于 bailout 机制(如 props 未变化)而跳过渲染时,React 使用该函数标记这些被跳过的优先级

      function markSkippedUpdateLanes(lane: Lane | Lanes): void {
        workInProgressRootSkippedLanes = mergeLanes(
          lane,
          workInProgressRootSkippedLanes,
        );
      }
      
      let workInProgressRootSkippedLanes: Lanes = NoLanes;

      工具函数之 includesSomeLane

      includesSomeLane 函数用于判断两个优先级集合(Lanes)是否存在交集。

      function includesSomeLane(a: Lanes | Lane, b: Lanes | Lane): boolean {
        return (a & b) !== NoLanes;
      }

      工具函数之 cloneChildFibers

      cloneChildFibers 函数用于在组件 bailout(跳过渲染)时浅克隆子 Fiber 节点。当父组件因 props 未变化而无需重新渲染时,React 会复用子 Fiber 结构,通过克隆操作创建新的 workInProgress 树,避免重新协调整个子树,从而显著提升性能。

      function cloneChildFibers(
        current: Fiber | null,
        workInProgress: Fiber,
      ): void {
        // 若 current 存在且子节点已变化,抛出错误
        if (current !== null && workInProgress.child !== current.child) {
          throw new Error('Resuming work not yet implemented.');
        }
      
        if (workInProgress.child === null) {
          return;
        }
      
        // 克隆首个子节点
        let currentChild = workInProgress.child;
        let newChild = createWorkInProgress(currentChild, currentChild.pendingProps);
        workInProgress.child = newChild;
      
        newChild.return = workInProgress;
        // 循环克隆所有兄弟节点
        while (currentChild.sibling !== null) {
          currentChild = currentChild.sibling;
          newChild = newChild.sibling = createWorkInProgress(
            currentChild,
            currentChild.pendingProps,
          );
          newChild.return = workInProgress;
        }
        // 最后一个节点的 sibling 设为 null,确保链表正确结束。
        newChild.sibling = null;
      }

      工具函数之 prepareToReadContext

      prepareToReadContext 函数是 React 渲染流程中的关键环节,用于为当前 Fiber 节点准备上下文读取环境。它主要完成以下工作:

      1. 设置当前渲染的 Fiber 节点。
      2. 重置上下文依赖链表。
      3. 处理上下文更新标记,确保依赖的上下文变化能触发组件重新渲染。
      function prepareToReadContext(
        workInProgress: Fiber,
        renderLanes: Lanes,
      ): void {
        // currentlyRenderingFiber:全局变量,指向当前正在渲染的 Fiber 节点。
      // lastContextDependency:全局变量,用于构建上下文依赖链表,初始化为 null。
        currentlyRenderingFiber = workInProgress;
        lastContextDependency = null;
      
        const dependencies = workInProgress.dependencies;
        if (dependencies !== null) {
          if (enableLazyContextPropagation) {
            // Reset the work-in-progress list
            // 重置依赖链表(延迟传播模式)
            dependencies.firstContext = null;
          } else {
            const firstContext = dependencies.firstContext;
            if (firstContext !== null) {
              if (includesSomeLane(dependencies.lanes, renderLanes)) {
                // Context list has a pending update. Mark that this fiber performed work.
                    // 上下文有更新,标记当前 Fiber 执行了工作
                markWorkInProgressReceivedUpdate();
              }
              // Reset the work-in-progress list
              dependencies.firstContext = null;
            }
          }
        }
      }

       <Tag>HostRoot

      case HostRoot:
        return updateHostRoot(current, workInProgress, renderLanes);

      工具函数之 updateHostRoot

      updateHostRoot 是 React 渲染流程中处理根组件(HostRoot Fiber)的核心函数,负责协调根组件的更新逻辑,包括状态处理、子节点 reconciliation、服务端渲染水合(Hydration)等。

      function updateHostRoot(
        current: null | Fiber,
        workInProgress: Fiber,
        renderLanes: Lanes,
      ) {
        // 推入根组件的上下文,确保子组件能访问正确的根状态。
        // pushHostRootContext(workInProgress);
      
        if (current === null) {
          throw new Error('Should have a current fiber. This is a bug in React.');
        }
      
        // 获取新 props 和旧状态
        const nextProps = workInProgress.pendingProps;
        const prevState = workInProgress.memoizedState;
        const prevChildren = prevState.element;
      
        // 复制当前更新队列到新的 workInProgress Fiber,确保更新操作的不可变性。
        cloneUpdateQueue(current, workInProgress);
        // 计算新的根状态(nextState),处理状态更新(如 setState)和副作用。
        processUpdateQueue(workInProgress, nextProps, null, renderLanes);
      
        const nextState: RootState = workInProgress.memoizedState;
        const root: FiberRoot = workInProgress.stateNode;
        // pushRootTransition(workInProgress, root, renderLanes);
      
       
        // suspendIfUpdateReadFromEntangledAsyncAction();
      
        const nextChildren = nextState.element;
        
        if (supportsHydration && prevState.isDehydrated) {
          
        
      
        } else {
        
          // resetHydrationState();
          
          // 若新子节点与旧子节点相同,通过 bailout 跳过调和过程,直接复用现有 Fiber。
          if (nextChildren === prevChildren) {
            return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
          }
      
          // 当子节点变化时,通过 reconcileChildren 生成新的子 Fiber 树,进入 diff 流程。
          reconcileChildren(current, workInProgress, nextChildren, renderLanes);
        }
        return workInProgress.child;
      }

      工具函数之 cloneUpdateQueue

      cloneUpdateQueue 是 React 内部用于克隆更新队列(Update Queue)的核心函数,主要作用是在调和(Reconciliation)阶段为 workInProgress Fiber 创建当前 Fiber(current)的更新队列副本。

      function cloneUpdateQueue<State>(
        current: Fiber,
        workInProgress: Fiber,
      ): void {
        // Clone the update queue from current. Unless it's already a clone.
        const queue: UpdateQueue<State> = (workInProgress.updateQueue: any);
        const currentQueue: UpdateQueue<State> = (current.updateQueue: any);
      
         // 仅当新旧队列引用相同时才执行克隆(避免重复克隆)
        if (queue === currentQueue) {
          const clone: UpdateQueue<State> = {
            baseState: currentQueue.baseState,
            firstBaseUpdate: currentQueue.firstBaseUpdate,
            lastBaseUpdate: currentQueue.lastBaseUpdate,
            shared: currentQueue.shared,
            callbacks: null, // 重置回调,避免旧回调影响新 Fiber
          };
          workInProgress.updateQueue = clone;
        }
      }
      interface UpdateQueue<State> {
        baseState: State;                // 基础状态(未处理更新的状态)
        firstBaseUpdate: Update<State>;  // 第一个未处理的更新
        lastBaseUpdate: Update<State>;   // 最后一个未处理的更新
        shared: { [key: string]: mixed }; // 共享状态(如上下文)
        callbacks: Callback | null;      // 更新回调函数
      }

      工具函数之 processUpdateQueue

      processUpdateQueue函数的核心作用是将组件的状态更新队列(queue)中的更新合并到当前状态(inst.state),确保状态按顺序更新,并处理函数式更新和对象合并逻辑。

      function processUpdateQueue(
        internalInstance: InternalInstance,
        inst: any,
        props: any,
        maskedLegacyContext: any,
      ): void {
        if (internalInstance.queue !== null && internalInstance.queue.length > 0) {
          // 处理更新队列
          
          const oldQueue = internalInstance.queue;
          // oldReplace:表示是否用新状态完全替换旧状态(而非合并)。
          const oldReplace = internalInstance.replace;
          // 重置队列为 null,避免重复处理
          internalInstance.queue = null;
          // 重置替换标志
          internalInstance.replace = false;
      
          // 仅一个更新项,直接替换状态。
          if (oldReplace && oldQueue.length === 1) {
            inst.state = oldQueue[0];
            
          } else {
            // 初始化 nextState
            let nextState = oldReplace ? oldQueue[0] : inst.state;
            // 是否需要创建新对象(避免直接修改旧状态)
            let dontMutate = true;
      
            // 遍历更新队列(从第一个有效更新开始)
            for (let i = oldReplace ? 1 : 0; i < oldQueue.length; i++) {
               // 获取当前更新项
              const partial = oldQueue[i];
              
              const partialState =
                typeof partial === 'function'
                // 处理函数式更新(如 setState((state) => ({ ...state, count: state.count + 1 })))
                  ? partial.call(inst, nextState, props, maskedLegacyContext)
                // 非函数式更新直接使用值
                  : partial;
              
              if (partialState != null) {
                if (dontMutate) {
                  // 首次修改,创建新对象以保持不可变性
                  dontMutate = false;
                  nextState = assign({}, nextState, partialState);
                } else {
                  // 后续修改直接合并(已创建新对象,可安全修改)
                  assign(nextState, partialState);
                }
              }
            }
            
            // 最终状态赋值
            inst.state = nextState;
          }
          
        } else {
          // 清空空队列
          internalInstance.queue = null;
        }
      }

       <Tag>HostHoistable

      React 渲染流程中处理 可提升资源节点(HostHoistable)。当浏览器支持资源优化(supportsResourcestrue)时,会调用 updateHostHoistable 函数对这类节点进行特殊处理,以优化关键资源(如 CSS、JavaScript)的加载顺序和优先级,从而提升应用性能。

      case HostHoistable:
        if (supportsResources) {
          return updateHostHoistable(current, workInProgress, renderLanes);
        }

      updateHostHoistable

      updateHostHoistable 是 React 渲染流程中处理 可提升资源节点(如 CSS、JS 等) 的核心函数。

      优化关键资源的加载执行流程:

      1. 标记 ref 相关副作用
      2. 初始化或更新资源对象(通过 getResource
      3. 管理资源状态(存储在 memoizedState 中)
      4. 决定是否创建 DOM 实例(非资源节点或非水合模式下)
      function updateHostHoistable(
        current: null | Fiber,
        workInProgress: Fiber,
        renderLanes: Lanes,
      ) {
        // 标记出来ref相关副作用
        markRef(current, workInProgress);
      
        // 首次渲染
        if (current === null) {
          // 通过 getResource 获取资源对象(如 CSS、JS 资源)
          const resource = getResource(
            workInProgress.type,
            null,
            workInProgress.pendingProps,
            null,
          );
          
          if (resource) {
            // 将资源对象存储在 memoizedState 中
            workInProgress.memoizedState = resource;
          } else {
            if (!getIsHydrating()) {
              // This is not a Resource Hoistable and we aren't hydrating so we construct the instance.
              // 创建非资源类型的可提升节点(如普通 DOM 元素)
              workInProgress.stateNode = createHoistableInstance(
                workInProgress.type,
                workInProgress.pendingProps,
                getRootHostContainer(),
                workInProgress,
              );
            }
          }
        } else {
          // Get Resource may or may not return a resource. either way we stash the result
          // on memoized state.
          // 对比新旧 props,决定是否需要更新资源
          // 复用或创建新资源对象,更新到 memoizedState
          workInProgress.memoizedState = getResource(
            workInProgress.type,
            current.memoizedProps,
            workInProgress.pendingProps,
            current.memoizedState,
          );
        }
      
        return null;
      }

      工具函数之 markRef

      markRef 函数主要作用是标记 workInProgress Fiber 是否需要执行 ref 相关的副作用(Effect)。

      function markRef(current: Fiber | null, workInProgress: Fiber) {
       
        const ref = workInProgress.ref;
        if (ref === null) {
          if (current !== null && current.ref !== null) {
            // Schedule a Ref effect
            workInProgress.flags |= Ref | RefStatic;
          }
        } else {
          if (typeof ref !== 'function' && typeof ref !== 'object') {
            throw new Error(
              'Expected ref to be a function, an object returned by React.createRef(), or undefined/null.',
            );
          }
          if (current === null || current.ref !== ref) {
            // Schedule a Ref effect
            workInProgress.flags |= Ref | RefStatic;
          }
        }
      }

      createHoistableInstance

      创建可提升实例 

      function createHoistableInstance(
        type: string,
        props: Props,
        rootContainerInstance: Container,
        internalInstanceHandle: Object,
      ): Instance {
        //n获取document对象
        const ownerDocument = getOwnerDocumentFromRootContainer(
          rootContainerInstance,
        );
      
        // 创建element
        const domElement: Instance = ownerDocument.createElement(type);
      
        // 用于建立 DOM 节点与 Fiber 节点双向映射
        precacheFiberNode(internalInstanceHandle, domElement);
      
        // 将 JSX 中的 props 信息存储到对应 DOM 节点上
        updateFiberProps(domElement, props);
      
        
        setInitialProperties(domElement, type, props);
      
        // 标记 DOM 节点为 可提升(Hoistable) 
        markNodeAsHoistable(domElement);
        return domElement;
      }

      工具函数之 precacheFiberNode

      precacheFiberNode 是 React 内部用于建立 DOM 节点与 Fiber 节点双向映射的核心函数。

      function precacheFiberNode(
        hostInst: Fiber,
        node: Instance | TextInstance | SuspenseInstance | ReactScopeInstance,
      ): void {
        (node: any)[internalInstanceKey] = hostInst;
      }
      
      const internalInstanceKey = '__reactFiber$' + randomKey;

      工具函数之 updateFiberProps

      updateFiberProps 是 React 内部用于将 JSX 中的 props 信息存储到对应 DOM 节点上的工具函数。

      function updateFiberProps(
        node: Instance | TextInstance | SuspenseInstance,
        props: Props,
      ): void {
        (node: any)[internalPropsKey] = props;
      }
      
      const internalPropsKey = '__reactProps$' + randomKey;

      工具函数之 markNodeAsHoistable

      markNodeAsHoistable 是 React 内部用于标记 DOM 节点为 可提升(Hoistable) 的工具函数。

      function markNodeAsHoistable(node: Node) {
        (node: any)[internalHoistableMarker] = true;
      }
      
      const internalHoistableMarker = '__reactMarker$' + randomKey;

      getResource

      getResource 是 React 内部用于管理和复用关键资源(如 CSS、JavaScript 文件)的核心函数。它通过资源根节点(resourceRoot)追踪已加载的资源,实现资源共享、预加载和避免重复加载,从而优化应用性能。

       function getResource(
        type: string,
        currentProps: any,
        pendingProps: any,
        currentResource: null | Resource,
      ): null | Resource {
         // 获取资源根节点
        const resourceRoot = getCurrentResourceRoot();
        if (!resourceRoot) {
          throw new Error(
            '"resourceRoot" was expected to exist. This is a bug in React.',
          );
        }
        switch (type) {
          case 'meta':
          case 'title': {
            return null;
          }
            // 处理资源类型style
          case 'style': {
            if (
              // precedence:样式优先级(如 'high'、'low'),用于控制加载顺序。
              typeof pendingProps.precedence === 'string' &&
              // href:外部样式表的 URL。
              typeof pendingProps.href === 'string'
            ) {
               // 资源键生成。getStyleKey:生成 URL 的唯一哈希值,确保相同 URL 的资源被复用。
              const key = getStyleKey(pendingProps.href);
              // 查找资源。hoistableStyles:Map 对象,键为资源 URL 哈希值,值为资源对象。
              const styles = getResourcesFromRoot(resourceRoot).hoistableStyles;
              
              let resource = styles.get(key);
              if (!resource) {
                // 资源对象结构
                
                resource = {
                  type: 'style', // 资源类型
                  instance: null, // DOM 实例(加载后填充)
                  count: 0, // 引用计数(用于垃圾回收)
                  state: null, // 资源状态(如加载中、已完成)
                };
      
                // 将新资源存入缓存
                styles.set(key, resource);
              }
              return resource;
            }
      
            // 无效资源处理
            return {
              type: 'void', // 特殊类型,表示无效资源
              instance: null,
              count: 0,
              state: null,
            };
            
          }
      
            // 处理资源类型link
          case 'link': {
            if (
              // rel="stylesheet":确认是样式表资源
              pendingProps.rel === 'stylesheet' &&
              // href 和 precedence 存在且类型正确
              typeof pendingProps.href === 'string' &&
              typeof pendingProps.precedence === 'string'
            ) {
              const qualifiedProps: StylesheetQualifyingProps = pendingProps;
              // 生成唯一key
              const key = getStyleKey(qualifiedProps.href);
      
              // 查找资源
              const styles = getResourcesFromRoot(resourceRoot).hoistableStyles;
      
              let resource = styles.get(key);
              
              if (!resource) {
                
                const ownerDocument = getDocumentFromRoot(resourceRoot);
                
                // 定义资源结构
                resource = ({
                  type: 'stylesheet',
                  instance: null, // 对应 DOM 元素
                  count: 0, // 引用计数
                  state: {
                    loading: NotLoaded, // 加载状态
                    preload: null, // 预加载 Promise
                  },
                }: StylesheetResource);
      
                // 存入缓存
                styles.set(key, resource);
      
                // 通过 CSS 选择器查找已存在的 <link> 标签
                const instance = ownerDocument.querySelector(
                  getStylesheetSelectorFromKey(key),
                );
                if (instance) {
                  // 使用内部属性 _p 判断加载状态
                  const loadingState: ?Promise<mixed> = (instance: any)._p;
                  if (loadingState) {
                    // This instance is inserted as part of a boundary reveal and is not yet
                    // loaded
                    // 正在加载中
                  } else {
                    // 实例已经加载完成
                    // This instance is already loaded
                    resource.instance = instance;
                    resource.state.loading = Loaded | Inserted;
                  }
                }
      
                // 预加载机制流程:
                  // 生成预加载配置(如 as="style")
                  // 创建 <link rel="preload"> 标签
                  // 监听加载完成事件,更新资源状态
                if (!preloadPropsMap.has(key)) {
                  const preloadProps = preloadPropsFromStylesheet(qualifiedProps);
                  preloadPropsMap.set(key, preloadProps);
                  if (!instance) {
                    preloadStylesheet(
                      ownerDocument,
                      key,
                      preloadProps,
                      resource.state,
                    );
                  }
                }
              }
              
              // if (currentProps && currentResource === null) {
              //   let diff = '';
              // }
              return resource;
              
            } else {
              // if (currentProps && currentResource !== null) {
              //   let diff = '';
              // }
              return null;
            }
          }
          case 'script': {
            const async = pendingProps.async;
            const src = pendingProps.src;
            if (
              typeof src === 'string' &&
              async &&
              typeof async !== 'function' &&
              typeof async !== 'symbol'
            ) {
              const key = getScriptKey(src);
              const scripts = getResourcesFromRoot(resourceRoot).hoistableScripts;
      
              let resource = scripts.get(key);
              if (!resource) {
                
                resource = {
                  type: 'script',
                  instance: null,
                  count: 0,
                  state: null,
                };
                
                scripts.set(key, resource);
              }
              return resource;
            }
            return  {
              type: 'void',
              instance: null,
              count: 0,
              state: null,
            };
            
          }
          default: {
            throw new Error(
              `getResource encountered a type it did not expect: "${type}". this is a bug in React.`,
            );
          }
        }
      }

      1、处理style类型的资源

      处理 外部样式表资源(<style> 标签) 的逻辑分支。它通过 precedencehref 属性识别需要优化加载的样式资源,利用缓存机制避免重复加载,并返回标准化的资源对象。

      2、处理link类型的资源

      React 内部处理 <link rel="stylesheet"> 资源的核心逻辑,主要负责:

      1. 资源去重:通过 URL 缓存避免重复加载同一 CSS 文件
      2. 状态管理:跟踪样式表的加载状态(未加载、加载中、已完成)
      3. 预加载优化:使用 <link rel="preload"> 加速关键样式的加载
      4. 服务端渲染集成:支持与 SSR 流程配合,提前收集关键 CSS

      3、处理script类型的资源

       

      工具函数之 preloadPropsFromStylesheet

      preloadPropsFromStylesheet 是 React 内部用于将 <link rel="stylesheet"> 转换为 <link rel="preload"> 的工具函数。

      function preloadPropsFromStylesheet(
        props: StylesheetQualifyingProps,
      ): PreloadProps {
        return {
          rel: 'preload', // 将 rel 从 'stylesheet' 改为 'preload'
          as: 'style', // 指定资源类型为样式表
          href: props.href, // 保留原始 URL
          crossOrigin: props.crossOrigin, // 跨域配置
          integrity: props.integrity,  // 内容完整性校验
          media: props.media, // 媒体查询条件
          hrefLang: props.hrefLang,  // 语言设置
          referrerPolicy: props.referrerPolicy, // 引用策略
        };
      }

      // 原始 JSX
      <link rel="stylesheet" href="critical.css" precedence="high" />
      
      // React 处理后
      <link rel="preload" as="style" href="critical.css" />  // 预加载阶段
      <link rel="stylesheet" href="critical.css" />         // 正式应用阶段

      工具函数之 preloadStylesheet

      preloadStylesheet 是 React 内部用于预加载 CSS 资源的核心函数,通过创建 <link rel="preload"> 标签实现样式表的并行加载,避免阻塞主线程渲染。

      function preloadStylesheet(
        ownerDocument: Document,
        key: string,
        preloadProps: PreloadProps,
        state: StylesheetState,
      ) {
        // 检查已有预加载标签
        const preloadEl = ownerDocument.querySelector(
          getPreloadStylesheetSelectorFromKey(key),
        );
        if (preloadEl) {
          // If we find a preload already it was SSR'd and we won't have an actual
          // loading state to track. For now we will just assume it is loaded
          // 服务端渲染已插入预加载标签,直接标记为已加载
          state.loading = Loaded;
        } else {
          // 创建预加载标签
          const instance = ownerDocument.createElement('link');
          state.preload = instance;
          
          // 监听加载事件
          instance.addEventListener('load', () => (state.loading |= Loaded));
          instance.addEventListener('error', () => (state.loading |= Errored));
      
          // 设置标签属性并插入文档
          setInitialProperties(instance, 'link', preloadProps);
          markNodeAsHoistable(instance); // 标记为可提升资源
          (ownerDocument.head: any).appendChild(instance); // 插入到文档头部
        }
      }
      function getPreloadStylesheetSelectorFromKey(key: string) {
        return `link[rel="preload"][as="style"][${key}]`;
      }

      工具函数之 getCurrentResourceRoot

      getCurrentResourceRoot() 是 React 内部用于获取当前渲染环境中 可提升资源根节点(HoistableRoot) 的工具函数。

      function getCurrentResourceRoot(): null | HoistableRoot {
        // 获取当前根容器
        const currentContainer = getCurrentRootHostContainer();
        // getHoistableRoot提取可提升资源根节点
        return currentContainer ? getHoistableRoot(currentContainer) : null;
      }
      function getCurrentRootHostContainer(): null | Container {
        return rootInstanceStackCursor.current;
      }
      function createCursor<T>(defaultValue: T): StackCursor<T> {
        return {
          current: defaultValue,
        };
      }

       工具函数之 getHoistableRoot

      function getHoistableRoot(container: Container): HoistableRoot {
        return typeof container.getRootNode === 'function'
          // Node 接口的 getRootNode() 方法返回上下文中的根节点
          ?  container.getRootNode()
          // Node.ownerDocument 只读属性会返回当前节点的顶层的 document 对象
          : container.ownerDocument;
      }

      工具函数之 getResourcesFromRoot 

      function getResourcesFromRoot(root: HoistableRoot): RootResources {
        // 获取节点上的设置的资源
        let resources = (root: any)[internalRootNodeResourcesKey];
        if (!resources) {
          // 设置
          resources = (root: any)[internalRootNodeResourcesKey] = {
            hoistableStyles: new Map(),
            hoistableScripts: new Map(),
          };
        }
        return resources;
      }
      
      const internalRootNodeResourcesKey = '__reactResources$' + randomKey;

       <Tag>HostSingleton

      React 渲染流程中处理 单节点宿主组件。

      
      // Fall through
      case HostSingleton:
        if (supportsSingletons) {
          return updateHostSingleton(current, workInProgress, renderLanes);
        }

      updateHostSingleton

      updateHostSingleton 是 React 渲染流程中处理 单节点宿主组件(如 <div><span> 等 DOM 元素) 的核心函数。

      function updateHostSingleton(
        current: Fiber | null,
        workInProgress: Fiber,
        renderLanes: Lanes,
      ) {
        // 将当前 Fiber 节点的上下文(如命名空间、文档模式)压入栈中
        pushHostContext(workInProgress);
      
        if (current === null) {
          // 服务端渲染水合处理
          // claimHydratableSingleton(workInProgress);
        }
      
        const nextChildren = workInProgress.pendingProps.children;
      
        // 首次渲染
        if (current === null && !getIsHydrating()) {
          // 使用 reconcileChildFibers 创建新的子 Fiber 树
          workInProgress.child = reconcileChildFibers(
            workInProgress,
            null,
            nextChildren,
            renderLanes,
          );
        } else {
          // 更新
          // 使用 reconcileChildren 对比新旧子节点,执行最小化 DOM 操作
          reconcileChildren(current, workInProgress, nextChildren, renderLanes);
        }
        // 标记ref副作用
        markRef(current, workInProgress);
         // 返回子 Fiber 节点
        return workInProgress.child;
      }
      

       <Tag>HostComponent 

      React 渲染流程中处理 宿主组件(如 HTML 标签)。

      // Fall through
      case HostComponent:
        return updateHostComponent(current, workInProgress, renderLanes);

      工具函数之 updateHostComponent

      updateHostComponent 是 React 渲染流程中处理 宿主组件(如 HTML 标签) 的核心函数。

      function updateHostComponent(
        current: Fiber | null,
        workInProgress: Fiber,
        renderLanes: Lanes,
      ) {
        if (current === null) {
          // tryToClaimNextHydratableInstance(workInProgress);
        }
      
        // 设置当前渲染上下文
        pushHostContext(workInProgress);
      
        const type = workInProgress.type;
        const nextProps = workInProgress.pendingProps;
        const prevProps = current !== null ? current.memoizedProps : null;
      
        let nextChildren = nextProps.children;
        const isDirectTextChild = shouldSetTextContent(type, nextProps);
      
        // 对于纯文本子节点(如 <div>Hello</div>),直接设置 textContent
        // 避免创建额外的文本节点,提升渲染效率
        if (isDirectTextChild) {
          nextChildren = null;
        } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) {
          // If we're switching from a direct text child to a normal child, or to
          // empty, we need to schedule the text content to be reset.
          workInProgress.flags |= ContentReset;
        }
      
        // 异步状态处理(并发模式)
        if (enableAsyncActions) {
          const memoizedState = workInProgress.memoizedState;
          if (memoizedState !== null) {
      
             // renderTransitionAwareHostComponentWithHooks 处理异步更新
            const newState = renderTransitionAwareHostComponentWithHooks(
              current,
              workInProgress,
              renderLanes,
            );
            
            // 根据渲染器类型(主渲染器或辅助渲染器)更新上下文值
            if (isPrimaryRenderer) {
              // _currentValue 存储主渲染器的上下文值
              HostTransitionContext._currentValue = newState;
            } else {
              // _currentValue2 存储辅助渲染器的上下文值
              HostTransitionContext._currentValue2 = newState;
            }
      
            // 懒传播
            if (enableLazyContextPropagation) {
              // In the lazy propagation implementation, we don't scan for matching
              // consumers until something bails out.
            } else {
              if (didReceiveUpdate) {
                if (current !== null) {
                  const oldStateHook: Hook = current.memoizedState;
                  const oldState: TransitionStatus = oldStateHook.memoizedState;
                
                  if (oldState !== newState) {
                    // 更新上下文并传播变化
                    propagateContextChange(
                      workInProgress,
                      HostTransitionContext,
                      renderLanes,
                    );
                  }
                }
              }
            }
          }
        }
      
        markRef(current, workInProgress);
        // 协调子节点
        reconcileChildren(current, workInProgress, nextChildren, renderLanes);
        return workInProgress.child;
      }

      renderTransitionAwareHostComponentWithHooks 

      处理hook钩子函数。

      function renderTransitionAwareHostComponentWithHooks(
        current: Fiber | null,
        workInProgress: Fiber,
        lanes: Lanes,
      ): TransitionStatus {
        if (!enableAsyncActions) {
          throw new Error('Not implemented.');
        }
        return renderWithHooks(
          current,
          workInProgress,
          TransitionAwareHostComponent,
          null,
          null,
          lanes,
        );
      }

      工具函数之 propagateContextChange 

      function propagateContextChange<T>(
        workInProgress: Fiber,
        context: ReactContext<T>,
        renderLanes: Lanes,
      ): void {
        if (enableLazyContextPropagation) {
         
          const forcePropagateEntireTree = true;
          propagateContextChanges(
            workInProgress,
            [context],
            renderLanes,
            forcePropagateEntireTree,
          );
        } else {
          propagateContextChange_eager(workInProgress, context, renderLanes);
        }
      }

      工具函数之 propagateContextChange_eager

      propagateContextChange_eager 是 React 中用于 主动传播上下文变化 的核心函数(适用于非懒传播模式)。当上下文(Context)的值发生改变时,该函数会遍历相关 Fiber 树,找到依赖该上下文的组件并为其标记更新,确保组件能响应上下文变化并重新渲染。

      function propagateContextChange_eager<T>(
        workInProgress: Fiber,
        context: ReactContext<T>,
        renderLanes: Lanes,
      ): void {
        // Only used by eager implementation
        if (enableLazyContextPropagation) {
          return;
        }
      
        // Fiber 树遍历初始化
        let fiber = workInProgress.child;
        if (fiber !== null) {
          // Set the return pointer of the child to the work-in-progress fiber.
          // 设置子节点的 return 指针指向父节点
          fiber.return = workInProgress;
        }
        // 深度优先遍历循环
        while (fiber !== null) {
          let nextFiber;
      
          // Visit this fiber.
          // 获取当前节点依赖的上下文列表
          const list = fiber.dependencies;
          if (list !== null) {
            nextFiber = fiber.child;
      
            let dependency = list.firstContext;
            while (dependency !== null) {
              // Check if the context matches.
               // 匹配到目标上下文,触发更新逻辑
              if (dependency.context === context) {
                
                // Match! Schedule an update on this fiber.
                   // 为类组件生成强制更新
                if (fiber.tag === ClassComponent) {
                  // Schedule a force update on the work-in-progress.
                  const lane = pickArbitraryLane(renderLanes);
                  
                  const update = createUpdate(lane);
                  update.tag = ForceUpdate;
       
                  // Inlined `enqueueUpdate` to remove interleaved update check
                   // 入队更新(直接操作队列,避免中间检查)
                  const updateQueue = fiber.updateQueue;
                  if (updateQueue === null) {
                    // Only occurs if the fiber has been unmounted.
                  } else {
                    const sharedQueue: SharedQueue<any> = (updateQueue: any).shared;
                    const pending = sharedQueue.pending;
      
                    // update是是一个循环链表结构
                    if (pending === null) {
                      // This is the first update. Create a circular list.
                      update.next = update;
                    } else {
                      update.next = pending.next;
                      pending.next = update;
                    }
                    sharedQueue.pending = update;
                  }
                }
      
                // 标记当前节点及其 alternate 节点的更新优先级
                fiber.lanes = mergeLanes(fiber.lanes, renderLanes);
                const alternate = fiber.alternate;
                if (alternate !== null) {
                  // 合并车道
                  alternate.lanes = mergeLanes(alternate.lanes, renderLanes);
                }
                 // 向上传播任务到父路径
                scheduleContextWorkOnParentPath(
                  fiber.return,
                  renderLanes,
                  workInProgress,
                );
      
                // Mark the updated lanes on the list, too.
                list.lanes = mergeLanes(list.lanes, renderLanes);
      
                // Since we already found a match, we can stop traversing the
                // dependency list.
                // 找到一个匹配后,无需继续遍历依赖列表
                break;
              }
              dependency = dependency.next;
            }
          } else if (fiber.tag === ContextProvider) {
            // Don't scan deeper if this is a matching provider
              // 若当前节点是匹配的 Provider,停止向下遍历(避免重复处理)
            nextFiber = fiber.type === workInProgress.type ? null : fiber.child;
            
          } else if (fiber.tag === DehydratedFragment) {
             // 处理 Suspense 边界的脱水片段,标记其父 Suspense 节点
            const parentSuspense = fiber.return;
      
            if (parentSuspense === null) {
              throw new Error(
                'We just came from a parent so we must have had a parent. This is a bug in React.',
              );
            }
      
            parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes);
            const alternate = parentSuspense.alternate;
            if (alternate !== null) {
              alternate.lanes = mergeLanes(alternate.lanes, renderLanes);
            }
      
            scheduleContextWorkOnParentPath(
              parentSuspense,
              renderLanes,
              workInProgress,
            );
            // 跳过子树,直接处理兄弟节点
            nextFiber = fiber.sibling;
          } else {
            // Traverse down.
            nextFiber = fiber.child;
          }
      
          if (nextFiber !== null) {
            // Set the return pointer of the child to the work-in-progress fiber.
            nextFiber.return = fiber;
          } else {
            // No child. Traverse to next sibling.
            nextFiber = fiber;
            while (nextFiber !== null) {
              if (nextFiber === workInProgress) {
                // We're back to the root of this subtree. Exit.
                nextFiber = null;
                break;
              }
              const sibling = nextFiber.sibling;
              if (sibling !== null) {
                // Set the return pointer of the sibling to the work-in-progress fiber.
                sibling.return = nextFiber.return;
                nextFiber = sibling;
                break;
              }
              // No more siblings. Traverse up.
              nextFiber = nextFiber.return;
            }
          }
          fiber = nextFiber;
        }
      }

      工具函数之 scheduleContextWorkOnParentPath

      scheduleContextWorkOnParentPath 是 React 中用于 向上传播上下文更新任务 的核心函数

      function scheduleContextWorkOnParentPath(
        parent: Fiber | null,
        renderLanes: Lanes,
        propagationRoot: Fiber,
      ) {
        // Update the child lanes of all the ancestors, including the alternates.
        let node = parent;
        // 从当前父节点出发遍历
        while (node !== null) {
          // 获取备用 Fiber 节点(双缓冲机制)
          const alternate = node.alternate;
      
          // 检查当前节点的 childLanes 是否包含新的 renderLanes
          if (!isSubsetOfLanes(node.childLanes, renderLanes)) {
            // 合并车道
            node.childLanes = mergeLanes(node.childLanes, renderLanes);
            
            if (alternate !== null) {
              // 同步更新备用节点
              alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
            }
          } else if (
            alternate !== null &&
            !isSubsetOfLanes(alternate.childLanes, renderLanes)
          ) {
            alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
          }
          //  到达传播根节点,停止遍历
          if (node === propagationRoot) {
            break;
          }
          // 向上处理父节点
          node = node.return;
        }
      }
      

       <Tag>HostText 

      case HostText:
        return updateHostText(current, workInProgress);

      updateHostText 

      function updateHostText(current: null | Fiber, workInProgress: Fiber) {
        // 说明首次渲染或没有可对比的旧fiber
        if (current === null) {
          //tryToClaimNextHydratableTextInstance(workInProgress);
        }
      
        return null;
      }

       <Tag>HostPortal 

      case HostPortal:
        return updatePortalComponent(current, workInProgress, renderLanes);

      updatePortalComponent 

      function updatePortalComponent(
        current: Fiber | null,
        workInProgress: Fiber,
        renderLanes: Lanes,
      ) {
        pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
        
        const nextChildren = workInProgress.pendingProps;
        if (current === null) {
          
          workInProgress.child = reconcileChildFibers(
            workInProgress,
            null,
            nextChildren,
            renderLanes,
          );
        } else {
          reconcileChildren(current, workInProgress, nextChildren, renderLanes);
        }
        return workInProgress.child;
      }

      渲染阶段二completeUnitOfWork

      completeUnitOfWork 函数在 React 的协调过程中负责完成单个 Fiber 节点的工作单元。它会不断尝试完成当前 Fiber 节点的工作,处理可能出现的未完成情况,根据处理结果决定是继续处理兄弟节点还是返回父节点,直到完成整个 Fiber 树的工作,并在到达根节点时更新根节点的退出状态。

      执行过程:

      1. 初始化当前要处理的 filbert 节点,定义为completedWork。
      2. do...while 循环,直到completedWork 为 null。
        1. 如果 fiber 是否存在未完成的工作,调用 unwindUnitOfWork 函数处理未完成的工作,然后跳出 do...while 循环。
        2. 没有未完成的工作,则调用 completeWork 完成当前节点的工作。
      function completeUnitOfWork(unitOfWork: Fiber): void {
      
        // completedWork 初始化为传入的 unitOfWork
        let completedWork: Fiber = unitOfWork;
      
        // 使用 do-while 循环来处理 Fiber 节点的工作
        do {
          // 检查 completedWork 的 flags 属性中是否包含 Incomplete 标志。如果包含,说明当前 Fiber 节点的工作未完成。
          if ((completedWork.flags & Incomplete) !== NoFlags) {
            const skipSiblings = workInProgressRootDidSkipSuspendedSiblings;
      
            // 用 unwindUnitOfWork 函数处理未完成的工作
            unwindUnitOfWork(completedWork, skipSiblings);
            return;
          }
      
         // 获取当前 Fiber 节点的替代节点,用于存储旧的状态。
          const current = completedWork.alternate;
          
          // 获取当前 Fiber 节点的父节点,用于在完成当前节点工作后返回父节点继续处理。
          const returnFiber = completedWork.return;
      
          // 用于存储 completeWork 函数返回的下一个要处理的 Fiber 节点。
          let next;
          // 调用 startProfilerTimer 函数开始记录性能分析时间。
          // startProfilerTimer(completedWork);
      
          // 调用 completeWork 函数完成当前 Fiber 节点的工作,传入当前 Fiber 节点的替代节点 current、当前 Fiber 节点 completedWork 以及相关的渲染车道 entangledRenderLanes。
          next = completeWork(current, completedWork, entangledRenderLanes);
      
      
          // 如果 next 不为 null,说明完成当前 Fiber 节点的工作产生了新的工作。
          if (next !== null) {
            // Completing this fiber spawned new work. Work on that next.
            // 将 next 赋值给 workInProgress,表示下一个要处理的 Fiber 节点成为当前的工作进行中的节点,函数直接返回。
            workInProgress = next;
            return;
          }
      
          // 获取当前 Fiber 节点的兄弟节点 siblingFiber。
          const siblingFiber = completedWork.sibling;
          if (siblingFiber !== null) {
            // If there is more work to do in this returnFiber, do that next.
            // 如果兄弟节点不为 null,将兄弟节点赋值给 workInProgress,表示接下来要处理兄弟节点的工作,函数直接返回。
            workInProgress = siblingFiber;
            return;
          }
      
          // 如果没有新产生的工作,也没有兄弟节点,将 completedWork 更新为其父节点 returnFiber,同时更新 workInProgress 为父节点,继续处理父节点的工作。
         
          completedWork = returnFiber;
          // Update the next thing we're working on in case something throws.
          workInProgress = completedWork;
          
          // 只要 completedWork 不为 null,就会继续循环处理。
        } while (completedWork !== null);
      
        // We've reached the root.
        // 如果根节点的退出状态为 RootInProgress(正在进行中),将其更新为 RootCompleted(已完成)。
        if (workInProgressRootExitStatus === RootInProgress) {
          workInProgressRootExitStatus = RootCompleted;
        }
      }
      

      completeWork

      completeWork 函数的主要职责是根据当前 Fiber 节点的类型(通过 workInProgress.tag 标识),对该节点进行相应的处理,比如更新 DOM、设置属性等。(负责单个fiber节点的处理)

      function completeWork(
        current: Fiber | null,
        workInProgress: Fiber,
        renderLanes: Lanes,
      ): Fiber | null {
        
        const newProps = workInProgress.pendingProps;
        popTreeContext(workInProgress);
        
        switch (workInProgress.tag) {
            // 省略的代码
      
          case Throw: {
            if (!disableLegacyMode) {
              // Only Legacy Mode completes an errored node.
              return null;
            }
          }
        }
      
        throw new Error(
          `Unknown unit of work tag (${workInProgress.tag}). This error is likely caused by a bug in ` +
            'React. Please file an issue.',
        );
      }

       <Tag>FunctionComponent/LazyComponent/ForwardRef/...

      case LazyComponent:
      case SimpleMemoComponent:
      case FunctionComponent:
      case ForwardRef:
      case Fragment:
      case Mode:
      case Profiler:
      case ContextConsumer:
      case MemoComponent:
        bubbleProperties(workInProgress);
        return null;
      

      bubbleProperties

      bubbleProperties 函数的主要功能是从一个已完成工作的 Fiber 节点(completedWork)的子节点中收集信息,将这些信息冒泡到该节点上。这些信息主要包括子节点的渲染优先级车道(Lanes)和副作用标志(Flags)。

      function bubbleProperties(completedWork: Fiber) {
      
        // 如果 completedWork 存在替代节点(alternate),并且替代节点的子节点与当前节点的子节点相同,则认为可以跳过更新。
        const didBailout =
          completedWork.alternate !== null &&
          completedWork.alternate.child === completedWork.child;
      
        // 用于存储合并后的子节点的渲染优先级车道,初始化为 NoLanes(表示没有车道)。
        let newChildLanes: Lanes = NoLanes;
        // 用于存储合并后的子节点的副作用标志,初始化为 NoFlags(表示没有标志)。
        let subtreeFlags = NoFlags;
      
         // 未跳过更新的情况
        if (!didBailout) {
          let child = completedWork.child;
          // 使用 while 循环遍历 completedWork 的所有子节点:
          while (child !== null) {
            // 合并子节点的 lanes 和 childLanes 到newChildLanes
            newChildLanes = mergeLanes(
              newChildLanes,
              mergeLanes(child.lanes, child.childLanes),
            );
      
            // 将子节点的 subtreeFlags 和 flags 合并到 subtreeFlags 中
            subtreeFlags |= child.subtreeFlags;
            subtreeFlags |= child.flags;
            
            child.return = completedWork;
      
            // 继续下一个兄弟节点
            child = child.sibling;
          }
      
          // 更新
          completedWork.subtreeFlags |= subtreeFlags;
          
        } else {
          
          let child = completedWork.child;
          while (child !== null) {
            // 合并子节点的 lanes 和 childLanes 到 newChildLanes 中。
            newChildLanes = mergeLanes(
              newChildLanes,
              mergeLanes(child.lanes, child.childLanes),
            );
      
            // ignore them.
            // 使用按位与运算符 & 过滤掉非静态的标志(通过 StaticMask)。
            subtreeFlags |= child.subtreeFlags & StaticMask;
            subtreeFlags |= child.flags & StaticMask;
            child.return = completedWork;
            child = child.sibling;
          }
      
          completedWork.subtreeFlags |= subtreeFlags;
        }
      
        completedWork.childLanes = newChildLanes;
        return didBailout;
      }

       <Tag>HostRoot

      React 处理 HostRoot 类型节点(即应用根节点)的核心逻辑,主要负责完成根节点渲染后的环境清理、状态同步和副作用标记。

      case HostRoot: {
        // 1、获取 FiberRoot 实例,React 应用的根对象,包含应用状态、优先级队列等核心信息。
        const fiberRoot = (workInProgress.stateNode: FiberRoot);
      
        //2、缓存处理
        if (enableCache) {
          let previousCache: Cache | null = null;
          if (current !== null) {
            previousCache = current.memoizedState.cache;
          }
          const cache: Cache = workInProgress.memoizedState.cache;
          // 比较新旧缓存对象,若不同则标记 Passive 副作用(如 useEffect)
          if (cache !== previousCache) {
            // Run passive effects to retain/release the cache.
            workInProgress.flags |= Passive;
          }
          // 清理缓存上下文栈
          popCacheProvider(workInProgress, cache);
        }
      
        // 3、环境状态恢复
        // 弹出过渡状态:结束当前渲染的过渡(如 startTransition)。
        popRootTransition(workInProgress, fiberRoot, renderLanes);
        // 弹出宿主容器:恢复 DOM 根节点上下文(见 popHostContainer 函数)
        popHostContainer(workInProgress);
        // 弹出遗留上下文:清理旧版 context API 的状态。
        popTopLevelLegacyContextObject(workInProgress);
      
        // 4、上下文状态同步
        // 在渲染过程中收集的新上下文值,在此处应用到根节点。
        if (fiberRoot.pendingContext) {
          fiberRoot.context = fiberRoot.pendingContext;
          fiberRoot.pendingContext = null;
        }
        //5、处理水合
        // 处理首次渲染或无子节点的情况
        if (current === null || current.child === null) {
          // If we hydrated, pop so that we can delete any remaining children
          // that weren't hydrated.
          // popHydrationState:清理水合过程中的临时状态,并返回是否成功水合。
          const wasHydrated = popHydrationState(workInProgress);
          // 水合成功
          if (wasHydrated) {
            // emitPendingHydrationWarnings();
            // 标记更新,可能用于处理残留的 DOM 差异。
            // markUpdate(workInProgress);
          } else {
            // 未水合或水合失败的处理
            
            if (current !== null) {
              const prevState: RootState = current.memoizedState;
              if (
                // Check if this is a client root
                 // 非脱水状态(纯客户端渲染)
                !prevState.isDehydrated ||
                // Check if we reverted to client rendering (e.g. due to an error)
                // 强制客户端渲染标志(如水合错误)
                (workInProgress.flags & ForceClientRender) !== NoFlags
              ) {
             // Snapshot 标志:触发 getSnapshotBeforeUpdate 生命周期(若适用)。
                workInProgress.flags |= Snapshot;
                // upgradeHydrationErrorsToRecoverable:将水合错误转换为可恢复错误,避免整页崩溃。
                upgradeHydrationErrorsToRecoverable();
              }
            }
          }
        }
        
        // 6、更新宿主容器与冒泡属性
        // 更新宿主容器:生成 DOM 更新队列(如属性变化、子节点增删)。
        updateHostContainer(current, workInProgress);
        // 冒泡属性:向上传递子树的状态(如是否有副作用、优先级信息)。
        bubbleProperties(workInProgress);
        return null;
      }

      updateHostContainer

      updateHostContainer 是 React 中处理宿主容器(如 DOM 根节点或 Portal 容器)更新的核心函数。当启用持久化渲染(supportsPersistence)且需要克隆容器时,该函数会创建新的子节点集合,标记更新,并最终触发容器的子节点替换。

      function updateHostContainer(current: null | Fiber, workInProgress: Fiber) {
        // supportsPersistence:是否启用持久化渲染(如 React 18+ 的并发模式)。
        if (supportsPersistence) {
      
          // oesRequireClone:判断是否需要克隆容器(如子节点结构变化、属性更新等)。
          if (doesRequireClone(current, workInProgress)) {
      
           // 创建新子节点集合
            const portalOrRoot: {
              containerInfo: Container,
              pendingChildren: ChildSet,
              
            } = workInProgress.stateNode;
            const container = portalOrRoot.containerInfo;
            // 创建用于存储子节点的临时集合。
            const newChildSet = createContainerChildSet();
            // If children might have changed, we have to add them all to the set.
            // appendAllChildrenToContainer将 workInProgress 的所有子节点添加到新集合。
            appendAllChildrenToContainer(
              newChildSet,
              workInProgress,
              /* needsVisibilityToggle */ false,
              /* isHidden */ false,
            );
            portalOrRoot.pendingChildren = newChildSet;
            // Schedule an update on the container to swap out the container.
            // 标记容器需要更新,触发后续的 DOM 操作。
            markUpdate(workInProgress);
            // 准备容器的子节点更新,可能包括:
              // 计算新旧子节点的差异。
              // 准备插入 / 删除 / 移动等 DOM 操作队列。
            finalizeContainerChildren(container, newChildSet);
          }
        }
      }

      工具函数之 doesRequireClone

      doesRequireClone 函数用于判断是否需要克隆宿主容器(如 DOM 节点)以应用更新。

      function doesRequireClone(current: null | Fiber, completedWork: Fiber) {
        const didBailout = current !== null && current.child === completedWork.child;
        // 若组件因 bailout 机制跳过渲染(如 React.memo 优化),直接返回 false(无需克隆)。
        if (didBailout) {
          return false;
        }
      
        // ChildDeletion 标志:表示子树中存在节点删除操作,需克隆容器以安全移除节点。
        if ((completedWork.flags & ChildDeletion) !== NoFlags) {
          return true;
        }
      
        // TODO: If we move the `doesRequireClone` call after `bubbleProperties`
        // then we only have to check the `completedWork.subtreeFlags`.
        let child = completedWork.child;
        while (child !== null) {
          // Cloned:节点需要被克隆。
          // Visibility:节点可见性变化(如通过 Suspense 控制)。
          // Placement:节点插入或移动。
          // ChildDeletion:子节点删除。
          // 持久化模式(enablePersistedModeClonedFlag 启用
          const checkedFlags = enablePersistedModeClonedFlag
            ? Cloned | Visibility | Placement | ChildDeletion
            // 传统模式:检查 MutationMask(包含 Placement、Update、Deletion 等基本变更)。
            : MutationMask;
      
          // child.flags:当前节点的变更标志。
          // child.subtreeFlags:子树中所有节点的累积变更标志。
          if (
            (child.flags & checkedFlags) !== NoFlags ||
            (child.subtreeFlags & checkedFlags) !== NoFlags
          ) {
            return true;
          }
          child = child.sibling;
        }
        return false;
      }

      工具函数之 createContainerChildSet

      createContainerChildSet 是 React 中用于创建子节点集合的工厂函数,主要服务于宿主容器(如 DOM 根节点或 Portal)的更新过程。

      createContainerChildSet(): Array<Instance | TextInstance> {
        return [];
      },

      工具函数之 appendAllChildrenToContainer

      appendAllChildrenToContainer 是 React 渲染流程中的核心函数,用于将 Fiber 树中的子节点递归转换为实际渲染节点(如 DOM 元素)并添加到容器中。

      function appendAllChildrenToContainer(
        containerChildSet: ChildSet, // 目标容器子节点集合
        workInProgress: Fiber, // 当前处理的 Fiber 节点
        needsVisibilityToggle: boolean, // 是否需要控制可见性
        isHidden: boolean,  // 当前是否隐藏
      ) {
        if (supportsPersistence) {
          // We only have the top Fiber that was created but we need recurse down its
          // children to find all the terminal nodes.
          let node = workInProgress.child;
          while (node !== null) {
            // 节点类型处理
            // 1、HostComponent:DOM 元素(如 <div>)。
            if (node.tag === HostComponent) {
              let instance = node.stateNode;
              if (needsVisibilityToggle && isHidden) {
                // This child is inside a timed out tree. Hide it.
                const props = node.memoizedProps;
                const type = node.type;
                instance = cloneHiddenInstance(instance, type, props);
              }
                
              // 将实例添加到子节点集合中
              appendChildToContainerChildSet(containerChildSet, instance);
      
              // 2、处理文本
            } else if (node.tag === HostText) {
              let instance = node.stateNode;
              if (needsVisibilityToggle && isHidden) {
                // This child is inside a timed out tree. Hide it.
                const text = node.memoizedProps;
                instance = cloneHiddenTextInstance(instance, text);
              }
              appendChildToContainerChildSet(containerChildSet, instance);
      
              // 3、处理HostPortal
            } else if (node.tag === HostPortal) {
              // Portal 节点不递归处理子节点(由 Portal 单独管理)
      
              // 4、处理不可见组件
            } else if (
              node.tag === OffscreenComponent &&
              node.memoizedState !== null
            ) {
              const child = node.child;
              if (child !== null) {
                child.return = node;
              }
              // If Offscreen is not in manual mode, detached tree is hidden from user space.
              const _needsVisibilityToggle = !isOffscreenManual(node);
              appendAllChildrenToContainer(
                containerChildSet,
                node,
                /* needsVisibilityToggle */ _needsVisibilityToggle,
                /* isHidden */ true,
              );
      
              // 递归到子节点
            } else if (node.child !== null) {
              
              node.child.return = node;
              node = node.child;
              continue;
            }
            
            node = (node: Fiber);
            if (node === workInProgress) {
              return;
            }
      
            // 回溯到父节点
            while (node.sibling === null) {
           
              if (node.return === null || node.return === workInProgress) {
                return;
              }
              node = node.return;
            }
        
            node.sibling.return = node.return;
            node = node.sibling;
          }
        }
      }

       工具函数之 appendChildToContainerChildSet

      appendChildToContainerChildSet 是 React 内部用于将子节点添加到容器子节点集合的辅助函数。

      appendChildToContainerChildSet(
         childSet: Array<Instance | TextInstance>,
         child: Instance | TextInstance,
       ): void {
          childSet.push(child);
      },

      工具函数之 appendAllChildrenToContainer 

      appendAllChildrenToContainer 是 React 渲染流程中的核心函数,用于将 Fiber 树中的子节点递归转换为实际渲染节点(如 DOM 元素)并添加到容器中。该函数处理多种节点类型(组件、文本、Portal 等),支持可见性控制,并在持久化渲染模式下优化节点添加逻辑。

      function appendAllChildrenToContainer(
        containerChildSet: ChildSet, // 目标容器子节点集合
        workInProgress: Fiber, // 当前处理的 Fiber 节点
        needsVisibilityToggle: boolean, // 是否需要控制可见性
        isHidden: boolean,  // 当前是否隐藏
      ) {
        if (supportsPersistence) {
          // We only have the top Fiber that was created but we need recurse down its
          // children to find all the terminal nodes.
          let node = workInProgress.child;
          while (node !== null) {
            // 节点类型处理
            // 1、HostComponent:DOM 元素(如 <div>)。
            if (node.tag === HostComponent) {
              let instance = node.stateNode;
              if (needsVisibilityToggle && isHidden) {
                // This child is inside a timed out tree. Hide it.
                const props = node.memoizedProps;
                const type = node.type;
                instance = cloneHiddenInstance(instance, type, props);
              }
              appendChildToContainerChildSet(containerChildSet, instance);
      
              // 2、处理文本
            } else if (node.tag === HostText) {
              let instance = node.stateNode;
              if (needsVisibilityToggle && isHidden) {
                // This child is inside a timed out tree. Hide it.
                const text = node.memoizedProps;
                instance = cloneHiddenTextInstance(instance, text);
              }
              appendChildToContainerChildSet(containerChildSet, instance);
      
              // 3、处理HostPortal
            } else if (node.tag === HostPortal) {
              // Portal 节点不递归处理子节点(由 Portal 单独管理)
      
              // 4、处理不可见组件
            } else if (
              node.tag === OffscreenComponent &&
              node.memoizedState !== null
            ) {
              const child = node.child;
              if (child !== null) {
                child.return = node;
              }
              // If Offscreen is not in manual mode, detached tree is hidden from user space.
              const _needsVisibilityToggle = !isOffscreenManual(node);
              appendAllChildrenToContainer(
                containerChildSet,
                node,
                /* needsVisibilityToggle */ _needsVisibilityToggle,
                /* isHidden */ true,
              );
      
              // 递归到子节点
            } else if (node.child !== null) {
              
              node.child.return = node;
              node = node.child;
              continue;
            }
            
            node = (node: Fiber);
            if (node === workInProgress) {
              return;
            }
      
            // 回溯或处理兄弟节点
            while (node.sibling === null) {
           
              if (node.return === null || node.return === workInProgress) {
                return;
              }
              node = node.return;
            }
        
            node.sibling.return = node.return;
            node = node.sibling;
          }
        }
      }

      工具函数之 finalizeContainerChildren 

       finalizeContainerChildren 函数用于将新生成的子节点集合(newChildren)关联到容器(container)。

      finalizeContainerChildren(
        container: Container,
        newChildren: Array<Instance | TextInstance>,
      ): void {
        container.pendingChildren = newChildren;
      
        if (
          newChildren.length === 1 &&
          newChildren[0].text === 'Error when completing root'
        ) {
          // Trigger an error for testing purposes
          throw Error('Error when completing root');
        }
      },

      <Tag>HostHoistable

      处理 React 中 HostHoistable 类型的 Fiber 节点,主要用于优化和管理可提升的宿主环境组件(如 DOM 元素)。这类组件可能包含异步资源(如图片、脚本),需要特殊的预加载和挂起逻辑。代码根据组件是否包含资源(Resource)以及是否处于更新阶段,选择不同的处理路径,确保资源预加载和组件渲染的高效性与正确性。

      执行过程(启用资源管理):

      一、初始化过程

      1. 标记更新。
      2. 处理资源类型。
      3. 处理普通实例类型。

      二、更新过程

      1. 资源存在
        1. 资源存在变化。标记更新。
        2. 资源未发生变化。清除挂起标记。
      2. 普通实例
        1. 支持突变模式。当props发生变化化,标记更新。
        2. 不支持突变模式,调用updateHostComponent函数。
      case HostHoistable: {
        if (supportsResources) {
       
          const type = workInProgress.type;
          const nextResource: Resource | null = workInProgress.memoizedState;
      
          // 初始化
          if (current === null) {
            
            // 标记更新
            markUpdate(workInProgress);
            
            if (nextResource !== null) {
            // 处理资源类型
              
              bubbleProperties(workInProgress);
              preloadResourceAndSuspendIfNeeded(
                workInProgress,
                nextResource,
                type,
                newProps,
                renderLanes,
              );
              return null;
              
            } else {
              // 处理普通实例
              bubbleProperties(workInProgress);
              preloadInstanceAndSuspendIfNeeded(
                workInProgress,
                type,
                newProps,
                renderLanes,
              );
              return null;
            }
          } else {
            // This is an update.
            if (nextResource) {
              // This is a Resource
              if (nextResource !== current.memoizedState) {
                //  资源变化,触发更新和预加载
                // we have a new Resource. we need to update
                markUpdate(workInProgress);
                // This must come at the very end of the complete phase.
                bubbleProperties(workInProgress);
              
                preloadResourceAndSuspendIfNeeded(
                  workInProgress,
                  nextResource,
                  type,
                  newProps,
                  renderLanes,
                );
                return null;
              } else {
                // This must come at the very end of the complete phase.
                bubbleProperties(workInProgress);
                 // 资源未变化,清除挂起标志
                workInProgress.flags &= ~MaySuspendCommit;
                return null;
              }
            } else {
              // 更新阶段且为普通实例
              // This is an Instance
              // We may have props to update on the Hoistable instance.
              if (supportsMutation) {
                const oldProps = current.memoizedProps;
                if (oldProps !== newProps) {
                  markUpdate(workInProgress);
                }
              } else {
                // We use the updateHostComponent path becuase it produces
                // the update queue we need for Hoistables.
                updateHostComponent(
                  current,
                  workInProgress,
                  type,
                  newProps,
                  renderLanes,
                );
              }
              // This must come at the very end of the complete phase.
              bubbleProperties(workInProgress);
              preloadInstanceAndSuspendIfNeeded(
                workInProgress,
                type,
                newProps,
                renderLanes,
              );
              return null;
            }
          }
        }
        // Fall through
      }

       工具函数之 preloadResourceAndSuspendIfNeeded

      preloadResourceAndSuspendIfNeeded 是 React 内部用于处理异步资源预加载的核心函数,主要针对 HostHoistable 类型的 Fiber 节点(如媒体元素、脚本等)。其核心逻辑是:尝试预加载资源,如果资源未就绪则挂起当前渲染,避免阻塞主线程。该函数实现了 React 的并发渲染特性,确保在资源加载期间页面保持响应,并根据配置决定是显示旧内容还是立即挂起。

      function preloadResourceAndSuspendIfNeeded(
        workInProgress: Fiber,
        resource: Resource,
        type: Type,
        props: Props,
        renderLanes: Lanes,
      ) {
        // This is a fork of preloadInstanceAndSuspendIfNeeded, but for resources.
        // mayResourceSuspendCommit 判断资源是否可能导致挂起。
        if (!mayResourceSuspendCommit(resource)) {
          // 若不可能挂起(如资源已缓存),清除挂起标志并直接返回。
          workInProgress.flags &= ~MaySuspendCommit;
          return;
        }
      
        // 标记可能挂起状态
        workInProgress.flags |= MaySuspendCommit;
      
        const isReady = preloadResource(resource);
        
        // 资源未就绪
        if (!isReady) {
          if (shouldRemainOnPreviousScreen()) {
            // 标记 ShouldSuspendCommit 标志,等待资源就绪后再提交更新。
            workInProgress.flags |= ShouldSuspendCommit;
          } else {
            // 资源已就绪
            // 立即调用 suspendCommit() 挂起当前渲染,触发 Suspense 边界的 fallback。
            suspendCommit();
          }
        }
      }

      <Tag>HostSingleton

      处理 React 中 HostSingleton 类型的 Fiber 节点,用于表示必须在整个应用中唯一存在的宿主环境组件。

      case HostSingleton: {
        // 支持单例
        if (supportsSingletons) {
          // 弹出当前 Fiber 的宿主环境上下文。
          popHostContext(workInProgress);
          // 获取根应用节点
          const rootContainerInstance = getRootHostContainer();
          const type = workInProgress.type;
          // 更新
          if (current !== null && workInProgress.stateNode != null) {
            // 突变模式
            if (supportsMutation) {
              const oldProps = current.memoizedProps;
              if (oldProps !== newProps) {
                // 标记更新
                markUpdate(workInProgress);
              }
            } else {
              
              updateHostComponent(
                current,
                workInProgress,
                type,
                newProps,
                renderLanes,
              );
            }
          } else {
            // 初始化
            if (!newProps) {
              if (workInProgress.stateNode === null) {
                throw new Error(
                  'We must have new props for new mounts. This error is likely ' +
                    'caused by a bug in React. Please file an issue.',
                );
              }
      
              // This can happen when we abort work.
              bubbleProperties(workInProgress);
              return null;
            }
      
            // 获取上下文
            const currentHostContext = getHostContext();
            const wasHydrated = popHydrationState(workInProgress);
            let instance: Instance;
            // 服务端渲染
            if (wasHydrated) {
              // prepareToHydrateHostInstance(workInProgress, currentHostContext);
              // // 复用现有 DOM 节点,避免重新创建。
              // instance = workInProgress.stateNode;
            } else {
              // 客户端渲染
              // 通过 resolveSingletonInstance 创建单例实例,并标记更新。
              instance = resolveSingletonInstance(
                type,
                newProps,
                rootContainerInstance,
                currentHostContext,
                true,
              );
              workInProgress.stateNode = instance;
              markUpdate(workInProgress);
            }
          }
          // 属性冒泡,将子节点的状态(如副作用标志)向上传播到父节点。
          bubbleProperties(workInProgress);
          // 结束当前 Fiber 的处理
          return null;
        }
        // Fall through
      }
      

      工具函数之 resolveSingletonInstance

      resolveSingletonInstance 是 React 内部用于获取或创建单例 DOM 元素的核心函数,专门处理那些在文档中必须唯一存在且不能被 React 直接创建的特殊元素(如 <html><head><body>)。

      function resolveSingletonInstance(
        type: string,
        props: Props,
        rootContainerInstance: Container,
        hostContext: HostContext,
        validateDOMNestingDev: boolean,
      ): Instance {
        // 获取document对象
        const ownerDocument = getOwnerDocumentFromRootContainer(
          rootContainerInstance,
        );
        switch (type) {
          case 'html': {
            const documentElement = ownerDocument.documentElement;
            if (!documentElement) {
              throw new Error(
                'React expected an <html> element (document.documentElement) to exist in the Document but one was' +
                  ' not found. React never removes the documentElement for any Document it renders into so' +
                  ' the cause is likely in some other script running on this page.',
              );
            }
            return documentElement;
          }
          case 'head': {
            const head = ownerDocument.head;
            if (!head) {
              throw new Error(
                'React expected a <head> element (document.head) to exist in the Document but one was' +
                  ' not found. React never removes the head for any Document it renders into so' +
                  ' the cause is likely in some other script running on this page.',
              );
            }
            return head;
          }
          case 'body': {
            const body = ownerDocument.body;
            if (!body) {
              throw new Error(
                'React expected a <body> element (document.body) to exist in the Document but one was' +
                  ' not found. React never removes the body for any Document it renders into so' +
                  ' the cause is likely in some other script running on this page.',
              );
            }
            return body;
          }
          default: {
            throw new Error(
              'resolveSingletonInstance was called with an element type that is not supported. This is a bug in React.',
            );
          }
        }
      }

      <Tag>HostComponent

      React 处理 HostComponent(如 DOM 元素)的核心逻辑,主要负责创建或更新实际的 DOM 节点。它根据节点是否已存在、是否来自服务端渲染水合等情况,选择不同的处理路径,并处理特殊属性(如自动聚焦)和预加载逻辑。

      case HostComponent: {
        // 退出当前宿主环境上下文栈
        popHostContext(workInProgress);
        // 获取组件类型,类如div,span
        const type = workInProgress.type;
        // 更新已存在的 DOM 节点
        if (current !== null && workInProgress.stateNode != null) {
          // 调用 updateHostComponent 更新 DOM 属性(如 className、style)。处理事件监听器的添加 / 移除。
          updateHostComponent(
            current,
            workInProgress,
            type,
            newProps,
            renderLanes,
          );
      
          // 首次渲染或新增
        } else {
          if (!newProps) {
            // 错误处理:新节点必须有 props
            if (workInProgress.stateNode === null) {
              throw new Error(
                'We must have new props for new mounts. This error is likely ' +
                  'caused by a bug in React. Please file an issue.',
              );
            }
      
            // This can happen when we abort work.
            bubbleProperties(workInProgress);
            return null;
          }
      
          const currentHostContext = getHostContext();
       
          const wasHydrated = popHydrationState(workInProgress);
          if (wasHydrated) {
            // prepareToHydrateHostInstance(workInProgress, currentHostContext);
          } else {
            // 纯客户端渲染逻辑
            
            const rootContainerInstance = getRootHostContainer();
            // 调用 createInstance 创建新 DOM 元素。
            const instance = createInstance(
              type,
              newProps,
              rootContainerInstance,
              currentHostContext,
              workInProgress,
            );
          
            markCloned(workInProgress);
            // 通过 appendAllChildren 添加子元素。
            appendAllChildren(instance, workInProgress, false, false);
            workInProgress.stateNode = instance;
      
            if (
              finalizeInitialChildren(
                instance,
                type,
                newProps,
                currentHostContext,
              )
            ) {
              markUpdate(workInProgress);
            }
          }
        }
         // 属性冒泡
        bubbleProperties(workInProgress);
      
        // 预加载
        preloadInstanceAndSuspendIfNeeded(
          workInProgress,
          workInProgress.type,
          workInProgress.pendingProps,
          renderLanes,
        );
        return null;
      }

      updateHostComponent

      updateHostComponent 是 React 处理宿主组件(如 DOM 元素)更新的核心函数,根据渲染模式(突变模式或持久化模式)选择不同的更新策略。在突变模式下,直接标记节点更新;在持久化模式下,通过克隆实例实现无突变更新,并支持状态保留。

      function updateHostComponent(
        current: Fiber,
        workInProgress: Fiber,
        type: Type,
        newProps: Props,
        renderLanes: Lanes,
      ) {
        // 突变模式下的处理(supportsMutation)
        if (supportsMutation) {
        
          const oldProps = current.memoizedProps;
          // 比较新旧属性引用是否相同(浅比较)。
          if (oldProps === newProps) {
            return;
          }
          // 标记节点为更新状态
          markUpdate(workInProgress);
      
          // 持久化模式下的处理(supportsPersistence)
        } else if (supportsPersistence) {
          const currentInstance = current.stateNode;
          const oldProps = current.memoizedProps;
          
          // 通过 doesRequireClone 检查节点是否需要克隆。
          const requiresClone = doesRequireClone(current, workInProgress);
          if (!requiresClone && oldProps === newProps) {
            workInProgress.stateNode = currentInstance;
            return;
          }
          const currentHostContext = getHostContext();
      
          let newChildSet = null;
          if (requiresClone && passChildrenWhenCloningPersistedNodes) {
            markCloned(workInProgress);
            newChildSet = createContainerChildSet();
            // If children might have changed, we have to add them all to the set.
            appendAllChildrenToContainer(
              newChildSet,
              workInProgress,
              /* needsVisibilityToggle */ false,
              /* isHidden */ false,
            );
          }
      
          // 调用 cloneInstance 创建新实例,保留旧状态。
          const newInstance = cloneInstance(
            currentInstance,
            type,
            oldProps,
            newProps,
            !requiresClone,
            newChildSet,
          );
          if (newInstance === currentInstance) {
            // 无需变更,复用
            workInProgress.stateNode = currentInstance;
            return;
          } else {
            // 标记为克隆节点
            markCloned(workInProgress);
          }
      
          // 处理特殊属性(如自动聚焦)
          if (
            finalizeInitialChildren(newInstance, type, newProps, currentHostContext)
          ) {
            markUpdate(workInProgress);
          }
      
          // 更新子节点
          workInProgress.stateNode = newInstance;
          if (!requiresClone) {
            if (!enablePersistedModeClonedFlag) {
              markUpdate(workInProgress);
            }
          } else if (!passChildrenWhenCloningPersistedNodes) {
            // If children have changed, we have to add them all to the set.
            appendAllChildren(
              newInstance,
              workInProgress,
              /* needsVisibilityToggle */ false,
              /* isHidden */ false,
            );
          }
        }
      }

      createInstance

      createInstance 方法,用于创建虚拟 DOM 元素的实例。该方法生成一个包含元素类型、属性和子节点信息的对象,并处理特殊属性(如 hiddensrc)和文本内容。通过不可枚举属性存储内部状态,确保这些信息不会暴露给外部代码。

      const sharedHostConfig = {
        createInstance(
          type: string,//元素的类型
          props: Props,// 传递给元素的属性对象。
          rootContainerInstance: Container,// 根容器实例,即渲染的目标容器。
          hostContext: HostContext,// 当前渲染的宿主环境上下文。
          internalInstanceHandle: Object,// 指向 React 内部 Fiber 节点的引用。
        ): Instance {
          if (type === 'errorInCompletePhase') {
            throw new Error('Error in host config.');
          }
          // 实例结构
          const inst = {
            id: instanceCounter++,
            type: type,
            children: [],
            parent: -1,
            // shouldSetTextContent:判断是否应将子节点作为文本内容处理。
            text: shouldSetTextContent(type, props)
              ? // eslint-disable-next-line react-internal/safe-string-coercion
              // computeText:处理文本内容(可能包括转义、格式化等)。
                computeText((props.children: any) + '', hostContext)
              : null,
            prop: props.prop,
            hidden: !!props.hidden,
            context: hostContext,
          };
      
          // 为 suspensey-thing 类型的元素添加 src 属性。
          if (type === 'suspensey-thing' && typeof props.src === 'string') {
            inst.src = props.src;
          }
      
          // Hide from unit tests
          // 将 id、parent、text 等属性设为不可枚举。
          // 防止这些内部状态在 for...in 循环或 JSON.stringify 中暴露。
          Object.defineProperty(inst, 'id', {value: inst.id, enumerable: false});
          Object.defineProperty(inst, 'parent', {
            value: inst.parent,
            enumerable: false,
          });
          Object.defineProperty(inst, 'text', {
            value: inst.text,
            enumerable: false,
          });
          Object.defineProperty(inst, 'context', {
            value: inst.context,
            enumerable: false,
          });
          Object.defineProperty(inst, 'fiber', {
            value: internalInstanceHandle,
            enumerable: false,
          });
          return inst;
        },
      }

      关键属性

      • id:唯一标识,用于内部跟踪。
      • type:元素类型(如 divspan)。
      • children:子节点数组。
      • text:文本内容(如果适用)。
      • hidden:是否隐藏(基于 props.hidden)。
      const inst = {
        id: instanceCounter++,
        type: type,
        children: [],
        parent: -1,
        // shouldSetTextContent:判断是否应将子节点作为文本内容处理。
        text: shouldSetTextContent(type, props)
          ? // eslint-disable-next-line react-internal/safe-string-coercion
          // computeText:处理文本内容(可能包括转义、格式化等)。
            computeText((props.children: any) + '', hostContext)
          : null,
        prop: props.prop,
        hidden: !!props.hidden,
        context: hostContext,
      };

      工具函数之 shouldSetTextContent 

      function shouldSetTextContent(type: string, props: Props): boolean {
        if (type === 'errorInBeginPhase') {
          throw new Error('Error in host config.');
        }
        return (
          typeof props.children === 'string' ||
          typeof props.children === 'number' ||
          typeof props.children === 'bigint'
        );
      }
      

      工具函数之 computeText 

      computeText 是一个文本处理函数,用于根据宿主环境上下文决定是否转换文本大小写。当上下文为 UPPERCASE_CONTEXT 时,将文本转换为大写;否则保持原文。 

      
      function computeText(rawText, hostContext) {
        return hostContext === UPPERCASE_CONTEXT ? rawText.toUpperCase() : rawText;
      }
      
      const UPPERCASE_CONTEXT = {};

      工具函数之 finalizeInitialChildren

      finalizeInitialChildren 函数主要用于完成元素初始化后的最终处理。

      它执行以下核心操作:

      1. 通过 setInitialProperties 设置元素的初始属性(如 classNamestyle)。
      2. 根据元素类型判断是否需要在渲染后执行副作用操作(如自动聚焦、图片预加载)。
      3. 返回布尔值,指示该元素是否需要在提交阶段(commit phase)执行额外的副作用。
      function finalizeInitialChildren(
        domElement: Instance,
        type: string,
        props: Props,
        hostContext: HostContext,
      ): boolean {
        setInitialProperties(domElement, type, props);
        switch (type) {
          case 'button':
          case 'input':
          case 'select':
          case 'textarea':
            return !!props.autoFocus;
          case 'img':
            return true;
          default:
            return false;
        }
      }

      工具函数之 appendAllChildren

      appendAllChildren 函数用于将 Fiber 树中的所有子节点挂载到父 DOM 节点上。它通过深度优先遍历 Fiber 树,将真实 DOM 节点(如 HostComponentHostText)按正确顺序添加到父容器中。该函数针对不同渲染模式(突变模式和持久化模式)进行了优化。

      处理过程:

      一、突变模式

      1. 处理当前子节点
        1. 如果节点tag是 HostComponent 或者 HostText,直接将 HostComponent(DOM 元素)或 HostText(文本节点)直接添加到父容器。
        2. 如果节点tag是 HostPortal,不做处理。(Portal 节点不直接添加到父容器,而是通过 Portal 机制挂载到其他容器)
        3. 如果当前子节点有子节点,则进入递归处理(则为下面的第2点)
      2. 递归处理子节点
      3. 如果当前子节点正是正在处理的fiber(workInProgress),则退出当前循环。
      4. 回溯或处理兄弟节点

      二、持久化模式

      1. 处理当前子节点
        1. 如果节点tag是 HostComponent ,当需要隐藏时克隆节点并应用隐藏样式直接,然后将克隆实例 instance 直接添加到父容器。
        2. 如果节点tag是 HostText ,当需要隐藏时克隆节点并应用隐藏样式直接,然后将克隆实例 instance 直接添加到父容器。
        3. 如果节点tag是 HostPortal,不做处理。(Portal 节点不直接添加到父容器,而是通过 Portal 机制挂载到其他容器)
        4. 如果节点tag是 OffscreenComponent,处理其子节点与子节点的引用关系,调用appendAllChildren递归处理子节点。
        5. 如果当前子节点有子节点,则进入递归处理(则为下面的第2点)
      2. 递归处理子节点
      3. 如果当前子节点正是正在处理的fiber(workInProgress),则退出当前循环。
      4. 回溯或处理兄弟节点
      function appendAllChildren(
        parent: Instance,// 指定子节点要挂载到的父容器。
        workInProgress: Fiber,// 当前正在处理的 Fiber 节点,作为遍历起点。
        needsVisibilityToggle: boolean, //指示是否需要根据 isHidden 参数调整子节点的可见性。
        isHidden: boolean, // 当 needsVisibilityToggle 为 true 时,决定子节点是否应被隐藏。
      ) {
      
        // 突变模式处理(supportsMutation)
        if (supportsMutation) {
        
          let node = workInProgress.child;
          while (node !== null) {
             // 处理当前节点
            if (node.tag === HostComponent || node.tag === HostText) {
              // 将 HostComponent(DOM 元素)或 HostText(文本节点)直接添加到父容器。
              appendInitialChild(parent, node.stateNode);
              
            } else if (
              node.tag === HostPortal ||
              (supportsSingletons ? node.tag === HostSingleton : false)
            ) {
               // Portal 节点不直接添加到父容器,而是通过 Portal 机制挂载到其他容器
      
              // 递归处理子节点
            } else if (node.child !== null) {
              node.child.return = node;
              node = node.child;
              continue;
            }
            
            if (node === workInProgress) {
              return;
            }
            
            //  回溯或处理兄弟节点
            while (node.sibling === null) {
              if (node.return === null || node.return === workInProgress) {
                return;
              }
              node = node.return;
            }
            
            node.sibling.return = node.return;
            node = node.sibling;
          }
      
          // 持久化模式处理(supportsPersistence)
        } else if (supportsPersistence) {
          // We only have the top Fiber that was created but we need recurse down its
          // children to find all the terminal nodes.
          let node = workInProgress.child;
          while (node !== null) {
            
            if (node.tag === HostComponent) {
              let instance = node.stateNode;
              if (needsVisibilityToggle && isHidden) {
                // 当节点位于超时的 Suspense 边界内时,克隆节点并应用隐藏样式。
                const props = node.memoizedProps;
                const type = node.type;
                instance = cloneHiddenInstance(instance, type, props);
              }
              //将 instance 直接添加到父容器。
              appendInitialChild(parent, instance);
              
            } else if (node.tag === HostText) {
              let instance = node.stateNode;
              
              if (needsVisibilityToggle && isHidden) {
                const text = node.memoizedProps;
                instance = cloneHiddenTextInstance(instance, text);
              }
              
              appendInitialChild(parent, instance);
      
              
            } else if (node.tag === HostPortal) {
               // Portal 节点不直接添加到父容器,而是通过 Portal 机制挂载到其他容器
            
            } else if (
              node.tag === OffscreenComponent &&
              node.memoizedState !== null
            ) {
         
              const child = node.child;
              if (child !== null) {
                child.return = node;
              }
              appendAllChildren(
                parent,
                node,
                /* needsVisibilityToggle */ true,
                /* isHidden */ true,
              );
      
              // 递归处理子节点
            } else if (node.child !== null) {
              node.child.return = node;
              node = node.child;
              continue;
            }
            if (node === workInProgress) {
              return;
            }
      
            // 回溯或处理兄弟节点
            while (node.sibling === null) {
             
              if (node.return === null || node.return === workInProgress) {
                return;
              }
              node = node.return;
            }
           
            node.sibling.return = node.return;
            node = node.sibling;
          }
        }
      }
      

       工具函数之 appendInitialChild

      function appendInitialChild(
        parentInstance: Instance,
        child: Instance | TextInstance,
      ): void {
        parentInstance.appendChild(child);
      }

       工具函数之 cloneHiddenInstance

      cloneHiddenInstance 方法,用于创建一个隐藏版本的 DOM 元素实例。该方法在需要临时隐藏元素但保留其结构和状态时使用。

      const hostConfig = useMutation ? {       
        cloneHiddenInstance(
            instance: Instance,
            type: string,
            props: Props,
          ): Instance {
            const clone = cloneInstance(instance, type, props, props, true, null);
            clone.hidden = true;
            return clone;
          },
      }

      工具函数之 cloneInstance

      cloneInstance 是 React 内部用于克隆 DOM 元素实例的函数,主要用于在不改变原始实例的情况下创建一个具有新属性的副本

      function cloneInstance(
        instance: Instance,
        type: string,
        oldProps: Props,
        newProps: Props,
        keepChildren: boolean,
        children: ?$ReadOnlyArray<Instance>,
      ): Instance {
      
        // 实例克隆核心逻辑
        const clone = {
          id: instance.id,
          type: type,
          parent: instance.parent,
          children: keepChildren ? instance.children : children ?? [],
          text: shouldSetTextContent(type, newProps)
            ? computeText((newProps.children: any) + '', instance.context)
            : null,
          prop: newProps.prop,
          hidden: !!newProps.hidden,
          context: instance.context,
        };
      
        // 当元素类型为 suspensey-thing 且新属性包含 src 时,添加 src 属性到克隆实例。
        if (type === 'suspensey-thing' && typeof newProps.src === 'string') {
          clone.src = newProps.src;
        }
      
        // 不可枚举属性设置
        // 将关键内部属性设为不可枚举,避免在遍历或序列化时暴露。
      // 保持与原始实例的行为一致性。
        Object.defineProperty(clone, 'id', {
          value: clone.id,
          enumerable: false,
        });
        Object.defineProperty(clone, 'parent', {
          value: clone.parent,
          enumerable: false,
        });
        Object.defineProperty(clone, 'text', {
          value: clone.text,
          enumerable: false,
        });
        Object.defineProperty(clone, 'context', {
          value: clone.context,
          enumerable: false,
        });
        hostCloneCounter++;
        return clone;
      }

      工具函数之 cloneHiddenTextInstance

      cloneHiddenTextInstance 方法,专门用于克隆文本节点并将其标记为隐藏状态。用在处理需要临时隐藏文本内容但保留其结构和上下文的场景时。

      const hostConfig = useMutation ?  {
        cloneHiddenTextInstance(
          instance: TextInstance,
          text: string,
        ): TextInstance {
          const clone = {
            text: instance.text,
            id: instance.id,
            parent: instance.parent,
            hidden: true,
            context: instance.context,
          };
          // Hide from unit tests
          Object.defineProperty(clone, 'id', {
            value: clone.id,
            enumerable: false,
          });
          Object.defineProperty(clone, 'parent', {
            value: clone.parent,
            enumerable: false,
          });
          Object.defineProperty(clone, 'context', {
            value: clone.context,
            enumerable: false,
          });
          return clone;
        },
      }

      preloadInstanceAndSuspendIfNeeded

      preloadInstanceAndSuspendIfNeeded 函数负责在元素实例化阶段预加载资源并决定是否需要挂起渲染。

      它通过以下步骤实现精细控制:

      1. 判断元素是否可能触发提交阶段的挂起(如包含异步资源)。
      2. 尝试预加载资源并检查就绪状态。
      3. 根据资源状态和屏幕过渡策略,决定是继续渲染、挂起并保持当前屏幕,还是立即挂起并显示 fallback。
      function preloadInstanceAndSuspendIfNeeded(
        workInProgress: Fiber,
        type: Type,
        props: Props,
        renderLanes: Lanes,
      ) {
        if (!maySuspendCommit(type, props)) {
        // MaySuspendCommit:表示该 Fiber 节点可能会暂停提交操作。在 React 的并发模式下,渲染过程可能会被暂停和恢复
          workInProgress.flags &= ~MaySuspendCommit;
          return;
        }
      
        workInProgress.flags |= MaySuspendCommit;
      
        const isReady = preloadInstance(type, props);
        
        if (!isReady) {
          if (shouldRemainOnPreviousScreen()) {
            workInProgress.flags |= ShouldSuspendCommit;
          } else {
            suspendCommit();
          }
        }
      }

      工具函数之 preloadResource

      preloadResource 是一个用于资源预加载控制的函数,主要决定特定资源是否需要暂停渲染(suspend)。核心逻辑是:当资源类型为样式表(stylesheet)且处于未加载状态时,函数返回 false 触发渲染暂停;否则返回 true 继续渲染。

      function preloadResource(resource: Resource): boolean {
        if (
          resource.type === 'stylesheet' &&
          (resource.state.loading & Settled) === NotLoaded
        ) {
          // Return false to indicate this resource should suspend
          return false;
        }
      
        // Return true to indicate this resource should not suspend
        return true;
      }

      <Tag>HostText

      React 处理 HostText 类型节点(即文本节点)的核心逻辑,主要负责更新或创建文本节点实例。它会根据节点是否已存在、是否来自服务端渲染水合等情况,选择不同的处理路径,确保文本内容正确地反映到 DOM 中。

      case HostText: {
      
        // 获取新旧文本内容
        const newText = newProps;
      
        // 更新
        if (current && workInProgress.stateNode != null) {
          const oldText = current.memoizedProps;
          // 调用 updateHostText 更新现有文本节点内容(如 setTextContent)。
          updateHostText(current, workInProgress, oldText, newText);
      
          // 首次渲染
        } else {
          // 处理新创建的文本节点
          
          if (typeof newText !== 'string') {
            if (workInProgress.stateNode === null) {
              throw new Error(
                'We must have new props for new mounts. This error is likely ' +
                  'caused by a bug in React. Please file an issue.',
              );
            }
            // This can happen when we abort work.
          }
          // 获取当前渲染的根容器(如 DOM 中的 root 节点)。
          const rootContainerInstance = getRootHostContainer();
          // 获取宿主环境上下文
          const currentHostContext = getHostContext();
          // 处理服务端渲染水合状态
          const wasHydrated = popHydrationState(workInProgress);
      
          // 检查当前节点是否来自服务端渲染的 HTML。
          if (wasHydrated) {
            // prepareToHydrateHostTextInstance(workInProgress);
          } else {
            // 添加Cloned标记
            markCloned(workInProgress);
            // 创建文本实例
            workInProgress.stateNode = createTextInstance(
              newText,
              rootContainerInstance,
              currentHostContext,
              workInProgress,
            );
          }
        }
        
        // 冒泡属性与完成处理
        bubbleProperties(workInProgress);
        return null;
      }

      updateHostText

      updateHostText 是 React 处理文本节点更新的核心函数,根据渲染模式(突变模式或持久化模式)选择不同的更新策略。当文本内容发生变化时,突变模式直接标记更新,而持久化模式则创建新的文本实例并标记克隆。这一机制确保了在不同渲染模式下文本更新的高效性和正确性。

      function updateHostText(
        current: Fiber,
        workInProgress: Fiber,
        oldText: string,
        newText: string,
      ) {
        // 突变模式下的处理(supportsMutation)
        if (supportsMutation) {
          // If the text differs, mark it as an update. All the work in done in commitWork.
          // 当新旧文本内容不一致时,标记节点为 Update。
          if (oldText !== newText) {
            markUpdate(workInProgress);
          }
      
          // 持久化模式下的处理(supportsPersistence)
        } else if (supportsPersistence) {
          if (oldText !== newText) {
            // If the text content differs, we'll create a new text instance for it.
            const rootContainerInstance = getRootHostContainer();
            const currentHostContext = getHostContext();
            markCloned(workInProgress);
            // 创建新的文本实例
            workInProgress.stateNode = createTextInstance(
              newText,
              rootContainerInstance,
              currentHostContext,
              workInProgress,
            );
            
             // 确保父节点知道子节点已变更
            if (!enablePersistedModeClonedFlag) {
              // We'll have to mark it as having an effect, even though we won't use the effect for anything.
              // This lets the parents know that at least one of their children has changed.
              markUpdate(workInProgress);
            }
          } else {
             // 文本未变化,复用现有实例
            workInProgress.stateNode = current.stateNode;
          }
        }
      }

      工具函数之 markUpdate

      function markUpdate(workInProgress: Fiber) {
        workInProgress.flags |= Update;
      }

      工具函数之 markCloned

      function markCloned(workInProgress: Fiber) {
        if (supportsPersistence && enablePersistedModeClonedFlag) {
          // 添加 Cloned 标志(flags |= Cloned)。
          workInProgress.flags |= Cloned;
        }
      }

      工具函数之 getRootHostContainer

      getRootHostContainer 是 React 渲染系统中的基础函数,用于获取当前渲染上下文的根宿主容器。在浏览器环境中,这通常对应于 ReactDOM.render 或 ReactDOM.createRoot 指定的 DOM 节点(如 <div id="root"></div>)。

      function getRootHostContainer(): Container {
        const rootInstance = requiredContext(rootInstanceStackCursor.current);
        return rootInstance;
      }
      const rootInstanceStackCursor: StackCursor<Container | null> = createCursor(null);
      function createCursor<T>(defaultValue: T): StackCursor<T> {
        return {
          current: defaultValue,
        };
      }
      function requiredContext<Value>(c: Value | null): Value {
        return (c: any);
      }

       工具函数之 getHostContext

      getHostContext() 是 React 渲染系统中的核心函数,用于获取当前宿主环境的上下文信息。这些信息包括命名空间(如 HTML/SVG)、样式作用域、容器配置等,是正确创建和渲染 DOM 元素的关键依据。通过维护一个上下文栈,React 能够在嵌套渲染(如 SVG 内部元素)时动态切换环境配置,确保元素正确渲染。

      function getHostContext(): HostContext {
        const context = requiredContext(contextStackCursor.current);
        return context;
      }
      const contextStackCursor: StackCursor<Object> =
        createCursor(emptyContextObject);
      
      const emptyContextObject: {} = {};

      createTextInstance

       createTextInstance 是 React 渲染系统中用于创建文本节点的核心函数。它通过宿主环境(如浏览器 DOM)提供的 API 创建实际的文本节点,并建立该节点与 React 内部 Fiber 节点的映射关系。这一过程是将虚拟 DOM 转换为真实 DOM 的关键步骤

      function createTextInstance(
        text: string,
        rootContainerInstance: Container,
        hostContext: HostContext,
        internalInstanceHandle: Object,
      ): TextInstance {
        // 创建新文本节点,调用 document.createTextNode(text) 创建实际的文本节点。
        const textNode: TextInstance = getOwnerDocumentFromRootContainer(
          rootContainerInstance,
        ).createTextNode(text);
        
         // 建立 Fiber 节点与 DOM 节点的映射
        precacheFiberNode(internalInstanceHandle, textNode);
        
        return textNode;
      }

       工具函数之 getOwnerDocumentFromRootContainer

      获取根容器所属的 document 对象。

      function getOwnerDocumentFromRootContainer(
        rootContainerElement: Element | Document | DocumentFragment,
      ): Document {
        return rootContainerElement.nodeType === DOCUMENT_NODE
          ? (rootContainerElement: any)
          : rootContainerElement.ownerDocument;
      }

      工具函数之 precacheFiberNode

      建立 Fiber 节点与 DOM 节点的映射 

      function precacheFiberNode(
        hostInst: Fiber,
        node: Instance | TextInstance | SuspenseInstance | ReactScopeInstance,
      ): void {
        (node: any)[internalInstanceKey] = hostInst;
      }
      const randomKey = Math.random().toString(36).slice(2);
      const internalInstanceKey = '__reactFiber$' + randomKey;

      <Tag>HostPortal

      处理 React 中 HostPortal 类型的 Fiber 节点,用于管理通过 ReactDOM.createPortal 创建的 Portal 组件。Portal 允许将子组件渲染到 DOM 树的不同位置(如独立的模态框、悬浮层),但保持与父组件的上下文关系。

      执行过程:

      1. 弹出 Portal 容器的上下文
      2. 更新 Portal 容器的状态
      3. 准备 Portal 挂载(首次渲染时)
      4. 冒泡属性以传播副作用和状态
      case HostPortal:
      // 从上下文栈中弹出当前 Portal 的容器信息。
        popHostContainer(workInProgress);
      
      // 比较新旧 Portal 容器的属性差异。标记需要执行的副作用(如属性更新、事件绑定)。
        updateHostContainer(current, workInProgress);
      
      // 首次挂载处理
        if (current === null) {
          //确保目标容器存在且可访问。注册 Portal 相关的事件处理(如点击穿透)。应用初始样式或动画。
          preparePortalMount(workInProgress.stateNode.containerInfo);
        }
      
      // 属性冒泡,将 Portal 子树的状态(如副作用标志、优先级)传播到父节点。
        bubbleProperties(workInProgress);
        return null;

      工具函数之 preparePortalMount 

      function preparePortalMount(portalInstance: Instance): void {
        listenToAllSupportedEvents(portalInstance);
      }

      工具函数之 listenToAllSupportedEvents 

      主要功能是为 React 应用的指定容器添加对所有支持的原生事件的监听。它会对事件监听进行去重处理,避免重复添加相同的事件监听器。同时,对于 selectionchange 事件会进行特殊处理,因为该事件不会冒泡,需要绑定到 document 对象上。 (详细的后续写一篇记录react合成事件)

      function listenToAllSupportedEvents(rootContainerElement: EventTarget) {
        // 检查 rootContainerElement 是否已经添加了事件监听器。如果没有,则将 listeningMarker 作为属性添加到 rootContainerElement 上,并将其值设为 true,表示已经添加了事件监听器。
        if (!(rootContainerElement: any)[listeningMarker]) {
          (rootContainerElement: any)[listeningMarker] = true;
      
          // allNativeEvents 是一个集合,包含了 React 支持的所有原生事件。
          // 遍历所有支持的原生事件
          allNativeEvents.forEach(domEventName => {
            if (domEventName !== 'selectionchange') {
              if (!nonDelegatedEvents.has(domEventName)) {
                listenToNativeEvent(domEventName, false, rootContainerElement);
              }
              listenToNativeEvent(domEventName, true, rootContainerElement);
            }
          });
      
          // 获取顶层document对象
          const ownerDocument =
            (rootContainerElement: any).nodeType === DOCUMENT_NODE
            ? rootContainerElement
            : (rootContainerElement: any).ownerDocument;
          
          if (ownerDocument !== null) {
            // The selectionchange event also needs deduplication
            // but it is attached to the document.
            if (!(ownerDocument: any)[listeningMarker]) {
              (ownerDocument: any)[listeningMarker] = true;
              listenToNativeEvent('selectionchange', false, ownerDocument);
            }
          }
      
        }
      }

      全局常量(根节点状态)

       React 渲染根节点(Root)的状态机,用于表示整个渲染过程中可能处于的不同阶段和结果。

      type RootExitStatus = 0 | 1 | 2 | 3 | 4 | 5 | 6;
      const RootInProgress = 0; // 根节点正在进行渲染
      const RootFatalErrored = 1; // 渲染过程中发生致命错误,无法恢复。
      const RootErrored = 2; //渲染过程中发生可恢复的错误。
      const RootSuspended = 3; // 渲染被挂起,等待异步资源(如数据或代码)。
      const RootSuspendedWithDelay = 4; // 渲染被挂起,但设置了延迟显示加载状态。
      const RootCompleted = 5; // 渲染成功完成,所有工作已提交到 DOM。
      const RootDidNotComplete = 6; // 渲染未完成,可能被更高优先级的更新中断。

       全局常量(组件类型)

       React 内部用于标识不同类型组件和节点的常量(称为 FiberTag)。每个常量对应一种特定的组件或节点类型。

      export const FunctionComponent = 0;
      export const ClassComponent = 1;
      
      export const HostRoot = 3; // Root of a host tree. Could be nested inside another node.
      export const HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
      export const HostComponent = 5;
      export const HostText = 6;
      
      export const Fragment = 7;
      export const Mode = 8;
      export const ContextConsumer = 9;
      export const ContextProvider = 10;
      export const ForwardRef = 11;
      export const Profiler = 12;
      
      export const SuspenseComponent = 13;
      
      export const MemoComponent = 14;
      export const SimpleMemoComponent = 15;
      export const LazyComponent = 16;
      
      export const IncompleteClassComponent = 17;
      export const DehydratedFragment = 18;
      
      export const SuspenseListComponent = 19;
      export const ScopeComponent = 21;
      export const OffscreenComponent = 22;
      export const LegacyHiddenComponent = 23;
      export const CacheComponent = 24;
      export const TracingMarkerComponent = 25;
      
      export const HostHoistable = 26;
      export const HostSingleton = 27;
      
      export const IncompleteFunctionComponent = 28;
      export const Throw = 29;

       全局常量(节点的状态和操作位掩码)

      标记节点状态和操作的位掩码常量(Flags)。每个标志都是一个二进制值,通过位运算可以高效地组合、检查和修改这些标志。

      // 无操作(初始状态)。
      const NoFlags = /*                      */ 0b0000000000000000000000000000;
      // 组件已执行工作(用于优化)。
      const PerformedWork = /*                */ 0b0000000000000000000000000001;
      // 需要插入或移动 DOM 节点。
      const Placement = /*                    */ 0b0000000000000000000000000010;
      // 组件捕获到错误(用于错误边界)。
      const DidCapture = /*                   */ 0b0000000000000000000010000000;
      // 需要重置节点内容(如文本节点内容完全改变)。
      const Hydrating = /*                    */ 0b0000000000000001000000000000;
      
      // You can change the rest (and add more).
      // 需要更新 DOM 节点属性(如 props 变化)。
      const Update = /*                       */ 0b0000000000000000000000000100;
      // Fiber 被克隆(如列表重排序时复用节点)。
      const Cloned = /*                       */ 0b0000000000000000000000001000;
      
      // 需要删除子节点。
      const ChildDeletion = /*                */ 0b0000000000000000000000010000;
      // 需要重置节点内容(如文本节点内容完全改变)。
      const ContentReset = /*                 */ 0b0000000000000000000000100000;
      // 需要执行回调(如 useEffect、useLayoutEffect)。
      const Callback = /*                     */ 0b0000000000000000000001000000;
      /* Used by DidCapture:                            0b0000000000000000000010000000; */
      
      // 强制客户端渲染(如 SSR 水合失败)。
       const ForceClientRender = /*            */ 0b0000000000000000000100000000;
      // 需要处理 ref 关联或解关联。
       const Ref = /*                          */ 0b0000000000000000001000000000;
      // 需要捕获 DOM 快照(如 getSnapshotBeforeUpdate)。
       const Snapshot = /*                     */ 0b0000000000000000010000000000;
      // 表示存在被动副作用(如 useEffect),需要异步执行。
       const Passive = /*                      */ 0b0000000000000000100000000000;
      /* Used by Hydrating:                             0b0000000000000001000000000000; */
      
      // 组件可见性变化(如 Suspense 显示 / 隐藏)。
       const Visibility = /*                   */ 0b0000000000000010000000000000;
      // 状态一致性标记(用于并发模式)。
       const StoreConsistency = /*             */ 0b0000000000000100000000000000;

      全局常量

      1. RefStatic:用于标记与 ref 相关的静态状态。在 React 中,ref 用于访问 DOM 节点或组件实例,这个标志可能表示 ref 相关的操作或状态是静态的,不需要在每次渲染时重新处理。
      2. LayoutStatic:表示与布局相关的静态状态。布局操作可能涉及到元素的位置、大小等信息,这个标志可能用于指示某些布局信息在渲染过程中是静态的,不需要频繁更新。
      3. PassiveStatic:与被动副作用相关的静态状态。被动副作用通常是指那些在渲染完成后异步执行的副作用,如 useEffect 钩子中的某些操作,这个标志可能表示这些副作用的状态是静态的。
      4. MaySuspendCommit:表示该 Fiber 节点可能会暂停提交操作。在 React 的并发模式下,渲染过程可能会被暂停和恢复,这个标志用于标记那些可能会导致提交操作暂停的节点。
      const StaticMask =
        LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit;
      
      
      const RefStatic = /*                    */ 0b0000001000000000000000000000;
      const LayoutStatic = /*                 */ 0b0000010000000000000000000000;
      const PassiveStatic = /*                */ 0b0000100000000000000000000000;
      const MaySuspendCommit = /*             */ 0b0001000000000000000000000000;

      本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2385756.html

      如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

      相关文章

      DL00987-基于深度学习YOLOv11的红外鸟类目标检测含完整数据集

      提升科研能力&#xff0c;精准识别红外鸟类目标&#xff01; 完整代码数据集见文末 针对科研人员&#xff0c;尤其是研究生们&#xff0c;是否在鸟类目标检测中遇到过数据不够精准、处理困难等问题&#xff1f;现在&#xff0c;我们为你提供一款基于深度学习YOLOv11的红外鸟类…

      黑马程序员C++2024新版笔记 第4章 函数和结构体

      1.结构体的基本应用 结构体struct是一种用户自定义的复合数据类型&#xff0c;可以包含不同类型的成员。例如&#xff1a; struct Studet {string name;int age;string gender; } 结构体的声明定义和使用的基本语法&#xff1a; struct 结构体类型 {成员1类型 成员1名称;成…

      数据仓库,扫描量

      有五种通用技术用于限制数据的扫描量&#xff0c;正如图3 - 4所示。第一种技术是扫描那些被打上时戳的数据。当一个应用对记录的最近一次变化或更改打上时戳时&#xff0c;数据仓库扫描就能够很有效地进行&#xff0c;因为日期不相符的数据就接触不到了。然而&#xff0c;目前的…

      Vue3性能优化: 大规模列表渲染解决方案

      # Vue3性能优化: 大规模列表渲染解决方案 一、背景与挑战 背景 在大规模应用中&#xff0c;Vue3的列表渲染性能一直是开发者关注的焦点。大规模列表渲染往往会导致卡顿、内存占用过高等问题&#xff0c;影响用户体验和系统整体性能。 挑战 渲染大规模列表时&#xff0c;DOM操作…

      【RocketMQ 生产者和消费者】- 生产者启动源码 - MQClientInstance 定时任务(4)

      文章目录 1. 前言2. startScheduledTask 启动定时任务2.1 fetchNameServerAddr 拉取名称服务地址2.2 updateTopicRouteInfoFromNameServer 更新 topic 路由信息2.2.1 topic 路由信息2.2.2 updateTopicRouteInfoFromNameServer 获取 topic2.2.3 updateTopicRouteInfoFromNameSer…

      超全GPT-4o 风格提示词案例,持续更新中,附使用方式

      本文汇集了各类4o风格提示词的精选案例&#xff0c;从基础指令到复杂任务&#xff0c;从创意写作到专业领域&#xff0c;为您提供全方位的参考和灵感。我们将持续更新这份案例集&#xff0c;确保您始终能够获取最新、最有效的提示词技巧。 让我们一起探索如何通过精心设计的提…

      Android 自定义SnackBar和下滑取消

      如何自定义SnackBar 首先我们得了解SnackBar的布局&#xff1a; 之前我看有一些方案是获取内部的contentLayout&#xff0c;然后做一些处理。但是现在已经行不通了&#xff1a; RestrictTo(LIBRARY_GROUP) public static final class SnackbarLayout extends BaseTransientB…

      Netty学习专栏(三):Netty重要组件详解(Future、ByteBuf、Bootstrap)

      文章目录 前言一、Future & Promise&#xff1a;异步编程的救星1.1 传统NIO的问题1.2 Netty的解决方案1.3 代码示例&#xff1a;链式异步操作 二、ByteBuf&#xff1a;重新定义数据缓冲区2.1 传统NIO ByteBuffer的缺陷2.2 Netty ByteBuf的解决方案2.3 代码示例&#xff1a;…

      详解 C# 中基于发布-订阅模式的 Messenger 消息传递机制:Messenger.Default.Send/Register

      &#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

      多场景游戏AI新突破!Divide-Fuse-Conquer如何激发大模型“顿悟时刻“?

      多场景游戏AI新突破&#xff01;Divide-Fuse-Conquer如何激发大模型"顿悟时刻"&#xff1f; 大语言模型在强化学习中偶现的"顿悟时刻"引人关注&#xff0c;但多场景游戏中训练不稳定、泛化能力差等问题亟待解决。Divide-Fuse-Conquer方法&#xff0c;通过…

      Java 函数式接口(Functional Interface)

      一、理论说明 1. 函数式接口的定义 Java 函数式接口是一种特殊的接口&#xff0c;它只包含一个抽象方法&#xff08;Single Abstract Method, SAM&#xff09;&#xff0c;但可以包含多个默认方法或静态方法。函数式接口是 Java 8 引入 Lambda 表达式的基础&#xff0c;通过函…

      分布式锁总结

      文章目录 分布式锁什么是分布式锁&#xff1f;分布式锁的实现方式基于数据库(mysql)实现基于缓存(redis)多实例并发访问问题演示项目代码(使用redis)配置nginx.confjmeter压测复现问题并发是1&#xff0c;即不产生并发问题并发30测试,产生并发问题(虽然单实例是synchronized&am…

      使用MybatisPlus实现sql日志打印优化

      背景&#xff1a; 在排查无忧行后台服务日志时&#xff0c;一个请求可能会包含多个执行的sql&#xff0c;经常会遇到SQL语句与对应参数不连续显示&#xff0c;或者参数较多需要逐个匹配的情况。这种情况下&#xff0c;如果需要还原完整SQL语句就会比较耗时。因此&#xff0c;我…

      client.chat.completions.create方法参数详解

      response client.chat.completions.create(model"gpt-3.5-turbo", # 必需参数messages[], # 必需参数temperature1.0, # 可选参数max_tokensNone, # 可选参数top_p1.0, # 可选参数frequency_penalty0.0, # 可选参数presenc…

      深入浅出人工智能:机器学习、深度学习、强化学习原理详解与对比!

      各位朋友&#xff0c;大家好&#xff01;今天咱们聊聊人工智能领域里最火的“三剑客”&#xff1a;机器学习 (Machine Learning)、深度学习 (Deep Learning) 和 强化学习 (Reinforcement Learning)。 听起来是不是有点高大上&#xff1f; 别怕&#xff0c;我保证把它们讲得明明…

      基于 ColBERT 框架的后交互 (late interaction) 模型速递:Reason-ModernColBERT

      一、Reason-ModernColBERT 模型概述 Reason-ModernColBERT 是一种基于 ColBERT 框架的后交互 (late interaction) 模型&#xff0c;专为信息检索任务中的推理密集型场景设计。该模型在 reasonir-hq 数据集上进行训练&#xff0c;于 BRIGHT 基准测试中取得了极具竞争力的性能表…

      vector中reserve导致的析构函数问题

      接上一节vector实现&#xff0c;解决杨辉三角问题时&#xff0c;我在最后调试的时候&#xff0c;发现return vv时&#xff0c;调用析构函数&#xff0c;到第四步时才析构含有14641的vector。我设置了一个全局变量i来记录。 初始为35&#xff1a; 当为39时&#xff0c;也就是第…

      微软开源多智能体自定义自动化工作流系统:构建企业级AI驱动的智能引擎

      微软近期推出了一款开源解决方案加速器——Multi-Agent Custom Automation Engine Solution Accelerator,这是一个基于AI多智能体协作的自动化工作流系统。该系统通过指挥多个智能体(Agent)协同完成复杂任务,显著提升企业在数据处理、业务流程管理等场景中的效率与准确性。…

      安卓无障碍脚本开发全教程

      文章目录 第一部分&#xff1a;无障碍服务基础1.1 无障碍服务概述核心功能&#xff1a; 1.2 基本原理与架构1.3 开发环境配置所需工具&#xff1a;关键依赖&#xff1a; 第二部分&#xff1a;创建基础无障碍服务2.1 服务声明配置2.2 服务配置文件关键属性说明&#xff1a; 2.3 …

      SOC-ESP32S3部分:10-GPIO中断按键中断实现

      飞书文档https://x509p6c8to.feishu.cn/wiki/W4Wlw45P2izk5PkfXEaceMAunKg 学习了GPIO输入和输出功能后&#xff0c;参考示例工程&#xff0c;我们再来看看GPIO中断&#xff0c;IO中断的配置分为三步 配置中断触发类型安装中断服务注册中断回调函数 ESP32-S3的所有通用GPIO…