行数

https://github.com/a8397550/react-source-share/blob/master/default/react-dom-default.js

JavaScript 位运算符

位运算符工作于32位的数字上。任何数字操作都将转换为32位。结果会转换为 JavaScript 数字。

运算符 描述 例子 类似于 结果 十进制
& AND x = 5 & 1 0101 & 0001 0001 1
| OR x = 5 | 1 0101 | 0001 0101 5
~ 取反 x = ~ 5 ~0101 1010 -6
^ 异或 x = 5 ^ 1 0101 ^ 0001 0100 4
<< 左移 x = 5 << 1 0101 << 1 1010 10
>> 右移 x = 5 >> 1 0101 >> 1 0010 2
  1. // 默认的时候 undefined
  2. var root = container._reactRootContainer;
  3. // fiber [faɪbə] 构造的意思
  4. var fiberRoot = void 0;
  5. if (!root) {
  6. root = container._reactRootContainer =
  7. legacyCreateRootFromDOMContainer(container, forceHydrate);
  8. fiberRoot = root._internalRoot; // 将创建好的FiberRootNode赋值给fiberRoot
  9. if (typeof callback === 'function') {
  10. var originalCallback = callback;
  11. callback = function () {
  12. var instance = getPublicRootInstance(fiberRoot);
  13. originalCallback.call(instance);
  14. };
  15. }
  16. unbatchedUpdates(function () {
  17. // children ReactElements
  18. // fiberRoot FiberRootNode
  19. // parentComponent undefined
  20. // callback undefined
  21. updateContainer(children, fiberRoot, parentComponent, callback);
  22. });
  23. } else {
  24. // ...
  25. }

