Skip to content

03.并发渲染

js
import { scheduleSyncCallback, flushSyncCallbacks } from './ReactFiberSyncTaskQueue';
const RootInProgress = 0;
const RootCompleted = 5;
let workInProgressRootExitStatus = RootInProgress;
diff
function ensureRootIsScheduled(root) {
  const nextLanes = getNextLanes(root, NoLanes);
+  if (nextLanes === NoLanes) {
+    return;
+  }
  let newCallbackPriority = getHighestPriorityLane(nextLanes);
+ let newCallbackNode;
  if (newCallbackPriority === SyncLane) {
+   scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root));
+   queueMicrotask(flushSyncCallbacks);
+   newCallbackNode = null;
  } else {
    let schedulerPriorityLevel;
    switch (lanesToEventPriority(nextLanes)) {
      case DiscreteEventPriority:
        schedulerPriorityLevel = ImmediateSchedulerPriority;
        break;
      case ContinuousEventPriority:
        schedulerPriorityLevel = UserBlockingSchedulerPriority;
        break;
      case DefaultEventPriority:
        schedulerPriorityLevel = NormalSchedulerPriority;
        break;
      case IdleEventPriority:
        schedulerPriorityLevel = IdleSchedulerPriority;
        break;
      default:
        schedulerPriorityLevel = NormalSchedulerPriority;
        break;
    }
+   newCallbackNode = Scheduler_scheduleCallback(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root));
  }
+ root.callbackNode = newCallbackNode
}
js
function performSyncWorkOnRoot(root) {
  const lanes = getNextLanes(root);
  renderRootSync(root, lanes);
  const finishedWork = root.current.alternate;
  root.finishedWork = finishedWork;
  commitRoot(root);
  return null;
}
diff
function performConcurrentWorkOnRoot(root, didTimeout) {
+ const originalCallbackNode = root.callbackNode;
+  const lanes = getNextLanes(root, NoLanes);
+  if (lanes === NoLanes) {
+    return null;
+  }
+  const shouldTimeSlice = !includesBlockingLane(root, lanes) && (!didTimeout);
+  const exitStatus = shouldTimeSlice ?
+    renderRootConcurrent(root, lanes) : renderRootSync(root, lanes);
+  if (exitStatus !== RootInProgress) {
    const finishedWork = root.current.alternate;
    root.finishedWork = finishedWork;
    commitRoot(root);
+  }
  if (root.callbackNode === originalCallbackNode) {
    return performConcurrentWorkOnRoot.bind(null, root);
  }
  return null;
}
js
function renderRootConcurrent(root, lanes) {
  if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {
    prepareFreshStack(root, lanes);
  }
  workLoopConcurrent();
  if (workInProgress !== null) {
    return RootInProgress;
  }
  return workInProgressRootExitStatus;
}
js
function commitRoot(root) {
  const previousUpdatePriority = getCurrentUpdatePriority();
  try {
    setCurrentUpdatePriority(DiscreteEventPriority);
    commitRootImpl(root)
  } finally {
    setCurrentUpdatePriority(previousUpdatePriority);
  }
}
diff
+function commitRootImpl(root) {
  const { finishedWork } = root;
  workInProgressRoot = null;
  workInProgressRootRenderLanes = null;
+ root.callbackNode = null;
  if ((finishedWork.subtreeFlags & Passive) !== NoFlags
    || (finishedWork.flags & Passive) !== NoFlags) {
    if (!rootDoesHavePassiveEffect) {
      rootDoesHavePassiveEffect = true;
+     Scheduler_scheduleCallback(NormalSchedulerPriority, flushPassiveEffect);
    }
  }
  ...
}
diff
function prepareFreshStack(root, renderLanes) {
-if (root !== workInProgressRoot || workInProgressRenderLanes !== renderLanes) {
  workInProgress = createWorkInProgress(root.current, null);
-}
  workInProgressRootRenderLanes = renderLanes;
  workInProgressRoot = root;
  finishQueueingConcurrentUpdates();
}
diff
function renderRootSync(root, renderLanes) {
+ if (root !== workInProgressRoot || workInProgressRootRenderLanes !== renderLanes) {
    prepareFreshStack(root, renderLanes);
+ }
  workLoopSync();
}
diff
function completeUnitOfWork(unitOfWork) {
  let completedWork = unitOfWork;
  do {
    const current = completedWork.alternate;
    const returnFiber = completedWork.return;
    completeWork(current, completedWork);
    const siblingFiber = completedWork.sibling;
    if (siblingFiber !== null) {
      workInProgress = siblingFiber;
      return;
    }
    completedWork = returnFiber;
    workInProgress = completedWork;
  } while (completedWork !== null);
+  if (workInProgressRootExitStatus === RootInProgress) {
+    workInProgressRootExitStatus = RootCompleted;
+  }
}

基于 VitePress 构建