renderRoot 调用 workLoopSync()

  1. function workLoopSync() {
  2. // workInProgress = FiberNode
  3. while (workInProgress !== null) {
  4. workInProgress = performUnitOfWork(workInProgress);
  5. }
  6. }

performUnitOfWork

  1. function performUnitOfWork(unitOfWork) {
  2. var current$$1 = unitOfWork.alternate;
  3. // startWorkTimer(unitOfWork) 初始化时 啥也没干
  4. startWorkTimer(unitOfWork);
  5. // 赋值了些什么
  6. setCurrentFiber(unitOfWork);
  7. var next = void 0;
  8. // enableProfilerTimer = true && (0 & 8) = 0 !== NoMode = 0
  9. // 此条件返回false
  10. if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {
  11. startProfilerTimer(unitOfWork);
  12. next = beginWork$$1(current$$1, unitOfWork, renderExpirationTime);
  13. stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
  14. } else {
  15. // renderExpirationTime = 1073741823
  16. next = beginWork$$1(current$$1, unitOfWork, renderExpirationTime);
  17. }
  18. resetCurrentFiber();
  19. unitOfWork.memoizedProps = unitOfWork.pendingProps;
  20. if (next === null) {
  21. // If this doesn't spawn new work, complete the current work.
  22. next = completeUnitOfWork(unitOfWork);
  23. }
  24. ReactCurrentOwner$2.current = null;
  25. return next;
  26. }

updateHostRoot 重要

  1. function updateHostRoot(current$$1, workInProgress, renderExpirationTime) {
  2. pushHostRootContext(workInProgress);
  3. var updateQueue = workInProgress.updateQueue;
  4. (function () {
  5. if (!(updateQueue !== null)) {
  6. {
  7. 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.'));
  8. }
  9. }
  10. })();
  11. var nextProps = workInProgress.pendingProps;
  12. var prevState = workInProgress.memoizedState;
  13. var prevChildren = prevState !== null ? prevState.element : null;
  14. processUpdateQueue(workInProgress, updateQueue, nextProps, null, renderExpirationTime);
  15. var nextState = workInProgress.memoizedState;
  16. // Caution: React DevTools currently depends on this property
  17. // being called "element".
  18. var nextChildren = nextState.element;
  19. if (nextChildren === prevChildren) {
  20. // If the state is the same as before, that's a bailout because we had
  21. // no work that expires at this time.
  22. resetHydrationState();
  23. return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
  24. }
  25. var root = workInProgress.stateNode;
  26. if ((current$$1 === null || current$$1.child === null) && root.hydrate && enterHydrationState(workInProgress)) {
  27. // If we don't have any current children this might be the first pass.
  28. // We always try to hydrate. If this isn't a hydration pass there won't
  29. // be any children to hydrate which is effectively the same thing as
  30. // not hydrating.
  31. // This is a bit of a hack. We track the host root as a placement to
  32. // know that we're currently in a mounting state. That way isMounted
  33. // works as expected. We must reset this before committing.
  34. // TODO: Delete this when we delete isMounted and findDOMNode.
  35. workInProgress.effectTag |= Placement;
  36. // Ensure that children mount into this root without tracking
  37. // side-effects. This ensures that we don't store Placement effects on
  38. // nodes that will be hydrated.
  39. workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
  40. } else {
  41. // Otherwise reset hydration state in case we aborted and resumed another
  42. // root.
  43. reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
  44. resetHydrationState();
  45. }
  46. return workInProgress.child;
  47. }

beginWork$$1

  1. beginWork$$1 = function (current$$1, unitOfWork, expirationTime) {
  2. var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork);
  3. try {
  4. // current$$1 初始化创建的 FiberNode
  5. // unitOfWork 是 workInProgress
  6. // renderExpirationTime = 1073741823
  7. return beginWork$1(current$$1, unitOfWork, expirationTime);
  8. } catch (originalError) {
  9. if (originalError !== null && typeof originalError === 'object' && typeof originalError.then === 'function') {
  10. // Don't replay promises. Treat everything else like an error.
  11. throw originalError;
  12. }
  13. // Keep this code in sync with renderRoot; any changes here must have
  14. // corresponding changes there.
  15. resetContextDependencies();
  16. resetHooks();
  17. // Unwind the failed stack frame
  18. unwindInterruptedWork(unitOfWork);
  19. // Restore the original properties of the fiber.
  20. assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);
  21. if (enableProfilerTimer && unitOfWork.mode & ProfileMode) {
  22. // Reset the profiler timer.
  23. startProfilerTimer(unitOfWork);
  24. }
  25. // Run beginWork again.
  26. invokeGuardedCallback(null, beginWork$1, null, current$$1, unitOfWork, expirationTime);
  27. if (hasCaughtError()) {
  28. var replayError = clearCaughtError();
  29. // `InvokeGuardedCallback` sometimes sets an expando `_suppressLogging`.
  30. // Rethrow this error instead of the original one.
  31. throw replayError;
  32. } else {
  33. throw originalError;
  34. }
  35. }
  36. };

