react-reconciler 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license React v16.
|
|
1
|
+
/** @license React v16.2.0
|
|
2
2
|
* react-reconciler.development.js
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) 2013-present, Facebook, Inc.
|
|
@@ -35,8 +35,6 @@ var shallowEqual = require('fbjs/lib/shallowEqual');
|
|
|
35
35
|
|
|
36
36
|
var enableAsyncSubtreeAPI = true;
|
|
37
37
|
|
|
38
|
-
// Exports React.Fragment
|
|
39
|
-
var enableReactFragment = false;
|
|
40
38
|
// Exports ReactDOM.createRoot
|
|
41
39
|
|
|
42
40
|
var enableUserTimingAPI = true;
|
|
@@ -48,6 +46,9 @@ var enableNoopReconciler = false;
|
|
|
48
46
|
// Experimental persistent mode (CS):
|
|
49
47
|
var enablePersistentReconciler = false;
|
|
50
48
|
|
|
49
|
+
// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
|
|
50
|
+
var debugRenderPhaseSideEffects = false;
|
|
51
|
+
|
|
51
52
|
// Only used in www builds.
|
|
52
53
|
|
|
53
54
|
/**
|
|
@@ -1135,6 +1136,10 @@ function msToExpirationTime(ms) {
|
|
|
1135
1136
|
return (ms / UNIT_SIZE | 0) + MAGIC_NUMBER_OFFSET;
|
|
1136
1137
|
}
|
|
1137
1138
|
|
|
1139
|
+
function expirationTimeToMs(expirationTime) {
|
|
1140
|
+
return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1138
1143
|
function ceiling(num, precision) {
|
|
1139
1144
|
return ((num / precision | 0) + 1) * precision;
|
|
1140
1145
|
}
|
|
@@ -1151,8 +1156,7 @@ var AsyncUpdates = 1;
|
|
|
1151
1156
|
try {
|
|
1152
1157
|
var nonExtensibleObject = Object.preventExtensions({});
|
|
1153
1158
|
/* eslint-disable no-new */
|
|
1154
|
-
|
|
1155
|
-
new Set([nonExtensibleObject]);
|
|
1159
|
+
|
|
1156
1160
|
/* eslint-enable no-new */
|
|
1157
1161
|
} catch (e) {
|
|
1158
1162
|
// TODO: Consider warning about bad polyfills
|
|
@@ -1795,6 +1799,12 @@ function getStateFromUpdate(update, instance, prevState, props) {
|
|
|
1795
1799
|
var partialState = update.partialState;
|
|
1796
1800
|
if (typeof partialState === 'function') {
|
|
1797
1801
|
var updateFn = partialState;
|
|
1802
|
+
|
|
1803
|
+
// Invoke setState callback an extra time to help detect side-effects.
|
|
1804
|
+
if (debugRenderPhaseSideEffects) {
|
|
1805
|
+
updateFn.call(instance, prevState, props);
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1798
1808
|
return updateFn.call(instance, prevState, props);
|
|
1799
1809
|
} else {
|
|
1800
1810
|
return partialState;
|
|
@@ -2040,6 +2050,11 @@ var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber
|
|
|
2040
2050
|
var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, newContext);
|
|
2041
2051
|
stopPhaseTimer();
|
|
2042
2052
|
|
|
2053
|
+
// Simulate an async bailout/interruption by invoking lifecycle twice.
|
|
2054
|
+
if (debugRenderPhaseSideEffects) {
|
|
2055
|
+
instance.shouldComponentUpdate(newProps, newState, newContext);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2043
2058
|
{
|
|
2044
2059
|
warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentName(workInProgress) || 'Unknown');
|
|
2045
2060
|
}
|
|
@@ -2096,10 +2111,10 @@ var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber
|
|
|
2096
2111
|
|
|
2097
2112
|
var state = instance.state;
|
|
2098
2113
|
if (state && (typeof state !== 'object' || isArray(state))) {
|
|
2099
|
-
|
|
2114
|
+
warning(false, '%s.state: must be set to an object or null', getComponentName(workInProgress));
|
|
2100
2115
|
}
|
|
2101
2116
|
if (typeof instance.getChildContext === 'function') {
|
|
2102
|
-
|
|
2117
|
+
warning(typeof workInProgress.type.childContextTypes === 'object', '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', getComponentName(workInProgress));
|
|
2103
2118
|
}
|
|
2104
2119
|
}
|
|
2105
2120
|
|
|
@@ -2139,9 +2154,13 @@ var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber
|
|
|
2139
2154
|
startPhaseTimer(workInProgress, 'componentWillMount');
|
|
2140
2155
|
var oldState = instance.state;
|
|
2141
2156
|
instance.componentWillMount();
|
|
2142
|
-
|
|
2143
2157
|
stopPhaseTimer();
|
|
2144
2158
|
|
|
2159
|
+
// Simulate an async bailout/interruption by invoking lifecycle twice.
|
|
2160
|
+
if (debugRenderPhaseSideEffects) {
|
|
2161
|
+
instance.componentWillMount();
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2145
2164
|
if (oldState !== instance.state) {
|
|
2146
2165
|
{
|
|
2147
2166
|
warning(false, '%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentName(workInProgress));
|
|
@@ -2156,6 +2175,11 @@ var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber
|
|
|
2156
2175
|
instance.componentWillReceiveProps(newProps, newContext);
|
|
2157
2176
|
stopPhaseTimer();
|
|
2158
2177
|
|
|
2178
|
+
// Simulate an async bailout/interruption by invoking lifecycle twice.
|
|
2179
|
+
if (debugRenderPhaseSideEffects) {
|
|
2180
|
+
instance.componentWillReceiveProps(newProps, newContext);
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2159
2183
|
if (instance.state !== oldState) {
|
|
2160
2184
|
{
|
|
2161
2185
|
var componentName = getComponentName(workInProgress) || 'Component';
|
|
@@ -2365,6 +2389,11 @@ var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber
|
|
|
2365
2389
|
startPhaseTimer(workInProgress, 'componentWillUpdate');
|
|
2366
2390
|
instance.componentWillUpdate(newProps, newState, newContext);
|
|
2367
2391
|
stopPhaseTimer();
|
|
2392
|
+
|
|
2393
|
+
// Simulate an async bailout/interruption by invoking lifecycle twice.
|
|
2394
|
+
if (debugRenderPhaseSideEffects) {
|
|
2395
|
+
instance.componentWillUpdate(newProps, newState, newContext);
|
|
2396
|
+
}
|
|
2368
2397
|
}
|
|
2369
2398
|
if (typeof instance.componentDidUpdate === 'function') {
|
|
2370
2399
|
workInProgress.effectTag |= Update;
|
|
@@ -2402,9 +2431,29 @@ var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber
|
|
|
2402
2431
|
};
|
|
2403
2432
|
};
|
|
2404
2433
|
|
|
2405
|
-
// The Symbol used to tag the
|
|
2434
|
+
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
|
|
2406
2435
|
// nor polyfill, then a plain number is used for performance.
|
|
2407
|
-
var
|
|
2436
|
+
var hasSymbol = typeof Symbol === 'function' && Symbol['for'];
|
|
2437
|
+
|
|
2438
|
+
var REACT_ELEMENT_TYPE = hasSymbol ? Symbol['for']('react.element') : 0xeac7;
|
|
2439
|
+
var REACT_CALL_TYPE = hasSymbol ? Symbol['for']('react.call') : 0xeac8;
|
|
2440
|
+
var REACT_RETURN_TYPE = hasSymbol ? Symbol['for']('react.return') : 0xeac9;
|
|
2441
|
+
var REACT_PORTAL_TYPE = hasSymbol ? Symbol['for']('react.portal') : 0xeaca;
|
|
2442
|
+
var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol['for']('react.fragment') : 0xeacb;
|
|
2443
|
+
|
|
2444
|
+
var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
|
|
2445
|
+
var FAUX_ITERATOR_SYMBOL = '@@iterator';
|
|
2446
|
+
|
|
2447
|
+
function getIteratorFn(maybeIterable) {
|
|
2448
|
+
if (maybeIterable === null || typeof maybeIterable === 'undefined') {
|
|
2449
|
+
return null;
|
|
2450
|
+
}
|
|
2451
|
+
var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
|
|
2452
|
+
if (typeof maybeIterator === 'function') {
|
|
2453
|
+
return maybeIterator;
|
|
2454
|
+
}
|
|
2455
|
+
return null;
|
|
2456
|
+
}
|
|
2408
2457
|
|
|
2409
2458
|
var getCurrentFiberStackAddendum$1 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
|
|
2410
2459
|
|
|
@@ -2441,38 +2490,6 @@ var getCurrentFiberStackAddendum$1 = ReactDebugCurrentFiber.getCurrentFiberStack
|
|
|
2441
2490
|
|
|
2442
2491
|
var isArray$1 = Array.isArray;
|
|
2443
2492
|
|
|
2444
|
-
var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
|
|
2445
|
-
var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
|
|
2446
|
-
|
|
2447
|
-
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
|
|
2448
|
-
// nor polyfill, then a plain number is used for performance.
|
|
2449
|
-
var REACT_ELEMENT_TYPE;
|
|
2450
|
-
var REACT_CALL_TYPE;
|
|
2451
|
-
var REACT_RETURN_TYPE;
|
|
2452
|
-
var REACT_FRAGMENT_TYPE;
|
|
2453
|
-
if (typeof Symbol === 'function' && Symbol['for']) {
|
|
2454
|
-
REACT_ELEMENT_TYPE = Symbol['for']('react.element');
|
|
2455
|
-
REACT_CALL_TYPE = Symbol['for']('react.call');
|
|
2456
|
-
REACT_RETURN_TYPE = Symbol['for']('react.return');
|
|
2457
|
-
REACT_FRAGMENT_TYPE = Symbol['for']('react.fragment');
|
|
2458
|
-
} else {
|
|
2459
|
-
REACT_ELEMENT_TYPE = 0xeac7;
|
|
2460
|
-
REACT_CALL_TYPE = 0xeac8;
|
|
2461
|
-
REACT_RETURN_TYPE = 0xeac9;
|
|
2462
|
-
REACT_FRAGMENT_TYPE = 0xeacb;
|
|
2463
|
-
}
|
|
2464
|
-
|
|
2465
|
-
function getIteratorFn(maybeIterable) {
|
|
2466
|
-
if (maybeIterable === null || typeof maybeIterable === 'undefined') {
|
|
2467
|
-
return null;
|
|
2468
|
-
}
|
|
2469
|
-
var iteratorFn = ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
|
|
2470
|
-
if (typeof iteratorFn === 'function') {
|
|
2471
|
-
return iteratorFn;
|
|
2472
|
-
}
|
|
2473
|
-
return null;
|
|
2474
|
-
}
|
|
2475
|
-
|
|
2476
2493
|
function coerceRef(current, element) {
|
|
2477
2494
|
var mixedRef = element.ref;
|
|
2478
2495
|
if (mixedRef !== null && typeof mixedRef !== 'function') {
|
|
@@ -2533,21 +2550,12 @@ function warnOnFunctionType() {
|
|
|
2533
2550
|
// to be able to optimize each path individually by branching early. This needs
|
|
2534
2551
|
// a compiler or we can do it manually. Helpers that don't need this branching
|
|
2535
2552
|
// live outside of this function.
|
|
2536
|
-
function ChildReconciler(
|
|
2553
|
+
function ChildReconciler(shouldTrackSideEffects) {
|
|
2537
2554
|
function deleteChild(returnFiber, childToDelete) {
|
|
2538
2555
|
if (!shouldTrackSideEffects) {
|
|
2539
2556
|
// Noop.
|
|
2540
2557
|
return;
|
|
2541
2558
|
}
|
|
2542
|
-
if (!shouldClone) {
|
|
2543
|
-
// When we're reconciling in place we have a work in progress copy. We
|
|
2544
|
-
// actually want the current copy. If there is no current copy, then we
|
|
2545
|
-
// don't need to track deletion side-effects.
|
|
2546
|
-
if (childToDelete.alternate === null) {
|
|
2547
|
-
return;
|
|
2548
|
-
}
|
|
2549
|
-
childToDelete = childToDelete.alternate;
|
|
2550
|
-
}
|
|
2551
2559
|
// Deletions are added in reversed order so we add it to the front.
|
|
2552
2560
|
// At this point, the return fiber's effect list is empty except for
|
|
2553
2561
|
// deletions, so we can just append the deletion to the list. The remaining
|
|
@@ -2600,22 +2608,10 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
|
|
|
2600
2608
|
function useFiber(fiber, pendingProps, expirationTime) {
|
|
2601
2609
|
// We currently set sibling to null and index to 0 here because it is easy
|
|
2602
2610
|
// to forget to do before returning it. E.g. for the single child case.
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
return clone;
|
|
2608
|
-
} else {
|
|
2609
|
-
// We override the expiration time even if it is earlier, because if
|
|
2610
|
-
// we're reconciling at a later time that means that this was
|
|
2611
|
-
// down-prioritized.
|
|
2612
|
-
fiber.expirationTime = expirationTime;
|
|
2613
|
-
fiber.effectTag = NoEffect;
|
|
2614
|
-
fiber.index = 0;
|
|
2615
|
-
fiber.sibling = null;
|
|
2616
|
-
fiber.pendingProps = pendingProps;
|
|
2617
|
-
return fiber;
|
|
2618
|
-
}
|
|
2611
|
+
var clone = createWorkInProgress(fiber, pendingProps, expirationTime);
|
|
2612
|
+
clone.index = 0;
|
|
2613
|
+
clone.sibling = null;
|
|
2614
|
+
return clone;
|
|
2619
2615
|
}
|
|
2620
2616
|
|
|
2621
2617
|
function placeChild(newFiber, lastPlacedIndex, newIndex) {
|
|
@@ -3412,7 +3408,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
|
|
|
3412
3408
|
// Handle top level unkeyed fragments as if they were arrays.
|
|
3413
3409
|
// This leads to an ambiguity between <>{[...]}</> and <>...</>.
|
|
3414
3410
|
// We treat the ambiguous cases above the same.
|
|
3415
|
-
if (
|
|
3411
|
+
if (typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null) {
|
|
3416
3412
|
newChild = newChild.props.children;
|
|
3417
3413
|
}
|
|
3418
3414
|
|
|
@@ -3487,11 +3483,8 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
|
|
|
3487
3483
|
return reconcileChildFibers;
|
|
3488
3484
|
}
|
|
3489
3485
|
|
|
3490
|
-
var reconcileChildFibers = ChildReconciler(true
|
|
3491
|
-
|
|
3492
|
-
var reconcileChildFibersInPlace = ChildReconciler(false, true);
|
|
3493
|
-
|
|
3494
|
-
var mountChildFibersInPlace = ChildReconciler(false, false);
|
|
3486
|
+
var reconcileChildFibers = ChildReconciler(true);
|
|
3487
|
+
var mountChildFibers = ChildReconciler(false);
|
|
3495
3488
|
|
|
3496
3489
|
function cloneChildFibers(current, workInProgress) {
|
|
3497
3490
|
!(current === null || workInProgress.child === current.child) ? invariant(false, 'Resuming work not yet implemented.') : void 0;
|
|
@@ -3546,20 +3539,15 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
|
|
|
3546
3539
|
// won't update its child set by applying minimal side-effects. Instead,
|
|
3547
3540
|
// we will add them all to the child before it gets rendered. That means
|
|
3548
3541
|
// we can optimize this reconciliation pass by not tracking side-effects.
|
|
3549
|
-
workInProgress.child =
|
|
3550
|
-
} else
|
|
3542
|
+
workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
|
|
3543
|
+
} else {
|
|
3551
3544
|
// If the current child is the same as the work in progress, it means that
|
|
3552
3545
|
// we haven't yet started any work on these children. Therefore, we use
|
|
3553
3546
|
// the clone algorithm to create a copy of all the current children.
|
|
3554
3547
|
|
|
3555
3548
|
// If we had any progressed work already, that is invalid at this point so
|
|
3556
3549
|
// let's throw it out.
|
|
3557
|
-
workInProgress.child = reconcileChildFibers(workInProgress,
|
|
3558
|
-
} else {
|
|
3559
|
-
// If, on the other hand, it is already using a clone, that means we've
|
|
3560
|
-
// already begun some work on this tree and we can continue where we left
|
|
3561
|
-
// off by reconciling against the existing children.
|
|
3562
|
-
workInProgress.child = reconcileChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, renderExpirationTime);
|
|
3550
|
+
workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderExpirationTime);
|
|
3563
3551
|
}
|
|
3564
3552
|
}
|
|
3565
3553
|
|
|
@@ -3669,6 +3657,9 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
|
|
|
3669
3657
|
{
|
|
3670
3658
|
ReactDebugCurrentFiber.setCurrentPhase('render');
|
|
3671
3659
|
nextChildren = instance.render();
|
|
3660
|
+
if (debugRenderPhaseSideEffects) {
|
|
3661
|
+
instance.render();
|
|
3662
|
+
}
|
|
3672
3663
|
ReactDebugCurrentFiber.setCurrentPhase(null);
|
|
3673
3664
|
}
|
|
3674
3665
|
// React DevTools reads this flag.
|
|
@@ -3727,7 +3718,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
|
|
|
3727
3718
|
// Ensure that children mount into this root without tracking
|
|
3728
3719
|
// side-effects. This ensures that we don't store Placement effects on
|
|
3729
3720
|
// nodes that will be hydrated.
|
|
3730
|
-
workInProgress.child =
|
|
3721
|
+
workInProgress.child = mountChildFibers(workInProgress, null, element, renderExpirationTime);
|
|
3731
3722
|
} else {
|
|
3732
3723
|
// Otherwise reset hydration state in case we aborted and resumed another
|
|
3733
3724
|
// root.
|
|
@@ -3894,11 +3885,9 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
|
|
|
3894
3885
|
// The following is a fork of reconcileChildrenAtExpirationTime but using
|
|
3895
3886
|
// stateNode to store the child.
|
|
3896
3887
|
if (current === null) {
|
|
3897
|
-
workInProgress.stateNode =
|
|
3898
|
-
} else if (current.child === workInProgress.child) {
|
|
3899
|
-
workInProgress.stateNode = reconcileChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
|
|
3888
|
+
workInProgress.stateNode = mountChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
|
|
3900
3889
|
} else {
|
|
3901
|
-
workInProgress.stateNode =
|
|
3890
|
+
workInProgress.stateNode = reconcileChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
|
|
3902
3891
|
}
|
|
3903
3892
|
|
|
3904
3893
|
memoizeProps(workInProgress, nextCall);
|
|
@@ -3927,7 +3916,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
|
|
|
3927
3916
|
// flow doesn't do during mount. This doesn't happen at the root because
|
|
3928
3917
|
// the root always starts with a "current" with a null child.
|
|
3929
3918
|
// TODO: Consider unifying this with how the root works.
|
|
3930
|
-
workInProgress.child =
|
|
3919
|
+
workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
|
|
3931
3920
|
memoizeProps(workInProgress, nextChildren);
|
|
3932
3921
|
} else {
|
|
3933
3922
|
reconcileChildren(current, workInProgress, nextChildren);
|
|
@@ -5508,6 +5497,12 @@ function logCapturedError(capturedError) {
|
|
|
5508
5497
|
return;
|
|
5509
5498
|
}
|
|
5510
5499
|
|
|
5500
|
+
var error = capturedError.error;
|
|
5501
|
+
var suppressLogging = error && error.suppressReactErrorLogging;
|
|
5502
|
+
if (suppressLogging) {
|
|
5503
|
+
return;
|
|
5504
|
+
}
|
|
5505
|
+
|
|
5511
5506
|
{
|
|
5512
5507
|
var componentName = capturedError.componentName,
|
|
5513
5508
|
componentStack = capturedError.componentStack,
|
|
@@ -5603,6 +5598,7 @@ var ReactFiberScheduler = function (config) {
|
|
|
5603
5598
|
|
|
5604
5599
|
var now = config.now,
|
|
5605
5600
|
scheduleDeferredCallback = config.scheduleDeferredCallback,
|
|
5601
|
+
cancelDeferredCallback = config.cancelDeferredCallback,
|
|
5606
5602
|
useSyncScheduling = config.useSyncScheduling,
|
|
5607
5603
|
prepareForCommit = config.prepareForCommit,
|
|
5608
5604
|
resetAfterCommit = config.resetAfterCommit;
|
|
@@ -6010,6 +6006,7 @@ var ReactFiberScheduler = function (config) {
|
|
|
6010
6006
|
{
|
|
6011
6007
|
ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
|
|
6012
6008
|
}
|
|
6009
|
+
|
|
6013
6010
|
var next = beginWork(current, workInProgress, nextRenderExpirationTime);
|
|
6014
6011
|
{
|
|
6015
6012
|
ReactDebugCurrentFiber.resetCurrentFiber();
|
|
@@ -6330,7 +6327,10 @@ var ReactFiberScheduler = function (config) {
|
|
|
6330
6327
|
} catch (e) {
|
|
6331
6328
|
// Prevent cycle if logCapturedError() throws.
|
|
6332
6329
|
// A cycle may still occur if logCapturedError renders a component that throws.
|
|
6333
|
-
|
|
6330
|
+
var suppressLogging = e && e.suppressReactErrorLogging;
|
|
6331
|
+
if (!suppressLogging) {
|
|
6332
|
+
console.error(e);
|
|
6333
|
+
}
|
|
6334
6334
|
}
|
|
6335
6335
|
|
|
6336
6336
|
// If we're in the commit phase, defer scheduling an update on the
|
|
@@ -6475,6 +6475,19 @@ var ReactFiberScheduler = function (config) {
|
|
|
6475
6475
|
return scheduleWorkImpl(fiber, expirationTime, false);
|
|
6476
6476
|
}
|
|
6477
6477
|
|
|
6478
|
+
function checkRootNeedsClearing(root, fiber, expirationTime) {
|
|
6479
|
+
if (!isWorking && root === nextRoot && expirationTime < nextRenderExpirationTime) {
|
|
6480
|
+
// Restart the root from the top.
|
|
6481
|
+
if (nextUnitOfWork !== null) {
|
|
6482
|
+
// This is an interruption. (Used for performance tracking.)
|
|
6483
|
+
interruptedBy = fiber;
|
|
6484
|
+
}
|
|
6485
|
+
nextRoot = null;
|
|
6486
|
+
nextUnitOfWork = null;
|
|
6487
|
+
nextRenderExpirationTime = NoWork;
|
|
6488
|
+
}
|
|
6489
|
+
}
|
|
6490
|
+
|
|
6478
6491
|
function scheduleWorkImpl(fiber, expirationTime, isErrorRecovery) {
|
|
6479
6492
|
recordScheduleUpdate();
|
|
6480
6493
|
|
|
@@ -6500,17 +6513,10 @@ var ReactFiberScheduler = function (config) {
|
|
|
6500
6513
|
if (node['return'] === null) {
|
|
6501
6514
|
if (node.tag === HostRoot) {
|
|
6502
6515
|
var root = node.stateNode;
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
if (nextUnitOfWork !== null) {
|
|
6506
|
-
// This is an interruption. (Used for performance tracking.)
|
|
6507
|
-
interruptedBy = fiber;
|
|
6508
|
-
}
|
|
6509
|
-
nextRoot = null;
|
|
6510
|
-
nextUnitOfWork = null;
|
|
6511
|
-
nextRenderExpirationTime = NoWork;
|
|
6512
|
-
}
|
|
6516
|
+
|
|
6517
|
+
checkRootNeedsClearing(root, fiber, expirationTime);
|
|
6513
6518
|
requestWork(root, expirationTime);
|
|
6519
|
+
checkRootNeedsClearing(root, fiber, expirationTime);
|
|
6514
6520
|
} else {
|
|
6515
6521
|
{
|
|
6516
6522
|
if (!isErrorRecovery && fiber.tag === ClassComponent) {
|
|
@@ -6562,7 +6568,8 @@ var ReactFiberScheduler = function (config) {
|
|
|
6562
6568
|
var firstScheduledRoot = null;
|
|
6563
6569
|
var lastScheduledRoot = null;
|
|
6564
6570
|
|
|
6565
|
-
var
|
|
6571
|
+
var callbackExpirationTime = NoWork;
|
|
6572
|
+
var callbackID = -1;
|
|
6566
6573
|
var isRendering = false;
|
|
6567
6574
|
var nextFlushedRoot = null;
|
|
6568
6575
|
var nextFlushedExpirationTime = NoWork;
|
|
@@ -6580,6 +6587,31 @@ var ReactFiberScheduler = function (config) {
|
|
|
6580
6587
|
|
|
6581
6588
|
var timeHeuristicForUnitOfWork = 1;
|
|
6582
6589
|
|
|
6590
|
+
function scheduleCallbackWithExpiration(expirationTime) {
|
|
6591
|
+
if (callbackExpirationTime !== NoWork) {
|
|
6592
|
+
// A callback is already scheduled. Check its expiration time (timeout).
|
|
6593
|
+
if (expirationTime > callbackExpirationTime) {
|
|
6594
|
+
// Existing callback has sufficient timeout. Exit.
|
|
6595
|
+
return;
|
|
6596
|
+
} else {
|
|
6597
|
+
// Existing callback has insufficient timeout. Cancel and schedule a
|
|
6598
|
+
// new one.
|
|
6599
|
+
cancelDeferredCallback(callbackID);
|
|
6600
|
+
}
|
|
6601
|
+
// The request callback timer is already running. Don't start a new one.
|
|
6602
|
+
} else {
|
|
6603
|
+
startRequestCallbackTimer();
|
|
6604
|
+
}
|
|
6605
|
+
|
|
6606
|
+
// Compute a timeout for the given expiration time.
|
|
6607
|
+
var currentMs = now() - startTime;
|
|
6608
|
+
var expirationMs = expirationTimeToMs(expirationTime);
|
|
6609
|
+
var timeout = expirationMs - currentMs;
|
|
6610
|
+
|
|
6611
|
+
callbackExpirationTime = expirationTime;
|
|
6612
|
+
callbackID = scheduleDeferredCallback(performAsyncWork, { timeout: timeout });
|
|
6613
|
+
}
|
|
6614
|
+
|
|
6583
6615
|
// requestWork is called by the scheduler whenever a root receives an update.
|
|
6584
6616
|
// It's up to the renderer to call renderRoot at some point in the future.
|
|
6585
6617
|
function requestWork(root, expirationTime) {
|
|
@@ -6620,7 +6652,9 @@ var ReactFiberScheduler = function (config) {
|
|
|
6620
6652
|
if (isUnbatchingUpdates) {
|
|
6621
6653
|
// ...unless we're inside unbatchedUpdates, in which case we should
|
|
6622
6654
|
// flush it now.
|
|
6623
|
-
|
|
6655
|
+
nextFlushedRoot = root;
|
|
6656
|
+
nextFlushedExpirationTime = Sync;
|
|
6657
|
+
performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime);
|
|
6624
6658
|
}
|
|
6625
6659
|
return;
|
|
6626
6660
|
}
|
|
@@ -6628,10 +6662,8 @@ var ReactFiberScheduler = function (config) {
|
|
|
6628
6662
|
// TODO: Get rid of Sync and use current time?
|
|
6629
6663
|
if (expirationTime === Sync) {
|
|
6630
6664
|
performWork(Sync, null);
|
|
6631
|
-
} else
|
|
6632
|
-
|
|
6633
|
-
startRequestCallbackTimer();
|
|
6634
|
-
scheduleDeferredCallback(performAsyncWork);
|
|
6665
|
+
} else {
|
|
6666
|
+
scheduleCallbackWithExpiration(expirationTime);
|
|
6635
6667
|
}
|
|
6636
6668
|
}
|
|
6637
6669
|
|
|
@@ -6728,13 +6760,12 @@ var ReactFiberScheduler = function (config) {
|
|
|
6728
6760
|
|
|
6729
6761
|
// If we're inside a callback, set this to false since we just completed it.
|
|
6730
6762
|
if (deadline !== null) {
|
|
6731
|
-
|
|
6763
|
+
callbackExpirationTime = NoWork;
|
|
6764
|
+
callbackID = -1;
|
|
6732
6765
|
}
|
|
6733
6766
|
// If there's work left over, schedule a new callback.
|
|
6734
|
-
if (
|
|
6735
|
-
|
|
6736
|
-
startRequestCallbackTimer();
|
|
6737
|
-
scheduleDeferredCallback(performAsyncWork);
|
|
6767
|
+
if (nextFlushedExpirationTime !== NoWork) {
|
|
6768
|
+
scheduleCallbackWithExpiration(nextFlushedExpirationTime);
|
|
6738
6769
|
}
|
|
6739
6770
|
|
|
6740
6771
|
// Clean-up.
|
|
@@ -6807,6 +6838,8 @@ var ReactFiberScheduler = function (config) {
|
|
|
6807
6838
|
return false;
|
|
6808
6839
|
}
|
|
6809
6840
|
if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
|
|
6841
|
+
// Disregard deadline.didTimeout. Only expired work should be flushed
|
|
6842
|
+
// during a timeout. This path is only hit for non-expired work.
|
|
6810
6843
|
return false;
|
|
6811
6844
|
}
|
|
6812
6845
|
deadlineDidExpire = true;
|