2. 调度入口
获取rootFiber;更新fiber的lanes;从当前fiber往上遍历至fiberRoot,更新父fiber的childLanes
更新rootFiber的pendingLanes和eventTimes
若是同步非批量更新,调用performSyncWorkOnRoot(root);同步非批量更新和异步更新,调用ensureRootIsScheduled(root, eventTime)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 function scheduleUpdateOnFiber (fiber, lane, eventTime ) { var root = markUpdateLaneFromFiberToRoot(fiber, lane); markRootUpdated(root, lane, eventTime); if (root === workInProgressRoot) { { workInProgressRootUpdatedLanes = mergeLanes(workInProgressRootUpdatedLanes, lane); } if (workInProgressRootExitStatus === RootSuspendedWithDelay) { markRootSuspended$1 (root, workInProgressRootRenderLanes); } } if (lane === SyncLane) { if ( (executionContext & LegacyUnbatchedContext) !== NoContext && (executionContext & (RenderContext | CommitContext)) === NoContext) { performSyncWorkOnRoot(root); } else { ensureRootIsScheduled(root, eventTime); if (executionContext === NoContext && (fiber.mode & ConcurrentMode) === NoMode) { resetRenderTimer(); flushSyncCallbacksOnlyInLegacyMode(); } } } else { ensureRootIsScheduled(root, eventTime); } return root; }
2.1 markUpdateLaneFromFiberToRoot: 更新fiber的lanes,返回fiberRoot 从当前fiber开始往上到rootFiber更新所有fiber的childLanes
更新当前fiber的lanes和alternate的lanes,
从下往上遍历父fiber,更新父fiber的childLanes和父fiber.alternate的childLanes,直到rootFiber
返回fiberRoot
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 function markUpdateLaneFromFiberToRoot (sourceFiber, lane ) { sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); var alternate = sourceFiber.alternate; if (alternate !== null ) { alternate.lanes = mergeLanes(alternate.lanes, lane); } var node = sourceFiber; var parent = sourceFiber.return; while (parent !== null ) { parent.childLanes = mergeLanes(parent.childLanes, lane); alternate = parent.alternate; if (alternate !== null ) { alternate.childLanes = mergeLanes(alternate.childLanes, lane); } node = parent; parent = parent.return; } if (node.tag === HostRoot) { var root = node.stateNode; return root; } else { return null ; } }
2.2 markRootUpdated:更新rootFiber的pendingLanes和eventTimes
将当前更新的lane和更新开始时间分别保存到rootFiber.pendingLanes和rootFiber.eventTimes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function markRootUpdated (root, updateLane, eventTime ) { root.pendingLanes |= updateLane; var higherPriorityLanes = updateLane - 1 ; root.suspendedLanes &= higherPriorityLanes; root.pingedLanes &= higherPriorityLanes; var eventTimes = root.eventTimes; var index = laneToIndex(updateLane); eventTimes[index] = eventTime; }
2.3 ensureRootIsScheduled: 定义了高优先级任务插队逻辑(赛车抢赛道) 获取优先级最高的lane,高优先级任务打断低优先级任务
1)循环遍历root.pendingLanes,没有过期时间,计算过期时间;有过期时间,判断是否过期,若过期,加入到root.expiredLanes中
2)从root.expiredLanes和root.pendingLanes未执行任务中找出优先级最高的lane和对应的优先级,获取lanes集合的优先级顺序是,过期任务的expiredLanes>非空闲且非挂起任务的lanes > 非空闲且挂起又恢复任务的lanes > 空闲且非挂起任务的lanes > 空闲且挂起又恢复任务的lanes
3)比较新旧任务的优先级,两者相等,无需调度;前者大于后者,取消旧任务
4)新任务的优先级高于旧任务,根据新任务的优先级来进行不同的调度任务:
同步优先级:调用scheduleSyncCallback去同步执行任务。 同步批量执行:调用scheduleCallback,将任务以立即执行的优先级去加入调度。 属于concurrent模式的优先级:调用scheduleCallback,将任务通过lanePriorityToSchedulerPriority获取到的新任务优先级去加入调度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 function ensureRootIsScheduled (root, currentTime ) { var existingCallbackNode = root.callbackNode; markStarvedLanesAsExpired(root, currentTime); var nextLanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes); var newCallbackPriority = returnNextLanesPriority(); if (nextLanes === NoLanes) { if (existingCallbackNode !== null ) { cancelCallback(existingCallbackNode); root.callbackNode = null ; root.callbackPriority = NoLanePriority; } return ; } if (existingCallbackNode !== null ) { var existingCallbackPriority = root.callbackPriority; if (existingCallbackPriority === newCallbackPriority) { return ; } cancelCallback(existingCallbackNode); } var newCallbackNode; if (newCallbackPriority === SyncLanePriority) { newCallbackNode = scheduleSyncCallback(performSyncWorkOnRoot.bind(null , root)); } else if (newCallbackPriority === SyncBatchedLanePriority) { newCallbackNode = scheduleCallback(ImmediatePriority$1 , performSyncWorkOnRoot.bind(null , root)); } else { var schedulerPriorityLevel = lanePriorityToSchedulerPriority(newCallbackPriority); newCallbackNode = scheduleCallback(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null , root)); } root.callbackPriority = newCallbackPriority; root.callbackNode = newCallbackNode; }
1)markStarvedLanesAsExpired
循环遍历pendingLanes(未执行的任务包含的lane),如果没过期时间就计算一个过期时间,如果过期了就加入root.expiredLanes中
在下次调用getNextLane函数的时候会优先返回expiredLanes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 function markStarvedLanesAsExpired (root, currentTime ) { var pendingLanes = root.pendingLanes; var suspendedLanes = root.suspendedLanes; var pingedLanes = root.pingedLanes; var expirationTimes = root.expirationTimes; var lanes = pendingLanes; while (lanes > 0 ) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; var expirationTime = expirationTimes[index]; if (expirationTime === NoTimestamp) { if ((lane & suspendedLanes) === NoLanes || (lane & pingedLanes) !== NoLanes) { expirationTimes[index] = computeExpirationTime(lane, currentTime); } } else if (expirationTime <= currentTime) { root.expiredLanes |= lane; } lanes &= ~lane; } } function computeExpirationTime (lane, currentTime ) { getHighestPriorityLanes(lane); var priority = return_highestLanePriority; if (priority >= InputContinuousLanePriority) { return currentTime + 250 ; } else if (priority >= TransitionPriority) { return currentTime + 5000 ; } else { return NoTimestamp; } }
2)getNextLanes 获取下一个执行任务的lanes,即从root.pendingLanes未执行任务和root.expiredLanes中找出优先级最高的lane
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 function getNextLanes (root, wipLanes ) { var pendingLanes = root.pendingLanes; if (pendingLanes === NoLanes) { return_highestLanePriority = NoLanePriority; return NoLanes; } var nextLanes = NoLanes; var nextLanePriority = NoLanePriority; var expiredLanes = root.expiredLanes; var suspendedLanes = root.suspendedLanes; var pingedLanes = root.pingedLanes; if (expiredLanes !== NoLanes) { nextLanes = expiredLanes; nextLanePriority = return_highestLanePriority = SyncLanePriority; } else { var nonIdlePendingLanes = pendingLanes & NonIdleLanes; if (nonIdlePendingLanes !== NoLanes) { var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; if (nonIdleUnblockedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); nextLanePriority = return_highestLanePriority; } else { var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; if (nonIdlePingedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); nextLanePriority = return_highestLanePriority; } } } else { var unblockedLanes = pendingLanes & ~suspendedLanes; if (unblockedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(unblockedLanes); nextLanePriority = return_highestLanePriority; } else { if (pingedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(pingedLanes); nextLanePriority = return_highestLanePriority; } } } } if (nextLanes === NoLanes) { return NoLanes; } nextLanes = pendingLanes & getEqualOrHigherPriorityLanes(nextLanes); if (wipLanes !== NoLanes && wipLanes !== nextLanes && (wipLanes & suspendedLanes) === NoLanes) { getHighestPriorityLanes(wipLanes); var wipLanePriority = return_highestLanePriority; if (nextLanePriority <= wipLanePriority) { return wipLanes; } else { return_highestLanePriority = nextLanePriority; } } return nextLanes; }
getHighestPriorityLanes:从优先级lanes集合中拿到优先级最高lanes和对应的更新任务优先级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 function getHighestPriorityLanes (lanes ) { if ((SyncLane & lanes) !== NoLanes) { return_highestLanePriority = SyncLanePriority; return SyncLane; } if ((SyncBatchedLane & lanes) !== NoLanes) { return_highestLanePriority = SyncBatchedLanePriority; return SyncBatchedLane; } if ((InputDiscreteHydrationLane & lanes) !== NoLanes) { return_highestLanePriority = InputDiscreteHydrationLanePriority; return InputDiscreteHydrationLane; } var inputDiscreteLanes = InputDiscreteLanes & lanes; if (inputDiscreteLanes !== NoLanes) { return_highestLanePriority = InputDiscreteLanePriority; return inputDiscreteLanes; } if ((lanes & InputContinuousHydrationLane) !== NoLanes) { return_highestLanePriority = InputContinuousHydrationLanePriority; return InputContinuousHydrationLane; } var inputContinuousLanes = InputContinuousLanes & lanes; if (inputContinuousLanes !== NoLanes) { return_highestLanePriority = InputContinuousLanePriority; return inputContinuousLanes; } if ((lanes & DefaultHydrationLane) !== NoLanes) { return_highestLanePriority = DefaultHydrationLanePriority; return DefaultHydrationLane; } var defaultLanes = DefaultLanes & lanes; if (defaultLanes !== NoLanes) { return_highestLanePriority = DefaultLanePriority; return defaultLanes; } if ((lanes & TransitionHydrationLane) !== NoLanes) { return_highestLanePriority = TransitionHydrationPriority; return TransitionHydrationLane; } var transitionLanes = TransitionLanes & lanes; if (transitionLanes !== NoLanes) { return_highestLanePriority = TransitionPriority; return transitionLanes; } var retryLanes = RetryLanes & lanes; if (retryLanes !== NoLanes) { return_highestLanePriority = RetryLanePriority; return retryLanes; } if (lanes & SelectiveHydrationLane) { return_highestLanePriority = SelectiveHydrationLanePriority; return SelectiveHydrationLane; } if ((lanes & IdleHydrationLane) !== NoLanes) { return_highestLanePriority = IdleHydrationLanePriority; return IdleHydrationLane; } var idleLanes = IdleLanes & lanes; if (idleLanes !== NoLanes) { return_highestLanePriority = IdleLanePriority; return idleLanes; } if ((OffscreenLane & lanes) !== NoLanes) { return_highestLanePriority = OffscreenLanePriority; return OffscreenLane; } return_highestLanePriority = DefaultLanePriority; return lanes; }
getEqualOrHigherPriorityLanes:获取比当前lanes优先级更高或相等的lanes集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function getEqualOrHigherPriorityLanes (lanes ) { return (getLowestPriorityLane(lanes) << 1 ) - 1 ; } function getLowestPriorityLane (lanes ) { var index = 31 - clz32(lanes); return index < 0 ? NoLanes : 1 << index; } function pickArbitraryLaneIndex (lanes ) { return 31 - clz32(lanes); } function laneToIndex (lane ) { return pickArbitraryLaneIndex(lane); }
lanePriorityToSchedulerPriority:更新任务优先级转为调度优先级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function lanePriorityToSchedulerPriority (lanePriority ) { switch (lanePriority) { case SyncLanePriority: case SyncBatchedLanePriority: return ImmediatePriority; case InputDiscreteHydrationLanePriority: case InputDiscreteLanePriority: case InputContinuousHydrationLanePriority: case InputContinuousLanePriority: return UserBlockingPriority; case DefaultHydrationLanePriority: case DefaultLanePriority: case TransitionHydrationPriority: case TransitionPriority: case SelectiveHydrationLanePriority: case RetryLanePriority: return NormalPriority; case IdleHydrationLanePriority: case IdleLanePriority: case OffscreenLanePriority: return IdlePriority; case NoLanePriority: return NoPriority; default : } }