beginWork$1

  1. function beginWork$1(current$$1, workInProgress, renderExpirationTime) {
  2. // current$$1 初始化创建的 FiberNode
  3. // unitOfWork 是 workInProgress
  4. // renderExpirationTime = 1073741823
  5. // workInProgress.expirationTime = 1073741823
  6. var updateExpirationTime = workInProgress.expirationTime;
  7. {
  8. // workInProgress._debugNeedsRemount = false
  9. if (workInProgress._debugNeedsRemount && current$$1 !== null) {
  10. // This will restart the begin phase with a new fiber.
  11. return remountFiber(current$$1, workInProgress,
  12. createFiberFromTypeAndProps(workInProgress.type,
  13. workInProgress.key, workInProgress.pendingProps,
  14. workInProgress._debugOwner || null,
  15. workInProgress.mode,
  16. workInProgress.expirationTime));
  17. }
  18. }
  19. if (current$$1 !== null) {
  20. // current$$1.memoizedProps = null;
  21. // workInProgress.pendingProps = null;
  22. var oldProps = current$$1.memoizedProps;
  23. var newProps = workInProgress.pendingProps;
  24. function hasContextChanged() {
  25. // disableLegacyContext = false;
  26. if (disableLegacyContext) {
  27. return false;
  28. } else {
  29. // didPerformWorkStackCursor.current = false;
  30. return didPerformWorkStackCursor.current;
  31. }
  32. }
  33. if (oldProps !== newProps || hasContextChanged() || (
  34. // workInProgress.type = null !== current$$1.type null 返回 false
  35. workInProgress.type !== current$$1.type)) {
  36. didReceiveUpdate = true;
  37. }
  38. // updateExpirationTime = 1073741823 < renderExpirationTime = 1073741823
  39. // if 结果为false
  40. else if (updateExpirationTime < renderExpirationTime) {
  41. // ...省略
  42. }
  43. } else {
  44. didReceiveUpdate = false;
  45. }
  46. // 常量 NoWork = 0
  47. workInProgress.expirationTime = NoWork;
  48. switch (workInProgress.tag) {
  49. case IndeterminateComponent: // 2
  50. {
  51. return mountIndeterminateComponent(current$$1, workInProgress, workInProgress.type, renderExpirationTime);
  52. }
  53. case LazyComponent: // 16
  54. {
  55. var elementType = workInProgress.elementType;
  56. return mountLazyComponent(current$$1, workInProgress, elementType, updateExpirationTime, renderExpirationTime);
  57. }
  58. case FunctionComponent: // 0
  59. {
  60. var _Component = workInProgress.type;
  61. var unresolvedProps = workInProgress.pendingProps;
  62. var resolvedProps = workInProgress.elementType === _Component ? unresolvedProps : resolveDefaultProps(_Component, unresolvedProps);
  63. return updateFunctionComponent(current$$1, workInProgress, _Component, resolvedProps, renderExpirationTime);
  64. }
  65. case ClassComponent: // 1
  66. {
  67. var _Component2 = workInProgress.type;
  68. var _unresolvedProps = workInProgress.pendingProps;
  69. var _resolvedProps = workInProgress.elementType === _Component2 ? _unresolvedProps : resolveDefaultProps(_Component2, _unresolvedProps);
  70. return updateClassComponent(current$$1, workInProgress, _Component2, _resolvedProps, renderExpirationTime);
  71. }
  72. case HostRoot: // 3
  73. return updateHostRoot(current$$1, workInProgress, renderExpirationTime);
  74. case HostComponent: // 5
  75. return updateHostComponent(current$$1, workInProgress, renderExpirationTime);
  76. case HostText: // 6
  77. return updateHostText(current$$1, workInProgress);
  78. case SuspenseComponent: // 13
  79. return updateSuspenseComponent(current$$1, workInProgress, renderExpirationTime);
  80. case HostPortal: // 4
  81. return updatePortalComponent(current$$1, workInProgress, renderExpirationTime);
  82. case ForwardRef: // 11
  83. {
  84. var type = workInProgress.type;
  85. var _unresolvedProps2 = workInProgress.pendingProps;
  86. var _resolvedProps2 = workInProgress.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2);
  87. return updateForwardRef(current$$1, workInProgress, type, _resolvedProps2, renderExpirationTime);
  88. }
  89. case Fragment: // 7
  90. return updateFragment(current$$1, workInProgress, renderExpirationTime);
  91. case Mode: // 8
  92. return updateMode(current$$1, workInProgress, renderExpirationTime);
  93. case Profiler: // 12
  94. return updateProfiler(current$$1, workInProgress, renderExpirationTime);
  95. case ContextProvider: // 10
  96. return updateContextProvider(current$$1, workInProgress, renderExpirationTime);
  97. case ContextConsumer: // 9
  98. return updateContextConsumer(current$$1, workInProgress, renderExpirationTime);
  99. case MemoComponent: // 14
  100. {
  101. var _type2 = workInProgress.type;
  102. var _unresolvedProps3 = workInProgress.pendingProps;
  103. // Resolve outer props first, then resolve inner props.
  104. var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3);
  105. {
  106. if (workInProgress.type !== workInProgress.elementType) {
  107. var outerPropTypes = _type2.propTypes;
  108. if (outerPropTypes) {
  109. checkPropTypes_1(outerPropTypes, _resolvedProps3, // Resolved for outer only
  110. 'prop', getComponentName(_type2), getCurrentFiberStackInDev);
  111. }
  112. }
  113. }
  114. _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3);
  115. return updateMemoComponent(current$$1, workInProgress, _type2, _resolvedProps3, updateExpirationTime, renderExpirationTime);
  116. }
  117. case SimpleMemoComponent: // 15
  118. {
  119. return updateSimpleMemoComponent(current$$1, workInProgress, workInProgress.type, workInProgress.pendingProps, updateExpirationTime, renderExpirationTime);
  120. }
  121. case IncompleteClassComponent: // 17
  122. {
  123. var _Component3 = workInProgress.type;
  124. var _unresolvedProps4 = workInProgress.pendingProps;
  125. var _resolvedProps4 = workInProgress.elementType === _Component3 ? _unresolvedProps4 : resolveDefaultProps(_Component3, _unresolvedProps4);
  126. return mountIncompleteClassComponent(current$$1, workInProgress, _Component3, _resolvedProps4, renderExpirationTime);
  127. }
  128. case DehydratedSuspenseComponent: // 18
  129. {
  130. if (enableSuspenseServerRenderer) {
  131. return updateDehydratedSuspenseComponent(current$$1, workInProgress, renderExpirationTime);
  132. }
  133. break;
  134. }
  135. case SuspenseListComponent: // 19
  136. {
  137. return updateSuspenseListComponent(current$$1, workInProgress, renderExpirationTime);
  138. }
  139. case FundamentalComponent: // 20
  140. {
  141. if (enableFundamentalAPI) {
  142. return updateFundamentalComponent$1(current$$1, workInProgress, renderExpirationTime);
  143. }
  144. break;
  145. }
  146. }
  147. (function () {
  148. {
  149. {
  150. throw ReactError(Error('Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.'));
  151. }
  152. }
  153. })();
  154. }