行数:21820
此处注意 finally 中的 flushSyncCallbackQueue

  1. function unbatchedUpdates(fn, a) {
  2. // executionContext 初始值是0
  3. // prevExecutionContext = 0
  4. var prevExecutionContext = executionContext;
  5. // 位运算
  6. // 初始化时 executionContext = 0 & ~1 = 0
  7. executionContext = executionContext & ~BatchedContext;
  8. // 初始化时 executionContext = 0 | 8 = 8
  9. executionContext = executionContext | LegacyUnbatchedContext;
  10. try {
  11. // 初始化时 a = undefined
  12. return fn(a);
  13. } finally {
  14. // 恢复executionContext的值
  15. // 初始化时,executionContext = prevExecutionContext = 0
  16. executionContext = prevExecutionContext;
  17. // NoContext 初始值是 0
  18. if (executionContext === NoContext) {
  19. flushSyncCallbackQueue();
  20. }
  21. }
  22. }
  23. function updateContainer(element, container, parentComponent, callback) {
  24. // FiberRootNode.current FiberNode
  25. // 取出定义好的当前的FiberNode
  26. // container 等于 FiberRootNode
  27. var current$$1 = container.current;
  28. // 例子 1073711812
  29. var currentTime = requestCurrentTime();
  30. {
  31. // jest没有赋值的地方,应该是作者打的一个与debug有关的标志
  32. if ('undefined' !== typeof jest) {
  33. warnIfUnmockedScheduler(current$$1);
  34. warnIfNotScopedWithMatchingAct(current$$1);
  35. }
  36. }
  37. // 初始化时 requestCurrentSuspenseConfig() return 了 null
  38. // suspenseConfig = null;
  39. var suspenseConfig = requestCurrentSuspenseConfig();
  40. // 初始化时 expirationTime = 1073741823
  41. var expirationTime = computeExpirationForFiber(currentTime, current$$1, suspenseConfig);
  42. // 初始化时,入参如下
  43. // element = ReactElements
  44. // container = DOMElement
  45. // parentComponent = null
  46. // expirationTime = 常量 1073741823
  47. // suspenseConfig = null
  48. // callback = undefined
  49. return updateContainerAtExpirationTime(element, container,
  50. parentComponent, expirationTime, suspenseConfig, callback);
  51. }
  52. var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
  53. var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig;
  54. function requestCurrentSuspenseConfig() {
  55. // 初始化时 ReactCurrentBatchConfig.suspense 值 为null
  56. return ReactCurrentBatchConfig.suspense;
  57. }
  58. function requestCurrentTime() {
  59. // 初始化时,(8 & (16 | 32)) !== 0 结果 false
  60. if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
  61. return msToExpirationTime(now());
  62. }
  63. // 初始化时 0 !== 0 返回 false
  64. if (currentEventTime !== NoWork) {
  65. return currentEventTime;
  66. }
  67. currentEventTime = msToExpirationTime(now());
  68. // 例子 currentEventTime = 1073711812
  69. return currentEventTime;
  70. }
  71. /**
  72. * 1个到期时间单位表示10毫秒。
  73. */
  74. function msToExpirationTime(ms) {
  75. // 例子 ms = 300098.8250000082
  76. // 总是加一个偏移量,这样我们就不会和现在的数字冲突。
  77. // 默认值 MAGIC_NUMBER_OFFSET =
  78. // (Batched = (Sync = MAX_SIGNED_31_BIT_INT = 1073741823) - 1) - 1
  79. // MAGIC_NUMBER_OFFSET = 1073741821
  80. // UNIT_SIZE = 10
  81. return MAGIC_NUMBER_OFFSET - (ms / UNIT_SIZE | 0);
  82. }
  83. var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
  84. var _ReactInternals$Sched = ReactInternals$1.Scheduler;
  85. var unstable_now = _ReactInternals$Sched.unstable_now;
  86. var Scheduler_now = unstable_now;
  87. var now = initialTimeMs < 10000 ? Scheduler_now : function () {
  88. // Scheduler_now 代码在React.js 2276行
  89. return Scheduler_now() - initialTimeMs;
  90. };
  91. // 以下这段代码在React.js中
  92. var getCurrentTime = void 0;
  93. getCurrentTime = function () {
  94. return Date.now();
  95. }
  96. getCurrentTime = typeof performance === 'object' && typeof performance.now === 'function' ? function () {
  97. return performance.now();
  98. } : function () {
  99. return _Date.now();
  100. };
  1. // 初始化调用时
  2. // currentTime = 1073740102
  3. // fiber = FiberNode
  4. // suspenseConfig = null
  5. function computeExpirationForFiber(currentTime, fiber, suspenseConfig) {
  6. // 初始化时 fiber.mode = 0
  7. var mode = fiber.mode;
  8. // 0 & 2 === 0 结果true
  9. if ((mode & BatchedMode) === NoMode) {
  10. // 返回常量值 1073741823
  11. return Sync;
  12. }
  13. var priorityLevel = getCurrentPriorityLevel();
  14. if ((mode & ConcurrentMode) === NoMode) {
  15. return priorityLevel === ImmediatePriority ? Sync : Batched;
  16. }
  17. if ((executionContext & RenderContext) !== NoContext) {
  18. // Use whatever time we're already rendering
  19. return renderExpirationTime;
  20. }
  21. var expirationTime = void 0;
  22. if (suspenseConfig !== null) {
  23. // Compute an expiration time based on the Suspense timeout.
  24. expirationTime = computeSuspenseExpiration(currentTime, suspenseConfig.timeoutMs | 0 || LOW_PRIORITY_EXPIRATION);
  25. } else {
  26. // Compute an expiration time based on the Scheduler priority.
  27. switch (priorityLevel) {
  28. case ImmediatePriority:
  29. expirationTime = Sync;
  30. break;
  31. case UserBlockingPriority$2:
  32. // TODO: Rename this to computeUserBlockingExpiration
  33. expirationTime = computeInteractiveExpiration(currentTime);
  34. break;
  35. case NormalPriority:
  36. case LowPriority:
  37. // TODO: Handle LowPriority
  38. // TODO: Rename this to... something better.
  39. expirationTime = computeAsyncExpiration(currentTime);
  40. break;
  41. case IdlePriority:
  42. expirationTime = Never;
  43. break;
  44. default:
  45. (function () {
  46. {
  47. {
  48. throw ReactError(Error('Expected a valid priority level'));
  49. }
  50. }
  51. })();
  52. }
  53. }
  54. if (workInProgressRoot !== null && expirationTime === renderExpirationTime) {
  55. // This is a trick to move this update into a separate batch
  56. expirationTime -= 1;
  57. }
  58. return expirationTime;
  59. }

行数 24462 updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, suspenseConfig, callback)

