行数 https://github.com/a8397550/react-source-share/blob/master/default/react-dom-default.js
function scheduleUpdateOnFiber(fiber, expirationTime) {// ... 省略// trueif (expirationTime === Sync) {if (// 常量 NoContext = 0// 初始化时 executionContext = 8 LegacyUnbatchedContext = 8// 8 & 8 = 8 下条语句初始化时结果为true(executionContext & LegacyUnbatchedContext) !== NoContext &&// 初始化 (8 & (16 | 32)) === NoContext 结果为true(executionContext & (RenderContext | CommitContext)) === NoContext) {// expirationTime === 1073741823// 初始化时,啥也没干schedulePendingInteractions(root, expirationTime);var callback = renderRoot(root, Sync, true);while (callback !== null) {callback = callback(true);}} else {scheduleCallbackForRoot(root, ImmediatePriority, Sync);if (executionContext === NoContext) {flushSyncCallbackQueue();}}} else {scheduleCallbackForRoot(root, priorityLevel, expirationTime);}if ((executionContext & DiscreteEventContext) !== NoContext && (// Only updates at user-blocking priority or greater are considered// discrete, even inside a discrete event.priorityLevel === UserBlockingPriority$2 || priorityLevel === ImmediatePriority)) {// This is the result of a discrete event. Track the lowest priority// discrete update per root so we can flush them early, if needed.if (rootsWithPendingDiscreteUpdates === null) {rootsWithPendingDiscreteUpdates = new Map([[root, expirationTime]]);} else {var lastDiscreteTime = rootsWithPendingDiscreteUpdates.get(root);if (lastDiscreteTime === undefined || lastDiscreteTime > expirationTime) {rootsWithPendingDiscreteUpdates.set(root, expirationTime);}}}}
renderRoot 主要方法
function renderRoot(root, expirationTime, isSync) {(function () {// (8 & (16 | 32)) === NoContext 结果为true 取反 falseif (!((executionContext & (RenderContext | CommitContext)) === NoContext)) {{throw ReactError(Error('Should not already be working.'));}}})();// 初始化时 true && 1073741823 !== 1073741823 结果 falseif (enableUserTimingAPI && expirationTime !== Sync) {var didExpire = isSync;stopRequestCallbackTimer(didExpire);}// 初始化时 1073741823 < 1073741823 结果 falseif (root.firstPendingTime < expirationTime) {return null;}// isSync = true// root.finishedExpirationTime = 0// expirationTime = 0// 初始化时 结果为falseif (isSync && root.finishedExpirationTime === expirationTime) {return commitRoot.bind(null, root);}// 初始化时,默认return了false,啥也没干flushPassiveEffects();// root = FiberRootNode// workInProgressRoot = null// expirationTime = 1073741823// renderExpirationTime = 0if (root !== workInProgressRoot || expirationTime !== renderExpirationTime) {// prepare 准备 [prɪˈpeə(r)]// Fresh 新的 [freʃ]// stack 堆栈 [stæk]prepareFreshStack(root, expirationTime);startWorkOnPendingInteractions(root, expirationTime);} else if (workInProgressRootExitStatus === RootSuspendedWithDelay) {if (workInProgressRootHasPendingPing) {prepareFreshStack(root, expirationTime);} else {var lastPendingTime = root.lastPendingTime;if (lastPendingTime < expirationTime) {return renderRoot.bind(null, root, lastPendingTime);}}}// workInProgress = FiberNodeif (workInProgress !== null) {// executionContext = 8var prevExecutionContext = executionContext;// 8 | 16 = 24executionContext |= RenderContext;// ReactCurrentDispatcher.current = nullvar prevDispatcher = ReactCurrentDispatcher.current;if (prevDispatcher === null) {/*var ContextOnlyDispatcher = {readContext: readContext,useCallback: throwInvalidHookError,useContext: throwInvalidHookError,useEffect: throwInvalidHookError,useImperativeHandle: throwInvalidHookError,useLayoutEffect: throwInvalidHookError,useMemo: throwInvalidHookError,useReducer: throwInvalidHookError,useRef: throwInvalidHookError,useState: throwInvalidHookError,useDebugValue: throwInvalidHookError,useResponder: throwInvalidHookError};*/prevDispatcher = ContextOnlyDispatcher;}// ReactCurrentDispatcher.current = null 全局变量ReactCurrentDispatcher.current = ContextOnlyDispatcher;var prevInteractions = null;// enableSchedulerTracing = trueif (enableSchedulerTracing) {// __interactionsRef.current = Set(0)prevInteractions = __interactionsRef.current;// root.memoizedInteractions = Set(0)__interactionsRef.current = root.memoizedInteractions;}startWorkLoopTimer(workInProgress);// 方法形参 isSync = trueif (isSync) {// expirationTime = 1073741823 !== Sync = 1073741823 结果为falseif (expirationTime !== Sync) {var currentTime = requestCurrentTime();if (currentTime < expirationTime) {executionContext = prevExecutionContext;resetContextDependencies();ReactCurrentDispatcher.current = prevDispatcher;if (enableSchedulerTracing) {__interactionsRef.current = prevInteractions;}return renderRoot.bind(null, root, currentTime);}}} else {currentEventTime = NoWork;}do {try {// isSync = trueif (isSync) {workLoopSync();} else {workLoop();}break;} catch (thrownValue) {resetContextDependencies();resetHooks();var sourceFiber = workInProgress;if (sourceFiber === null || sourceFiber.return === null) {prepareFreshStack(root, expirationTime);executionContext = prevExecutionContext;throw thrownValue;}if (enableProfilerTimer && sourceFiber.mode & ProfileMode) {stopProfilerTimerIfRunningAndRecordDelta(sourceFiber, true);}var returnFiber = sourceFiber.return;throwException(root, returnFiber, sourceFiber, thrownValue, renderExpirationTime);workInProgress = completeUnitOfWork(sourceFiber);}} while (true);executionContext = prevExecutionContext;resetContextDependencies();ReactCurrentDispatcher.current = prevDispatcher;if (enableSchedulerTracing) {__interactionsRef.current = prevInteractions;}if (workInProgress !== null) {// There's still work left over. Return a continuation.stopInterruptedWorkLoopTimer();if (expirationTime !== Sync) {startRequestCallbackTimer();}return renderRoot.bind(null, root, expirationTime);}}stopFinishedWorkLoopTimer();root.finishedWork = root.current.alternate;root.finishedExpirationTime = expirationTime;var isLocked = resolveLocksOnRoot(root, expirationTime);if (isLocked) {return null;}workInProgressRoot = null;switch (workInProgressRootExitStatus) {case RootIncomplete:{(function () {{{throw ReactError(Error('Should have a work-in-progress.'));}}})();}case RootErrored:{var _lastPendingTime = root.lastPendingTime;if (_lastPendingTime < expirationTime) {return renderRoot.bind(null, root, _lastPendingTime);}if (!isSync) {prepareFreshStack(root, expirationTime);scheduleSyncCallback(renderRoot.bind(null, root, expirationTime));return null;}return commitRoot.bind(null, root);}case RootSuspended:{flushSuspensePriorityWarningInDEV();var hasNotProcessedNewUpdates = workInProgressRootLatestProcessedExpirationTime === Sync;if (hasNotProcessedNewUpdates && !isSync &&!(true && flushSuspenseFallbacksInTests && IsThisRendererActing.current)) {var msUntilTimeout = globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now();if (msUntilTimeout > 10) {if (workInProgressRootHasPendingPing) {prepareFreshStack(root, expirationTime);return renderRoot.bind(null, root, expirationTime);}var _lastPendingTime2 = root.lastPendingTime;if (_lastPendingTime2 < expirationTime) {return renderRoot.bind(null, root, _lastPendingTime2);}root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root), msUntilTimeout);return null;}}return commitRoot.bind(null, root);}case RootSuspendedWithDelay:{flushSuspensePriorityWarningInDEV();if (!isSync &&!(true && flushSuspenseFallbacksInTests && IsThisRendererActing.current)) {if (workInProgressRootHasPendingPing) {prepareFreshStack(root, expirationTime);return renderRoot.bind(null, root, expirationTime);}var _lastPendingTime3 = root.lastPendingTime;if (_lastPendingTime3 < expirationTime) {return renderRoot.bind(null, root, _lastPendingTime3);}var _msUntilTimeout = void 0;if (workInProgressRootLatestSuspenseTimeout !== Sync) {_msUntilTimeout = expirationTimeToMs(workInProgressRootLatestSuspenseTimeout) - now();} else if (workInProgressRootLatestProcessedExpirationTime === Sync) {_msUntilTimeout = 0;} else {var eventTimeMs = inferTimeFromExpirationTime(workInProgressRootLatestProcessedExpirationTime);var currentTimeMs = now();var timeUntilExpirationMs = expirationTimeToMs(expirationTime) - currentTimeMs;var timeElapsed = currentTimeMs - eventTimeMs;if (timeElapsed < 0) {timeElapsed = 0;}_msUntilTimeout = jnd(timeElapsed) - timeElapsed;if (timeUntilExpirationMs < _msUntilTimeout) {_msUntilTimeout = timeUntilExpirationMs;}}if (_msUntilTimeout > 10) {root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root), _msUntilTimeout);return null;}}return commitRoot.bind(null, root);}case RootCompleted:{if (!isSync &&!(true && flushSuspenseFallbacksInTests && IsThisRendererActing.current) && workInProgressRootLatestProcessedExpirationTime !== Sync && workInProgressRootCanSuspendUsingConfig !== null) {var _msUntilTimeout2 = computeMsUntilSuspenseLoadingDelay(workInProgressRootLatestProcessedExpirationTime, expirationTime, workInProgressRootCanSuspendUsingConfig);if (_msUntilTimeout2 > 10) {root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root), _msUntilTimeout2);return null;}}return commitRoot.bind(null, root);}default:{(function () {{{throw ReactError(Error('Unknown root exit status.'));}}})();}}}
flushPassiveEffects
function flushPassiveEffects() {// 变量rootWithPendingPassiveEffects 默认等于nullif (rootWithPendingPassiveEffects === null) {return false;}var root = rootWithPendingPassiveEffects;var expirationTime = pendingPassiveEffectsExpirationTime;var renderPriorityLevel = pendingPassiveEffectsRenderPriority;rootWithPendingPassiveEffects = null;pendingPassiveEffectsExpirationTime = NoWork;pendingPassiveEffectsRenderPriority = NoPriority;var priorityLevel = renderPriorityLevel > NormalPriority ? NormalPriority : renderPriorityLevel;return runWithPriority$2(priorityLevel, flushPassiveEffectsImpl.bind(null, root, expirationTime));}
prepareFreshStack
function prepareFreshStack(root, expirationTime) {// 初始化时 root.finishedWork = null,root.finishedExpirationTime = 0// NoWork = 0root.finishedWork = null;root.finishedExpirationTime = NoWork;// root.timeoutHandle 初始化时 = -1var timeoutHandle = root.timeoutHandle;// 常量 noTimeout = -1if (timeoutHandle !== noTimeout) {root.timeoutHandle = noTimeout;cancelTimeout(timeoutHandle);}// 初始化时 变量 workInProgress = nullif (workInProgress !== null) {var interruptedWork = workInProgress.return;while (interruptedWork !== null) {unwindInterruptedWork(interruptedWork);interruptedWork = interruptedWork.return;}}// 初始化时 workInProgressRoot = null// Progress 进程 [ˈprəʊɡres]workInProgressRoot = root;workInProgress = createWorkInProgress(root.current, null, expirationTime);// expirationTime = 1073741823renderExpirationTime = expirationTime;// RootIncomplete = 0workInProgressRootExitStatus = RootIncomplete;// Sync = 1073741823workInProgressRootLatestProcessedExpirationTime = Sync;workInProgressRootLatestSuspenseTimeout = Sync;workInProgressRootCanSuspendUsingConfig = null;workInProgressRootHasPendingPing = false;// enableSchedulerTracing = trueif (enableSchedulerTracing) {spawnedWorkDuringRender = null;}{/*ReactStrictModeWarnings = {discardPendingWarnings: ƒ ()flushLegacyContextWarning: ƒ ()flushPendingUnsafeLifecycleWarnings: ƒ ()recordLegacyContextWarning: ƒ (fiber, instance)recordUnsafeLifecycleWarnings: ƒ (fiber, instance)__proto__: Object}11858行ReactStrictModeWarnings.discardPendingWarnings = function () {pendingComponentWillMountWarnings = [];pendingUNSAFE_ComponentWillMountWarnings = [];pendingComponentWillReceivePropsWarnings = [];pendingUNSAFE_ComponentWillReceivePropsWarnings = [];pendingComponentWillUpdateWarnings = [];pendingUNSAFE_ComponentWillUpdateWarnings = [];pendingLegacyContextWarning = new Map();};*/ReactStrictModeWarnings.discardPendingWarnings();componentsThatTriggeredHighPriSuspend = null;}}
行数 23910 createWorkInProgress [prəˈɡres]
function createWorkInProgress(current, pendingProps, expirationTime) {// current.alternate 默认为nullvar workInProgress = current.alternate;if (workInProgress === null) {// current.tag = 3// pendingProps = null// current.key = null// current.mode = 0workInProgress = createFiber(current.tag, pendingProps,current.key, current.mode);// current.elementType = nullworkInProgress.elementType = current.elementType;// current.type = nullworkInProgress.type = current.type;// current.stateNode = FiberRootNodeworkInProgress.stateNode = current.stateNode;{// DEV-only fields// current._debugID = 1;workInProgress._debugID = current._debugID;// current._debugSource = null;workInProgress._debugSource = current._debugSource;// current._debugOwner = null;workInProgress._debugOwner = current._debugOwner;// current._debugHookTypes = null;workInProgress._debugHookTypes = current._debugHookTypes;}workInProgress.alternate = current;current.alternate = workInProgress;} else {workInProgress.pendingProps = pendingProps;workInProgress.effectTag = NoEffect;workInProgress.nextEffect = null;workInProgress.firstEffect = null;workInProgress.lastEffect = null;if (enableProfilerTimer) {workInProgress.actualDuration = 0;workInProgress.actualStartTime = -1;}}// current.childExpirationTime = 0workInProgress.childExpirationTime = current.childExpirationTime;// current.expirationTime = 1073741823workInProgress.expirationTime = current.expirationTime;// current.child = nullworkInProgress.child = current.child;// current.memoizedProps = null;workInProgress.memoizedProps = current.memoizedProps;// current.memoizedState = null;workInProgress.memoizedState = current.memoizedState;// 重要 current.updateQueue = {firstUpdate, lastUpdate, ...}/*firstUpdate = {payload: {element: {$$typeof: Symbol(react.element), ...}, ...}, ...}lastUpdate的结构与firstUpdate一致*/workInProgress.updateQueue = current.updateQueue;// current.dependencies = nullvar currentDependencies = current.dependencies;workInProgress.dependencies = currentDependencies === null ? null : {expirationTime: currentDependencies.expirationTime,firstContext: currentDependencies.firstContext,responders: currentDependencies.responders};// current.sibling = null;workInProgress.sibling = current.sibling;// current.index = 0;workInProgress.index = current.index;// current.ref = null;workInProgress.ref = current.ref;// 常量 enableProfilerTimer = trueif (enableProfilerTimer) {// current.selfBaseDuration = 0;workInProgress.selfBaseDuration = current.selfBaseDuration;// current.treeBaseDuration = 0;workInProgress.treeBaseDuration = current.treeBaseDuration;}{// current._debugNeedsRemount = false;workInProgress._debugNeedsRemount = current._debugNeedsRemount;switch (workInProgress.tag) {case IndeterminateComponent: // 2case FunctionComponent: // 0case SimpleMemoComponent: // 15workInProgress.type = resolveFunctionForHotReloading(current.type);break;case ClassComponent: // 1workInProgress.type = resolveClassForHotReloading(current.type);break;case ForwardRef: // 11workInProgress.type = resolveForwardRefForHotReloading(current.type);break;default:break;}}return workInProgress;}
startWorkOnPendingInteractions
function startWorkOnPendingInteractions(root, expirationTime) {// enableSchedulerTracing = trueif (!enableSchedulerTracing) {return;}var interactions = new Set();// root.pendingInteractionMap.size = 0root.pendingInteractionMap.forEach(function (scheduledInteractions, scheduledExpirationTime) {if (scheduledExpirationTime >= expirationTime) {scheduledInteractions.forEach(function (interaction) {return interactions.add(interaction);});}});root.memoizedInteractions = interactions;if (interactions.size > 0) {var subscriber = __subscriberRef.current;if (subscriber !== null) {var threadID = computeThreadID(root, expirationTime);try {subscriber.onWorkStarted(interactions, threadID);} catch (error) {// If the subscriber throws, rethrow it in a separate taskscheduleCallback(ImmediatePriority, function () {throw error;});}}}}
startWorkLoopTimer
var formatMarkName = function (markName) {// reactEmoji = "⚛"return reactEmoji + ' ' + markName;};var beginMark = function (markName) {// performance 需要注意这个玩意是window.performance// performance 主要用来做性能监控,白屏时间,首屏时间,用户可操作时间节点,总下载时间...performance.mark(formatMarkName(markName));};var resumeTimers = function () {// currentFiber = FiberNode # renderRoot 传入 workInProgressif (currentFiber !== null) {resumeTimersRecursively(currentFiber);}};var resumeTimersRecursively = function (fiber) {// fiber.return = nullif (fiber.return !== null) {resumeTimersRecursively(fiber.return);}// fiber._debugIsCurrentlyTiming = falseif (fiber._debugIsCurrentlyTiming) {beginFiberMark(fiber, null);}};function startWorkLoopTimer(nextUnitOfWork) {// enableUserTimingAPI = trueif (enableUserTimingAPI) {// nextUnitOfWork = FiberNode # renderRoot 传入 workInProgresscurrentFiber = nextUnitOfWork;// supportsUserTiming = trueif (!supportsUserTiming) {return;}commitCountInCurrentWorkLoop = 0;beginMark('(React Tree Reconciliation)');// Resume any measurements that were in progress during the last loop.resumeTimers();}}
行数 22320 workLoopSync
function workLoopSync() {// workInProgress = FiberNodewhile (workInProgress !== null) {workInProgress = performUnitOfWork(workInProgress);}}function performUnitOfWork(unitOfWork) {// The current, flushed, state of this fiber is the alternate. Ideally// nothing should rely on this, but relying on it here means that we don't// need an additional field on the work in progress.var current$$1 = unitOfWork.alternate;startWorkTimer(unitOfWork);setCurrentFiber(unitOfWork);var next = void 0;if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {startProfilerTimer(unitOfWork);next = beginWork$$1(current$$1, unitOfWork, renderExpirationTime);stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);} else {next = beginWork$$1(current$$1, unitOfWork, renderExpirationTime);}resetCurrentFiber();unitOfWork.memoizedProps = unitOfWork.pendingProps;if (next === null) {// If this doesn't spawn new work, complete the current work.next = completeUnitOfWork(unitOfWork);}ReactCurrentOwner$2.current = null;return next;}