assignFiberPropertiesInDEV

  1. function assignFiberPropertiesInDEV(target, source) {
  2. if (target === null) {
  3. target = createFiber(IndeterminateComponent, null, null, NoMode);
  4. }
  5. target.tag = source.tag;
  6. target.key = source.key;
  7. target.elementType = source.elementType;
  8. target.type = source.type;
  9. target.stateNode = source.stateNode;
  10. target.return = source.return;
  11. target.child = source.child;
  12. target.sibling = source.sibling;
  13. target.index = source.index;
  14. target.ref = source.ref;
  15. target.pendingProps = source.pendingProps;
  16. target.memoizedProps = source.memoizedProps;
  17. target.updateQueue = source.updateQueue;
  18. target.memoizedState = source.memoizedState;
  19. target.dependencies = source.dependencies;
  20. target.mode = source.mode;
  21. target.effectTag = source.effectTag;
  22. target.nextEffect = source.nextEffect;
  23. target.firstEffect = source.firstEffect;
  24. target.lastEffect = source.lastEffect;
  25. target.expirationTime = source.expirationTime;
  26. target.childExpirationTime = source.childExpirationTime;
  27. target.alternate = source.alternate;
  28. if (enableProfilerTimer) {
  29. target.actualDuration = source.actualDuration;
  30. target.actualStartTime = source.actualStartTime;
  31. target.selfBaseDuration = source.selfBaseDuration;
  32. target.treeBaseDuration = source.treeBaseDuration;
  33. }
  34. target._debugID = source._debugID;
  35. target._debugSource = source._debugSource;
  36. target._debugOwner = source._debugOwner;
  37. target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming;
  38. target._debugNeedsRemount = source._debugNeedsRemount;
  39. target._debugHookTypes = source._debugHookTypes;
  40. return target;
  41. }

setCurrentFiber

  1. function setCurrentFiber(fiber) {
  2. {
  3. // typeof getCurrentFiberStackInDev === 'function'
  4. ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackInDev;
  5. current = fiber;
  6. phase = null;
  7. }
  8. }

startWorkTimer

  1. var shouldIgnoreFiber = function (fiber) {
  2. // fiber.tag = 3
  3. switch (fiber.tag) {
  4. case HostRoot: // 3
  5. case HostComponent: // 5
  6. case HostText: // 6
  7. case HostPortal: // 4
  8. case Fragment: // 7
  9. case ContextProvider: // 10
  10. case ContextConsumer: // 9
  11. case Mode: // 8
  12. return true;
  13. default:
  14. return false;
  15. }
  16. };
  17. function startWorkTimer(fiber) {
  18. // enableUserTimingAPI = true
  19. if (enableUserTimingAPI) {
  20. // supportsUserTiming = true
  21. // shouldIgnoreFiber(fiber) 返回 true
  22. if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
  23. return;
  24. }
  25. // If we pause, this is the fiber to unwind from.
  26. currentFiber = fiber;
  27. if (!beginFiberMark(fiber, null)) {
  28. return;
  29. }
  30. fiber._debugIsCurrentlyTiming = true;
  31. }
  32. }