核心代码 scheduleRootUpdate 工作计划 [ˈskedʒuːl]

  1. var ReactFiberInstrumentation = {
  2. debugTool: null
  3. };
  4. var ReactFiberInstrumentation_1 = ReactFiberInstrumentation;
  5. function updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, suspenseConfig, callback) {
  6. // FiberNodo
  7. var current$$1 = container.current;
  8. {
  9. // 初始化时 ReactFiberInstrumentation_1.debugTool = null
  10. if (ReactFiberInstrumentation_1.debugTool) {
  11. if (current$$1.alternate === null) {
  12. ReactFiberInstrumentation_1.debugTool.onMountContainer(container);
  13. } else if (element === null) {
  14. ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container);
  15. } else {
  16. ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container);
  17. }
  18. }
  19. }
  20. // 初始化时 parentComponent值 为null
  21. // context = {}
  22. var context = getContextForSubtree(parentComponent);
  23. // 初始化时 container.context = null
  24. if (container.context === null) {
  25. container.context = context;
  26. } else {
  27. container.pendingContext = context;
  28. }
  29. // 初始化时,入参如下
  30. // current$$1 = FiberNode
  31. // element = ReactElements
  32. // expirationTime = 常量 1073741823
  33. // suspenseConfig = null
  34. // callback = undefined
  35. return scheduleRootUpdate(current$$1, element, expirationTime, suspenseConfig, callback);
  36. }
  37. var emptyContextObject = {};
  38. {
  39. Object.freeze(emptyContextObject);
  40. }
  41. // 初始化时,入参为null
  42. function getContextForSubtree(parentComponent) {
  43. if (!parentComponent) {
  44. return emptyContextObject;
  45. }
  46. var fiber = get(parentComponent);
  47. var parentContext = findCurrentUnmaskedContext(fiber);
  48. if (fiber.tag === ClassComponent) {
  49. var Component = fiber.type;
  50. if (isContextProvider(Component)) {
  51. return processChildContext(fiber, Component, parentContext);
  52. }
  53. }
  54. return parentContext;
  55. }

核心 24434 scheduleRootUpdate(current$$1, element, expirationTime, suspenseConfig, callback)

