renderRoot 调用 workLoopSync()
function workLoopSync() {
// workInProgress = FiberNode
while (workInProgress !== null) {
workInProgress = performUnitOfWork(workInProgress);
}
}
performUnitOfWork
function performUnitOfWork(unitOfWork) {
var current$$1 = unitOfWork.alternate;
// startWorkTimer(unitOfWork) 初始化时 啥也没干
startWorkTimer(unitOfWork);
// 赋值了些什么
setCurrentFiber(unitOfWork);
var next = void 0;
// enableProfilerTimer = true && (0 & 8) = 0 !== NoMode = 0
// 此条件返回false
if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {
startProfilerTimer(unitOfWork);
next = beginWork$$1(current$$1, unitOfWork, renderExpirationTime);
stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
} else {
// renderExpirationTime = 1073741823
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;
}
updateHostRoot 重要
function updateHostRoot(current$$1, workInProgress, renderExpirationTime) {
pushHostRootContext(workInProgress);
var updateQueue = workInProgress.updateQueue;
(function () {
if (!(updateQueue !== null)) {
{
throw ReactError(Error('If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue.'));
}
}
})();
var nextProps = workInProgress.pendingProps;
var prevState = workInProgress.memoizedState;
var prevChildren = prevState !== null ? prevState.element : null;
processUpdateQueue(workInProgress, updateQueue, nextProps, null, renderExpirationTime);
var nextState = workInProgress.memoizedState;
// Caution: React DevTools currently depends on this property
// being called "element".
var nextChildren = nextState.element;
if (nextChildren === prevChildren) {
// If the state is the same as before, that's a bailout because we had
// no work that expires at this time.
resetHydrationState();
return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
}
var root = workInProgress.stateNode;
if ((current$$1 === null || current$$1.child === null) && root.hydrate && enterHydrationState(workInProgress)) {
// If we don't have any current children this might be the first pass.
// We always try to hydrate. If this isn't a hydration pass there won't
// be any children to hydrate which is effectively the same thing as
// not hydrating.
// This is a bit of a hack. We track the host root as a placement to
// know that we're currently in a mounting state. That way isMounted
// works as expected. We must reset this before committing.
// TODO: Delete this when we delete isMounted and findDOMNode.
workInProgress.effectTag |= Placement;
// Ensure that children mount into this root without tracking
// side-effects. This ensures that we don't store Placement effects on
// nodes that will be hydrated.
workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
} else {
// Otherwise reset hydration state in case we aborted and resumed another
// root.
reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
resetHydrationState();
}
return workInProgress.child;
}
beginWork$$1
beginWork$$1 = function (current$$1, unitOfWork, expirationTime) {
var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork);
try {
// current$$1 初始化创建的 FiberNode
// unitOfWork 是 workInProgress
// renderExpirationTime = 1073741823
return beginWork$1(current$$1, unitOfWork, expirationTime);
} catch (originalError) {
if (originalError !== null && typeof originalError === 'object' && typeof originalError.then === 'function') {
// Don't replay promises. Treat everything else like an error.
throw originalError;
}
// Keep this code in sync with renderRoot; any changes here must have
// corresponding changes there.
resetContextDependencies();
resetHooks();
// Unwind the failed stack frame
unwindInterruptedWork(unitOfWork);
// Restore the original properties of the fiber.
assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);
if (enableProfilerTimer && unitOfWork.mode & ProfileMode) {
// Reset the profiler timer.
startProfilerTimer(unitOfWork);
}
// Run beginWork again.
invokeGuardedCallback(null, beginWork$1, null, current$$1, unitOfWork, expirationTime);
if (hasCaughtError()) {
var replayError = clearCaughtError();
// `InvokeGuardedCallback` sometimes sets an expando `_suppressLogging`.
// Rethrow this error instead of the original one.
throw replayError;
} else {
throw originalError;
}
}
};
beginWork$1
function beginWork$1(current$$1, workInProgress, renderExpirationTime) {
// current$$1 初始化创建的 FiberNode
// unitOfWork 是 workInProgress
// renderExpirationTime = 1073741823
// workInProgress.expirationTime = 1073741823
var updateExpirationTime = workInProgress.expirationTime;
{
// workInProgress._debugNeedsRemount = false
if (workInProgress._debugNeedsRemount && current$$1 !== null) {
// This will restart the begin phase with a new fiber.
return remountFiber(current$$1, workInProgress,
createFiberFromTypeAndProps(workInProgress.type,
workInProgress.key, workInProgress.pendingProps,
workInProgress._debugOwner || null,
workInProgress.mode,
workInProgress.expirationTime));
}
}
if (current$$1 !== null) {
// current$$1.memoizedProps = null;
// workInProgress.pendingProps = null;
var oldProps = current$$1.memoizedProps;
var newProps = workInProgress.pendingProps;
function hasContextChanged() {
// disableLegacyContext = false;
if (disableLegacyContext) {
return false;
} else {
// didPerformWorkStackCursor.current = false;
return didPerformWorkStackCursor.current;
}
}
if (oldProps !== newProps || hasContextChanged() || (
// workInProgress.type = null !== current$$1.type null 返回 false
workInProgress.type !== current$$1.type)) {
didReceiveUpdate = true;
}
// updateExpirationTime = 1073741823 < renderExpirationTime = 1073741823
// if 结果为false
else if (updateExpirationTime < renderExpirationTime) {
// ...省略
}
} else {
didReceiveUpdate = false;
}
// 常量 NoWork = 0
workInProgress.expirationTime = NoWork;
switch (workInProgress.tag) {
case IndeterminateComponent: // 2
{
return mountIndeterminateComponent(current$$1, workInProgress, workInProgress.type, renderExpirationTime);
}
case LazyComponent: // 16
{
var elementType = workInProgress.elementType;
return mountLazyComponent(current$$1, workInProgress, elementType, updateExpirationTime, renderExpirationTime);
}
case FunctionComponent: // 0
{
var _Component = workInProgress.type;
var unresolvedProps = workInProgress.pendingProps;
var resolvedProps = workInProgress.elementType === _Component ? unresolvedProps : resolveDefaultProps(_Component, unresolvedProps);
return updateFunctionComponent(current$$1, workInProgress, _Component, resolvedProps, renderExpirationTime);
}
case ClassComponent: // 1
{
var _Component2 = workInProgress.type;
var _unresolvedProps = workInProgress.pendingProps;
var _resolvedProps = workInProgress.elementType === _Component2 ? _unresolvedProps : resolveDefaultProps(_Component2, _unresolvedProps);
return updateClassComponent(current$$1, workInProgress, _Component2, _resolvedProps, renderExpirationTime);
}
case HostRoot: // 3
return updateHostRoot(current$$1, workInProgress, renderExpirationTime);
case HostComponent: // 5
return updateHostComponent(current$$1, workInProgress, renderExpirationTime);
case HostText: // 6
return updateHostText(current$$1, workInProgress);
case SuspenseComponent: // 13
return updateSuspenseComponent(current$$1, workInProgress, renderExpirationTime);
case HostPortal: // 4
return updatePortalComponent(current$$1, workInProgress, renderExpirationTime);
case ForwardRef: // 11
{
var type = workInProgress.type;
var _unresolvedProps2 = workInProgress.pendingProps;
var _resolvedProps2 = workInProgress.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2);
return updateForwardRef(current$$1, workInProgress, type, _resolvedProps2, renderExpirationTime);
}
case Fragment: // 7
return updateFragment(current$$1, workInProgress, renderExpirationTime);
case Mode: // 8
return updateMode(current$$1, workInProgress, renderExpirationTime);
case Profiler: // 12
return updateProfiler(current$$1, workInProgress, renderExpirationTime);
case ContextProvider: // 10
return updateContextProvider(current$$1, workInProgress, renderExpirationTime);
case ContextConsumer: // 9
return updateContextConsumer(current$$1, workInProgress, renderExpirationTime);
case MemoComponent: // 14
{
var _type2 = workInProgress.type;
var _unresolvedProps3 = workInProgress.pendingProps;
// Resolve outer props first, then resolve inner props.
var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3);
{
if (workInProgress.type !== workInProgress.elementType) {
var outerPropTypes = _type2.propTypes;
if (outerPropTypes) {
checkPropTypes_1(outerPropTypes, _resolvedProps3, // Resolved for outer only
'prop', getComponentName(_type2), getCurrentFiberStackInDev);
}
}
}
_resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3);
return updateMemoComponent(current$$1, workInProgress, _type2, _resolvedProps3, updateExpirationTime, renderExpirationTime);
}
case SimpleMemoComponent: // 15
{
return updateSimpleMemoComponent(current$$1, workInProgress, workInProgress.type, workInProgress.pendingProps, updateExpirationTime, renderExpirationTime);
}
case IncompleteClassComponent: // 17
{
var _Component3 = workInProgress.type;
var _unresolvedProps4 = workInProgress.pendingProps;
var _resolvedProps4 = workInProgress.elementType === _Component3 ? _unresolvedProps4 : resolveDefaultProps(_Component3, _unresolvedProps4);
return mountIncompleteClassComponent(current$$1, workInProgress, _Component3, _resolvedProps4, renderExpirationTime);
}
case DehydratedSuspenseComponent: // 18
{
if (enableSuspenseServerRenderer) {
return updateDehydratedSuspenseComponent(current$$1, workInProgress, renderExpirationTime);
}
break;
}
case SuspenseListComponent: // 19
{
return updateSuspenseListComponent(current$$1, workInProgress, renderExpirationTime);
}
case FundamentalComponent: // 20
{
if (enableFundamentalAPI) {
return updateFundamentalComponent$1(current$$1, workInProgress, renderExpirationTime);
}
break;
}
}
(function () {
{
{
throw ReactError(Error('Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.'));
}
}
})();
}
assignFiberPropertiesInDEV
function assignFiberPropertiesInDEV(target, source) {
if (target === null) {
target = createFiber(IndeterminateComponent, null, null, NoMode);
}
target.tag = source.tag;
target.key = source.key;
target.elementType = source.elementType;
target.type = source.type;
target.stateNode = source.stateNode;
target.return = source.return;
target.child = source.child;
target.sibling = source.sibling;
target.index = source.index;
target.ref = source.ref;
target.pendingProps = source.pendingProps;
target.memoizedProps = source.memoizedProps;
target.updateQueue = source.updateQueue;
target.memoizedState = source.memoizedState;
target.dependencies = source.dependencies;
target.mode = source.mode;
target.effectTag = source.effectTag;
target.nextEffect = source.nextEffect;
target.firstEffect = source.firstEffect;
target.lastEffect = source.lastEffect;
target.expirationTime = source.expirationTime;
target.childExpirationTime = source.childExpirationTime;
target.alternate = source.alternate;
if (enableProfilerTimer) {
target.actualDuration = source.actualDuration;
target.actualStartTime = source.actualStartTime;
target.selfBaseDuration = source.selfBaseDuration;
target.treeBaseDuration = source.treeBaseDuration;
}
target._debugID = source._debugID;
target._debugSource = source._debugSource;
target._debugOwner = source._debugOwner;
target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming;
target._debugNeedsRemount = source._debugNeedsRemount;
target._debugHookTypes = source._debugHookTypes;
return target;
}
setCurrentFiber
function setCurrentFiber(fiber) {
{
// typeof getCurrentFiberStackInDev === 'function'
ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackInDev;
current = fiber;
phase = null;
}
}
startWorkTimer
var shouldIgnoreFiber = function (fiber) {
// fiber.tag = 3
switch (fiber.tag) {
case HostRoot: // 3
case HostComponent: // 5
case HostText: // 6
case HostPortal: // 4
case Fragment: // 7
case ContextProvider: // 10
case ContextConsumer: // 9
case Mode: // 8
return true;
default:
return false;
}
};
function startWorkTimer(fiber) {
// enableUserTimingAPI = true
if (enableUserTimingAPI) {
// supportsUserTiming = true
// shouldIgnoreFiber(fiber) 返回 true
if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
return;
}
// If we pause, this is the fiber to unwind from.
currentFiber = fiber;
if (!beginFiberMark(fiber, null)) {
return;
}
fiber._debugIsCurrentlyTiming = true;
}
}