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;
+ }
}