21526行 负责执行scheduleWork

  1. function scheduleRootUpdate(current$$1, element, expirationTime, suspenseConfig, callback) {
  2. {
  3. if (phase === 'render' && current !== null && !didWarnAboutNestedUpdates) {
  4. didWarnAboutNestedUpdates = true;
  5. warningWithoutStack$1(false, 'Render methods should be a pure function of props and state; ' + 'triggering nested component updates from Render is not allowed. ' + 'If necessary, trigger nested updates in componentDidUpdate.\n\n' + 'Check the Render method of %s.', getComponentName(current.type) || 'Unknown');
  6. }
  7. }
  8. var update = createUpdate(expirationTime, suspenseConfig);
  9. update.payload = { element: element };
  10. callback = callback === undefined ? null : callback;
  11. if (callback !== null) {
  12. !(typeof callback === 'function') ? warningWithoutStack$1(false, 'Render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback) : void 0;
  13. update.callback = callback;
  14. }
  15. // revertPassiveEffectsChange 默认值 false
  16. if (revertPassiveEffectsChange) {
  17. flushPassiveEffects();
  18. }
  19. // enenqueue 排队,FiberNode
  20. // 给FiberNode加上updateQueue属性
  21. enqueueUpdate(current$$1, update);
  22. // schedule [ˈskedʒuːl] 工作计划
  23. // var scheduleWork = scheduleUpdateOnFiber;
  24. scheduleWork(current$$1, expirationTime);
  25. return expirationTime;
  26. }
  27. // expirationTime = 1073741823
  28. // suspenseConfig = null
  29. function createUpdate(expirationTime, suspenseConfig) {
  30. var update = {
  31. expirationTime: expirationTime,
  32. suspenseConfig: suspenseConfig,
  33. // UpdateState 常量值 0
  34. tag: UpdateState,
  35. payload: null,
  36. callback: null,
  37. next: null,
  38. nextEffect: null
  39. };
  40. {
  41. update.priority = getCurrentPriorityLevel();
  42. }
  43. return update;
  44. }
  45. function getCurrentPriorityLevel() {
  46. switch (Scheduler_getCurrentPriorityLevel()) {
  47. // Scheduler_ImmediatePriority = 1
  48. case Scheduler_ImmediatePriority:
  49. // ImmediatePriority = 99
  50. return ImmediatePriority;
  51. // Scheduler_UserBlockingPriority = 2
  52. case Scheduler_UserBlockingPriority:
  53. // UserBlockingPriority$2 = 98
  54. return UserBlockingPriority$2;
  55. // Scheduler_NormalPriority = 3
  56. case Scheduler_NormalPriority:
  57. // NormalPriority = 97
  58. return NormalPriority;
  59. // Scheduler_LowPriority = 4
  60. case Scheduler_LowPriority:
  61. // LowPriority = 96
  62. return LowPriority;
  63. // Scheduler_IdlePriority = 5
  64. case Scheduler_IdlePriority:
  65. // IdlePriority = 95
  66. return IdlePriority;
  67. default:
  68. (function () {
  69. {
  70. {
  71. throw ReactError(Error('Unknown priority level.'));
  72. }
  73. }
  74. })();
  75. }
  76. }
  77. // 此代码出处React.js
  78. function unstable_getCurrentPriorityLevel () {
  79. // currentPriorityLevel 默认值是3 是一个变量
  80. return currentPriorityLevel;
  81. }
function enqueueUpdate(fiber, update) {
  // 更新队列是惰性创建的
  // fiber.alternate 默认为 null
  var alternate = fiber.alternate;
  var queue1 = void 0;
  var queue2 = void 0;
  if (alternate === null) {
    // fiber.updateQueue 默认为 null
    queue1 = fiber.updateQueue;
    queue2 = null;
    if (queue1 === null) {
      // fiber.memoizedState 默认值为 null
      queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);
    }
  } else {
    // There are two owners.
    queue1 = fiber.updateQueue;
    queue2 = alternate.updateQueue;
    if (queue1 === null) {
      if (queue2 === null) {
        // Neither fiber has an update queue. Create new ones.
        queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);
        queue2 = alternate.updateQueue = createUpdateQueue(alternate.memoizedState);
      } else {
        // Only one fiber has an update queue. Clone to create a new one.
        queue1 = fiber.updateQueue = cloneUpdateQueue(queue2);
      }
    } else {
      if (queue2 === null) {
        // Only one fiber has an update queue. Clone to create a new one.
        queue2 = alternate.updateQueue = cloneUpdateQueue(queue1);
      } else {
        // Both owners have an update queue.
      }
    }
  }

  // 初始化时 queue2 = null || queue1 = {...}
  if (queue2 === null || queue1 === queue2) {
    appendUpdateToQueue(queue1, update);
  } else {
    // There are two queues. We need to append the update to both queues,
    // while accounting for the persistent structure of the list — we don't
    // want the same update to be added multiple times.
    if (queue1.lastUpdate === null || queue2.lastUpdate === null) {
      // One of the queues is not empty. We must add the update to both queues.
      appendUpdateToQueue(queue1, update);
      appendUpdateToQueue(queue2, update);
    } else {
      // Both queues are non-empty. The last update is the same in both lists,
      // because of structural sharing. So, only append to one of the lists.
      appendUpdateToQueue(queue1, update);
      // But we still need to update the `lastUpdate` pointer of queue2.
      queue2.lastUpdate = update;
    }
  }

  {
    // fiber.tag = 3 
    // ClassComponent = 1
    // currentlyProcessingQueue 默认值为 null
    // didWarnUpdateInsideUpdate = false
    // queue2 = null
    if (fiber.tag === ClassComponent && (currentlyProcessingQueue === queue1 ||
      queue2 !== null && currentlyProcessingQueue === queue2) &&
      !didWarnUpdateInsideUpdate) {

      warningWithoutStack$1(false, 'An update (setState, replaceState, or forceUpdate) was scheduled ' + 'from inside an update function. Update functions should be pure, ' + 'with zero side-effects. Consider using componentDidUpdate or a ' + 'callback.');
      didWarnUpdateInsideUpdate = true;
    }
  }
}

function createUpdateQueue(baseState) {
  var queue = {
    baseState: baseState,
    firstUpdate: null,
    lastUpdate: null,
    firstCapturedUpdate: null,
    lastCapturedUpdate: null,
    firstEffect: null,
    lastEffect: null,
    firstCapturedEffect: null,
    lastCapturedEffect: null
  };
  return queue;
}

function appendUpdateToQueue(queue, update) {
  // 初始化时 queue.lastUpdate = null
  if (queue.lastUpdate === null) {
    // Queue is empty
    queue.firstUpdate = queue.lastUpdate = update;
  } else {
    queue.lastUpdate.next = update;
    queue.lastUpdate = update;
  }
}