行数
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 |
// 默认的时候 undefined
var root = container._reactRootContainer;
// fiber [faɪbə] 构造的意思
var fiberRoot = void 0;
if (!root) {
root = container._reactRootContainer =
legacyCreateRootFromDOMContainer(container, forceHydrate);
fiberRoot = root._internalRoot; // 将创建好的FiberRootNode赋值给fiberRoot
if (typeof callback === 'function') {
var originalCallback = callback;
callback = function () {
var instance = getPublicRootInstance(fiberRoot);
originalCallback.call(instance);
};
}
unbatchedUpdates(function () {
// children ReactElements
// fiberRoot FiberRootNode
// parentComponent undefined
// callback undefined
updateContainer(children, fiberRoot, parentComponent, callback);
});
} else {
// ...
}
行数:21820
此处注意 finally 中的 flushSyncCallbackQueue
function unbatchedUpdates(fn, a) {
// executionContext 初始值是0
// prevExecutionContext = 0
var prevExecutionContext = executionContext;
// 位运算
// 初始化时 executionContext = 0 & ~1 = 0
executionContext = executionContext & ~BatchedContext;
// 初始化时 executionContext = 0 | 8 = 8
executionContext = executionContext | LegacyUnbatchedContext;
try {
// 初始化时 a = undefined
return fn(a);
} finally {
// 恢复executionContext的值
// 初始化时,executionContext = prevExecutionContext = 0
executionContext = prevExecutionContext;
// NoContext 初始值是 0
if (executionContext === NoContext) {
flushSyncCallbackQueue();
}
}
}
function updateContainer(element, container, parentComponent, callback) {
// FiberRootNode.current FiberNode
// 取出定义好的当前的FiberNode
// container 等于 FiberRootNode
var current$$1 = container.current;
// 例子 1073711812
var currentTime = requestCurrentTime();
{
// jest没有赋值的地方,应该是作者打的一个与debug有关的标志
if ('undefined' !== typeof jest) {
warnIfUnmockedScheduler(current$$1);
warnIfNotScopedWithMatchingAct(current$$1);
}
}
// 初始化时 requestCurrentSuspenseConfig() return 了 null
// suspenseConfig = null;
var suspenseConfig = requestCurrentSuspenseConfig();
// 初始化时 expirationTime = 1073741823
var expirationTime = computeExpirationForFiber(currentTime, current$$1, suspenseConfig);
// 初始化时,入参如下
// element = ReactElements
// container = DOMElement
// parentComponent = null
// expirationTime = 常量 1073741823
// suspenseConfig = null
// callback = undefined
return updateContainerAtExpirationTime(element, container,
parentComponent, expirationTime, suspenseConfig, callback);
}
var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig;
function requestCurrentSuspenseConfig() {
// 初始化时 ReactCurrentBatchConfig.suspense 值 为null
return ReactCurrentBatchConfig.suspense;
}
function requestCurrentTime() {
// 初始化时,(8 & (16 | 32)) !== 0 结果 false
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
return msToExpirationTime(now());
}
// 初始化时 0 !== 0 返回 false
if (currentEventTime !== NoWork) {
return currentEventTime;
}
currentEventTime = msToExpirationTime(now());
// 例子 currentEventTime = 1073711812
return currentEventTime;
}
/**
* 1个到期时间单位表示10毫秒。
*/
function msToExpirationTime(ms) {
// 例子 ms = 300098.8250000082
// 总是加一个偏移量,这样我们就不会和现在的数字冲突。
// 默认值 MAGIC_NUMBER_OFFSET =
// (Batched = (Sync = MAX_SIGNED_31_BIT_INT = 1073741823) - 1) - 1
// MAGIC_NUMBER_OFFSET = 1073741821
// UNIT_SIZE = 10
return MAGIC_NUMBER_OFFSET - (ms / UNIT_SIZE | 0);
}
var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var _ReactInternals$Sched = ReactInternals$1.Scheduler;
var unstable_now = _ReactInternals$Sched.unstable_now;
var Scheduler_now = unstable_now;
var now = initialTimeMs < 10000 ? Scheduler_now : function () {
// Scheduler_now 代码在React.js 2276行
return Scheduler_now() - initialTimeMs;
};
// 以下这段代码在React.js中
var getCurrentTime = void 0;
getCurrentTime = function () {
return Date.now();
}
getCurrentTime = typeof performance === 'object' && typeof performance.now === 'function' ? function () {
return performance.now();
} : function () {
return _Date.now();
};
// 初始化调用时
// currentTime = 1073740102
// fiber = FiberNode
// suspenseConfig = null
function computeExpirationForFiber(currentTime, fiber, suspenseConfig) {
// 初始化时 fiber.mode = 0
var mode = fiber.mode;
// 0 & 2 === 0 结果true
if ((mode & BatchedMode) === NoMode) {
// 返回常量值 1073741823
return Sync;
}
var priorityLevel = getCurrentPriorityLevel();
if ((mode & ConcurrentMode) === NoMode) {
return priorityLevel === ImmediatePriority ? Sync : Batched;
}
if ((executionContext & RenderContext) !== NoContext) {
// Use whatever time we're already rendering
return renderExpirationTime;
}
var expirationTime = void 0;
if (suspenseConfig !== null) {
// Compute an expiration time based on the Suspense timeout.
expirationTime = computeSuspenseExpiration(currentTime, suspenseConfig.timeoutMs | 0 || LOW_PRIORITY_EXPIRATION);
} else {
// Compute an expiration time based on the Scheduler priority.
switch (priorityLevel) {
case ImmediatePriority:
expirationTime = Sync;
break;
case UserBlockingPriority$2:
// TODO: Rename this to computeUserBlockingExpiration
expirationTime = computeInteractiveExpiration(currentTime);
break;
case NormalPriority:
case LowPriority:
// TODO: Handle LowPriority
// TODO: Rename this to... something better.
expirationTime = computeAsyncExpiration(currentTime);
break;
case IdlePriority:
expirationTime = Never;
break;
default:
(function () {
{
{
throw ReactError(Error('Expected a valid priority level'));
}
}
})();
}
}
if (workInProgressRoot !== null && expirationTime === renderExpirationTime) {
// This is a trick to move this update into a separate batch
expirationTime -= 1;
}
return expirationTime;
}
行数 24462 updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, suspenseConfig, callback)
核心代码 scheduleRootUpdate 工作计划 [ˈskedʒuːl]
var ReactFiberInstrumentation = {
debugTool: null
};
var ReactFiberInstrumentation_1 = ReactFiberInstrumentation;
function updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, suspenseConfig, callback) {
// FiberNodo
var current$$1 = container.current;
{
// 初始化时 ReactFiberInstrumentation_1.debugTool = null
if (ReactFiberInstrumentation_1.debugTool) {
if (current$$1.alternate === null) {
ReactFiberInstrumentation_1.debugTool.onMountContainer(container);
} else if (element === null) {
ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container);
} else {
ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container);
}
}
}
// 初始化时 parentComponent值 为null
// context = {}
var context = getContextForSubtree(parentComponent);
// 初始化时 container.context = null
if (container.context === null) {
container.context = context;
} else {
container.pendingContext = context;
}
// 初始化时,入参如下
// current$$1 = FiberNode
// element = ReactElements
// expirationTime = 常量 1073741823
// suspenseConfig = null
// callback = undefined
return scheduleRootUpdate(current$$1, element, expirationTime, suspenseConfig, callback);
}
var emptyContextObject = {};
{
Object.freeze(emptyContextObject);
}
// 初始化时,入参为null
function getContextForSubtree(parentComponent) {
if (!parentComponent) {
return emptyContextObject;
}
var fiber = get(parentComponent);
var parentContext = findCurrentUnmaskedContext(fiber);
if (fiber.tag === ClassComponent) {
var Component = fiber.type;
if (isContextProvider(Component)) {
return processChildContext(fiber, Component, parentContext);
}
}
return parentContext;
}
核心 24434 scheduleRootUpdate(current$$1, element, expirationTime, suspenseConfig, callback)
21526行 负责执行scheduleWork
function scheduleRootUpdate(current$$1, element, expirationTime, suspenseConfig, callback) {
{
if (phase === 'render' && current !== null && !didWarnAboutNestedUpdates) {
didWarnAboutNestedUpdates = true;
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');
}
}
var update = createUpdate(expirationTime, suspenseConfig);
update.payload = { element: element };
callback = callback === undefined ? null : callback;
if (callback !== null) {
!(typeof callback === 'function') ? warningWithoutStack$1(false, 'Render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback) : void 0;
update.callback = callback;
}
// revertPassiveEffectsChange 默认值 false
if (revertPassiveEffectsChange) {
flushPassiveEffects();
}
// enenqueue 排队,FiberNode
// 给FiberNode加上updateQueue属性
enqueueUpdate(current$$1, update);
// schedule [ˈskedʒuːl] 工作计划
// var scheduleWork = scheduleUpdateOnFiber;
scheduleWork(current$$1, expirationTime);
return expirationTime;
}
// expirationTime = 1073741823
// suspenseConfig = null
function createUpdate(expirationTime, suspenseConfig) {
var update = {
expirationTime: expirationTime,
suspenseConfig: suspenseConfig,
// UpdateState 常量值 0
tag: UpdateState,
payload: null,
callback: null,
next: null,
nextEffect: null
};
{
update.priority = getCurrentPriorityLevel();
}
return update;
}
function getCurrentPriorityLevel() {
switch (Scheduler_getCurrentPriorityLevel()) {
// Scheduler_ImmediatePriority = 1
case Scheduler_ImmediatePriority:
// ImmediatePriority = 99
return ImmediatePriority;
// Scheduler_UserBlockingPriority = 2
case Scheduler_UserBlockingPriority:
// UserBlockingPriority$2 = 98
return UserBlockingPriority$2;
// Scheduler_NormalPriority = 3
case Scheduler_NormalPriority:
// NormalPriority = 97
return NormalPriority;
// Scheduler_LowPriority = 4
case Scheduler_LowPriority:
// LowPriority = 96
return LowPriority;
// Scheduler_IdlePriority = 5
case Scheduler_IdlePriority:
// IdlePriority = 95
return IdlePriority;
default:
(function () {
{
{
throw ReactError(Error('Unknown priority level.'));
}
}
})();
}
}
// 此代码出处React.js
function unstable_getCurrentPriorityLevel () {
// currentPriorityLevel 默认值是3 是一个变量
return currentPriorityLevel;
}
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;
}
}