From 54f23f4b3c487cf516dc92262d0d87efaf2131dc Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 4 Apr 2018 15:11:21 -0700 Subject: [PATCH] React sync for revisions 9d484ed...1c2876d Reviewed By: gaearon Differential Revision: D7500761 fbshipit-source-id: 8dc1cda879942fc4990b23144a616039fdbe6dc0 --- Libraries/Renderer/REVISION | 2 +- Libraries/Renderer/ReactFabric-dev.js | 5652 +++++++++-------- Libraries/Renderer/ReactFabric-prod.js | 1023 +-- Libraries/Renderer/ReactNativeRenderer-dev.js | 5649 ++++++++-------- .../Renderer/ReactNativeRenderer-prod.js | 1087 ++-- Libraries/Renderer/shims/ReactTypes.js | 4 +- package.json | 32 +- 7 files changed, 7536 insertions(+), 5913 deletions(-) diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index 824ff8c33a4c4f..fc81a7c7f28c85 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -ad9544f48e58f2599a8ea0de1e9f4dd104db30bb \ No newline at end of file +1c2876d5b558b8591feb335d8d7204bc46f7da8a \ No newline at end of file diff --git a/Libraries/Renderer/ReactFabric-dev.js b/Libraries/Renderer/ReactFabric-dev.js index 867873cd41d55b..0b7a78516c11ba 100644 --- a/Libraries/Renderer/ReactFabric-dev.js +++ b/Libraries/Renderer/ReactFabric-dev.js @@ -25,8 +25,8 @@ var deepDiffer = require("deepDiffer"); var flattenStyle = require("flattenStyle"); var React = require("react"); var emptyObject = require("fbjs/lib/emptyObject"); -var checkPropTypes = require("prop-types/checkPropTypes"); var shallowEqual = require("fbjs/lib/shallowEqual"); +var checkPropTypes = require("prop-types/checkPropTypes"); var deepFreezeAndThrowOnMutationInDev = require("deepFreezeAndThrowOnMutationInDev"); var FabricUIManager = require("FabricUIManager"); @@ -509,11 +509,13 @@ var injection$1 = { getNodeFromInstance = Injected.getNodeFromInstance; { - warning( - getNodeFromInstance && getInstanceFromNode, - "EventPluginUtils.injection.injectComponentTree(...): Injected " + - "module is missing getNodeFromInstance or getInstanceFromNode." - ); + !(getNodeFromInstance && getInstanceFromNode) + ? warning( + false, + "EventPluginUtils.injection.injectComponentTree(...): Injected " + + "module is missing getNodeFromInstance or getInstanceFromNode." + ) + : void 0; } } }; @@ -549,10 +551,9 @@ var validateEventDispatches = void 0; ? dispatchInstances.length : dispatchInstances ? 1 : 0; - warning( - instancesIsArr === listenersIsArr && instancesLen === listenersLen, - "EventPluginUtils: Invalid `event`." - ); + !(instancesIsArr === listenersIsArr && instancesLen === listenersLen) + ? warning(false, "EventPluginUtils: Invalid `event`.") + : void 0; }; } @@ -810,6 +811,7 @@ var Fragment = 10; var Mode = 11; var ContextConsumer = 12; var ContextProvider = 13; +var ForwardRef = 14; function getParent(inst) { do { @@ -938,7 +940,7 @@ function listenerAtPhase(inst, event, propagationPhase) { */ function accumulateDirectionalDispatches(inst, phase, event) { { - warning(inst, "Dispatching inst must not be null"); + !inst ? warning(false, "Dispatching inst must not be null") : void 0; } var listener = listenerAtPhase(inst, event, phase); if (listener) { @@ -1257,13 +1259,15 @@ SyntheticEvent.extend = function(Interface) { !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1 ) { - warning( - didWarnForAddedNewProperty || target.isPersistent(), - "This synthetic event is reused for performance reasons. If you're " + - "seeing this, you're adding a new property in the synthetic event object. " + - "The property is never released. See " + - "https://fb.me/react-event-pooling for more information." - ); + !(didWarnForAddedNewProperty || target.isPersistent()) + ? warning( + false, + "This synthetic event is reused for performance reasons. If you're " + + "seeing this, you're adding a new property in the synthetic event object. " + + "The property is never released. See " + + "https://fb.me/react-event-pooling for more information." + ) + : void 0; didWarnForAddedNewProperty = true; } target[prop] = value; @@ -1310,16 +1314,18 @@ function getPooledWarningPropertyDefinition(propName, getVal) { function warn(action, result) { var warningCondition = false; - warning( - warningCondition, - "This synthetic event is reused for performance reasons. If you're seeing this, " + - "you're %s `%s` on a released/nullified synthetic event. %s. " + - "If you must keep the original synthetic event around, use event.persist(). " + - "See https://fb.me/react-event-pooling for more information.", - action, - propName, - result - ); + !warningCondition + ? warning( + false, + "This synthetic event is reused for performance reasons. If you're seeing this, " + + "you're %s `%s` on a released/nullified synthetic event. %s. " + + "If you must keep the original synthetic event around, use event.persist(). " + + "See https://fb.me/react-event-pooling for more information.", + action, + propName, + result + ) + : void 0; } } @@ -1437,13 +1443,15 @@ function getTouchIdentifier(_ref) { invariant(identifier != null, "Touch object is missing identifier."); { - warning( - identifier <= MAX_TOUCH_BANK, - "Touch identifier %s is greater than maximum supported %s which causes " + - "performance issues backfilling array locations for all of the indices.", - identifier, - MAX_TOUCH_BANK - ); + !(identifier <= MAX_TOUCH_BANK) + ? warning( + false, + "Touch identifier %s is greater than maximum supported %s which causes " + + "performance issues backfilling array locations for all of the indices.", + identifier, + MAX_TOUCH_BANK + ) + : void 0; } return identifier; } @@ -1542,10 +1550,9 @@ var ResponderTouchHistoryStore = { } { var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; - warning( - activeRecord != null && activeRecord.touchActive, - "Cannot find single active touch." - ); + !(activeRecord != null && activeRecord.touchActive) + ? warning(false, "Cannot find single active touch.") + : void 0; } } } @@ -2356,6 +2363,9 @@ var REACT_CONTEXT_TYPE = hasSymbol ? Symbol["for"]("react.context") : 0xeace; var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol["for"]("react.async_mode") : 0xeacf; +var REACT_FORWARD_REF_TYPE = hasSymbol + ? Symbol["for"]("react.forward_ref") + : 0xead0; var MAYBE_ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = "@@iterator"; @@ -2637,7 +2647,7 @@ var TouchHistoryMath = { // TODO: this is special because it gets imported during build. -var ReactVersion = "16.3.0-alpha.1"; +var ReactVersion = "16.3.1"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -3307,15 +3317,17 @@ function findNodeHandle(componentOrHandle) { { var owner = ReactCurrentOwner.current; if (owner !== null && owner.stateNode !== null) { - warning( - owner.stateNode._warnedAboutRefsInRender, - "%s is accessing findNodeHandle inside its render(). " + - "render() should be a pure function of props and state. It should " + - "never access something that requires stale data from the previous " + - "render, such as refs. Move this logic to componentDidMount and " + - "componentDidUpdate instead.", - getComponentName(owner) || "A component" - ); + !owner.stateNode._warnedAboutRefsInRender + ? warning( + false, + "%s is accessing findNodeHandle inside its render(). " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentName(owner) || "A component" + ) + : void 0; owner.stateNode._warnedAboutRefsInRender = true; } @@ -3773,7 +3785,8 @@ var frameDeadline = 0; var frameDeadlineObject = { timeRemaining: function() { return frameDeadline - now(); - } + }, + didTimeout: false }; function setTimeoutCallback() { @@ -3861,9 +3874,10 @@ var Callback = /* */ 32; var DidCapture = /* */ 64; var Ref = /* */ 128; var ErrLog = /* */ 256; +var Snapshot = /* */ 2048; // Union of all host effects -var HostEffectMask = /* */ 511; +var HostEffectMask = /* */ 2559; var Incomplete = /* */ 512; var ShouldCapture = /* */ 1024; @@ -3911,15 +3925,17 @@ function isMounted(component) { if (owner !== null && owner.tag === ClassComponent) { var ownerFiber = owner; var instance = ownerFiber.stateNode; - warning( - instance._warnedAboutRefsInRender, - "%s is accessing isMounted inside its render() function. " + - "render() should be a pure function of props and state. It should " + - "never access something that requires stale data from the previous " + - "render, such as refs. Move this logic to componentDidMount and " + - "componentDidUpdate instead.", - getComponentName(ownerFiber) || "A component" - ); + !instance._warnedAboutRefsInRender + ? warning( + false, + "%s is accessing isMounted inside its render() function. " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentName(ownerFiber) || "A component" + ) + : void 0; instance._warnedAboutRefsInRender = true; } } @@ -4130,1741 +4146,1488 @@ function findCurrentHostFiberWithNoPortals(parent) { return null; } -var valueStack = []; +// Max 31 bit integer. The max integer size in V8 for 32-bit systems. +// Math.pow(2, 30) - 1 +// 0b111111111111111111111111111111 +var MAX_SIGNED_31_BIT_INT = 1073741823; + +// TODO: Use an opaque type once ESLint et al support the syntax -var fiberStack = void 0; +var NoWork = 0; +var Sync = 1; +var Never = MAX_SIGNED_31_BIT_INT; -{ - fiberStack = []; -} +var UNIT_SIZE = 10; +var MAGIC_NUMBER_OFFSET = 2; -var index = -1; +// 1 unit of expiration time represents 10ms. +function msToExpirationTime(ms) { + // Always add an offset so that we don't clash with the magic number for NoWork. + return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET; +} -function createCursor(defaultValue) { - return { - current: defaultValue - }; +function expirationTimeToMs(expirationTime) { + return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE; } -function pop(cursor, fiber) { - if (index < 0) { - { - warning(false, "Unexpected pop."); - } - return; - } +function ceiling(num, precision) { + return (((num / precision) | 0) + 1) * precision; +} - { - if (fiber !== fiberStack[index]) { - warning(false, "Unexpected Fiber popped."); - } - } +function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { + return ceiling( + currentTime + expirationInMs / UNIT_SIZE, + bucketSizeMs / UNIT_SIZE + ); +} - cursor.current = valueStack[index]; +var NoContext = 0; +var AsyncMode = 1; +var StrictMode = 2; - valueStack[index] = null; +var hasBadMapPolyfill = void 0; - { - fiberStack[index] = null; +{ + hasBadMapPolyfill = false; + try { + var nonExtensibleObject = Object.preventExtensions({}); + var testMap = new Map([[nonExtensibleObject, null]]); + var testSet = new Set([nonExtensibleObject]); + // This is necessary for Rollup to not consider these unused. + // https://github.com/rollup/rollup/issues/1771 + // TODO: we can remove these if Rollup fixes the bug. + testMap.set(0, 0); + testSet.add(0); + } catch (e) { + // TODO: Consider warning about bad polyfills + hasBadMapPolyfill = true; } - - index--; } -function push(cursor, value, fiber) { - index++; - - valueStack[index] = cursor.current; +// A Fiber is work on a Component that needs to be done or was done. There can +// be more than one per component. - { - fiberStack[index] = fiber; - } +var debugCounter = void 0; - cursor.current = value; +{ + debugCounter = 1; } -function reset() { - while (index > -1) { - valueStack[index] = null; +function FiberNode(tag, pendingProps, key, mode) { + // Instance + this.tag = tag; + this.key = key; + this.type = null; + this.stateNode = null; - { - fiberStack[index] = null; - } + // Fiber + this["return"] = null; + this.child = null; + this.sibling = null; + this.index = 0; - index--; - } -} + this.ref = null; -var describeComponentFrame = function(name, source, ownerName) { - return ( - "\n in " + - (name || "Unknown") + - (source - ? " (at " + - source.fileName.replace(/^.*[\\\/]/, "") + - ":" + - source.lineNumber + - ")" - : ownerName ? " (created by " + ownerName + ")" : "") - ); -}; + this.pendingProps = pendingProps; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; -function describeFiber(fiber) { - switch (fiber.tag) { - case IndeterminateComponent: - case FunctionalComponent: - case ClassComponent: - case HostComponent: - var owner = fiber._debugOwner; - var source = fiber._debugSource; - var name = getComponentName(fiber); - var ownerName = null; - if (owner) { - ownerName = getComponentName(owner); - } - return describeComponentFrame(name, source, ownerName); - default: - return ""; - } -} + this.mode = mode; -// This function can only be called with a work-in-progress fiber and -// only during begin or complete phase. Do not call it under any other -// circumstances. -function getStackAddendumByWorkInProgressFiber(workInProgress) { - var info = ""; - var node = workInProgress; - do { - info += describeFiber(node); - // Otherwise this return pointer might point to the wrong tree: - node = node["return"]; - } while (node); - return info; -} + // Effects + this.effectTag = NoEffect; + this.nextEffect = null; -function getCurrentFiberOwnerName() { - { - var fiber = ReactDebugCurrentFiber.current; - if (fiber === null) { - return null; - } - var owner = fiber._debugOwner; - if (owner !== null && typeof owner !== "undefined") { - return getComponentName(owner); - } - } - return null; -} + this.firstEffect = null; + this.lastEffect = null; + + this.expirationTime = NoWork; + + this.alternate = null; -function getCurrentFiberStackAddendum() { { - var fiber = ReactDebugCurrentFiber.current; - if (fiber === null) { - return null; + this._debugID = debugCounter++; + this._debugSource = null; + this._debugOwner = null; + this._debugIsCurrentlyTiming = false; + if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") { + Object.preventExtensions(this); } - // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. - return getStackAddendumByWorkInProgressFiber(fiber); } - return null; -} - -function resetCurrentFiber() { - ReactDebugCurrentFrame.getCurrentStack = null; - ReactDebugCurrentFiber.current = null; - ReactDebugCurrentFiber.phase = null; } -function setCurrentFiber(fiber) { - ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; - ReactDebugCurrentFiber.current = fiber; - ReactDebugCurrentFiber.phase = null; -} +// This is a constructor function, rather than a POJO constructor, still +// please ensure we do the following: +// 1) Nobody should add any instance methods on this. Instance methods can be +// more difficult to predict when they get optimized and they are almost +// never inlined properly in static compilers. +// 2) Nobody should rely on `instanceof Fiber` for type testing. We should +// always know when it is a fiber. +// 3) We might want to experiment with using numeric keys since they are easier +// to optimize in a non-JIT environment. +// 4) We can easily go from a constructor to a createFiber object literal if that +// is faster. +// 5) It should be easy to port this to a C struct and keep a C implementation +// compatible. +var createFiber = function(tag, pendingProps, key, mode) { + // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, pendingProps, key, mode); +}; -function setCurrentPhase(phase) { - ReactDebugCurrentFiber.phase = phase; +function shouldConstruct(Component) { + return !!(Component.prototype && Component.prototype.isReactComponent); } -var ReactDebugCurrentFiber = { - current: null, - phase: null, - resetCurrentFiber: resetCurrentFiber, - setCurrentFiber: setCurrentFiber, - setCurrentPhase: setCurrentPhase, - getCurrentFiberOwnerName: getCurrentFiberOwnerName, - getCurrentFiberStackAddendum: getCurrentFiberStackAddendum -}; +// This is used to create an alternate fiber to do work on. +function createWorkInProgress(current, pendingProps, expirationTime) { + var workInProgress = current.alternate; + if (workInProgress === null) { + // We use a double buffering pooling technique because we know that we'll + // only ever need at most two versions of a tree. We pool the "other" unused + // node that we're free to reuse. This is lazily created to avoid allocating + // extra objects for things that are never updated. It also allow us to + // reclaim the extra memory if needed. + workInProgress = createFiber( + current.tag, + pendingProps, + current.key, + current.mode + ); + workInProgress.type = current.type; + workInProgress.stateNode = current.stateNode; -var debugRenderPhaseSideEffects = false; -var debugRenderPhaseSideEffectsForStrictMode = false; - -var enableUserTimingAPI = true; -var enableGetDerivedStateFromCatch = false; -var warnAboutDeprecatedLifecycles = false; -var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; - -// React Fabric uses persistent reconciler. -var enableMutatingReconciler = false; -var enableNoopReconciler = false; -var enablePersistentReconciler = true; + { + // DEV-only fields + workInProgress._debugID = current._debugID; + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; + } -// Only used in www builds. + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + workInProgress.pendingProps = pendingProps; -// Prefix measurements so that it's possible to filter them. -// Longer prefixes are hard to read in DevTools. -var reactEmoji = "\u269B"; -var warningEmoji = "\u26D4"; -var supportsUserTiming = - typeof performance !== "undefined" && - typeof performance.mark === "function" && - typeof performance.clearMarks === "function" && - typeof performance.measure === "function" && - typeof performance.clearMeasures === "function"; + // We already have an alternate. + // Reset the effect tag. + workInProgress.effectTag = NoEffect; -// Keep track of current fiber so that we know the path to unwind on pause. -// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? -var currentFiber = null; -// If we're in the middle of user code, which fiber and method is it? -// Reusing `currentFiber` would be confusing for this because user code fiber -// can change during commit phase too, but we don't need to unwind it (since -// lifecycles in the commit phase don't resemble a tree). -var currentPhase = null; -var currentPhaseFiber = null; -// Did lifecycle hook schedule an update? This is often a performance problem, -// so we will keep track of it, and include it in the report. -// Track commits caused by cascading updates. -var isCommitting = false; -var hasScheduledUpdateInCurrentCommit = false; -var hasScheduledUpdateInCurrentPhase = false; -var commitCountInCurrentWorkLoop = 0; -var effectCountInCurrentCommit = 0; -var isWaitingForCallback = false; -// During commits, we only show a measurement once per method name -// to avoid stretch the commit phase with measurement overhead. -var labelsInCurrentCommit = new Set(); + // The effect list is no longer valid. + workInProgress.nextEffect = null; + workInProgress.firstEffect = null; + workInProgress.lastEffect = null; + } -var formatMarkName = function(markName) { - return reactEmoji + " " + markName; -}; + workInProgress.expirationTime = expirationTime; -var formatLabel = function(label, warning$$1) { - var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; - var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; - return "" + prefix + label + suffix; -}; + workInProgress.child = current.child; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; -var beginMark = function(markName) { - performance.mark(formatMarkName(markName)); -}; + // These will be overridden during the parent's reconciliation + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; -var clearMark = function(markName) { - performance.clearMarks(formatMarkName(markName)); -}; + return workInProgress; +} -var endMark = function(label, markName, warning$$1) { - var formattedMarkName = formatMarkName(markName); - var formattedLabel = formatLabel(label, warning$$1); - try { - performance.measure(formattedLabel, formattedMarkName); - } catch (err) {} - // If previous mark was missing for some reason, this will throw. - // This could only happen if React crashed in an unexpected place earlier. - // Don't pile on with more errors. +function createHostRootFiber(isAsync) { + var mode = isAsync ? AsyncMode | StrictMode : NoContext; + return createFiber(HostRoot, null, null, mode); +} - // Clear marks immediately to avoid growing buffer. - performance.clearMarks(formattedMarkName); - performance.clearMeasures(formattedLabel); -}; +function createFiberFromElement(element, mode, expirationTime) { + var owner = null; + { + owner = element._owner; + } -var getFiberMarkName = function(label, debugID) { - return label + " (#" + debugID + ")"; -}; + var fiber = void 0; + var type = element.type; + var key = element.key; + var pendingProps = element.props; -var getFiberLabel = function(componentName, isMounted, phase) { - if (phase === null) { - // These are composite component total time measurements. - return componentName + " [" + (isMounted ? "update" : "mount") + "]"; + var fiberTag = void 0; + if (typeof type === "function") { + fiberTag = shouldConstruct(type) ? ClassComponent : IndeterminateComponent; + } else if (typeof type === "string") { + fiberTag = HostComponent; } else { - // Composite component methods. - return componentName + "." + phase; + switch (type) { + case REACT_FRAGMENT_TYPE: + return createFiberFromFragment( + pendingProps.children, + mode, + expirationTime, + key + ); + case REACT_ASYNC_MODE_TYPE: + fiberTag = Mode; + mode |= AsyncMode | StrictMode; + break; + case REACT_STRICT_MODE_TYPE: + fiberTag = Mode; + mode |= StrictMode; + break; + case REACT_CALL_TYPE: + fiberTag = CallComponent; + break; + case REACT_RETURN_TYPE: + fiberTag = ReturnComponent; + break; + default: { + if (typeof type === "object" && type !== null) { + switch (type.$$typeof) { + case REACT_PROVIDER_TYPE: + fiberTag = ContextProvider; + break; + case REACT_CONTEXT_TYPE: + // This is a consumer + fiberTag = ContextConsumer; + break; + case REACT_FORWARD_REF_TYPE: + fiberTag = ForwardRef; + break; + default: + if (typeof type.tag === "number") { + // Currently assumed to be a continuation and therefore is a + // fiber already. + // TODO: The yield system is currently broken for updates in + // some cases. The reified yield stores a fiber, but we don't + // know which fiber that is; the current or a workInProgress? + // When the continuation gets rendered here we don't know if we + // can reuse that fiber or if we need to clone it. There is + // probably a clever way to restructure this. + fiber = type; + fiber.pendingProps = pendingProps; + fiber.expirationTime = expirationTime; + return fiber; + } else { + throwOnInvalidElementType(type, owner); + } + break; + } + } else { + throwOnInvalidElementType(type, owner); + } + } + } } -}; -var beginFiberMark = function(fiber, phase) { - var componentName = getComponentName(fiber) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); + fiber = createFiber(fiberTag, pendingProps, key, mode); + fiber.type = type; + fiber.expirationTime = expirationTime; - if (isCommitting && labelsInCurrentCommit.has(label)) { - // During the commit phase, we don't show duplicate labels because - // there is a fixed overhead for every measurement, and we don't - // want to stretch the commit phase beyond necessary. - return false; + { + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; } - labelsInCurrentCommit.add(label); - var markName = getFiberMarkName(label, debugID); - beginMark(markName); - return true; -}; + return fiber; +} -var clearFiberMark = function(fiber, phase) { - var componentName = getComponentName(fiber) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - clearMark(markName); -}; +function throwOnInvalidElementType(type, owner) { + var info = ""; + { + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + info += + " You likely forgot to export your component from the file " + + "it's defined in, or you might have mixed up default and " + + "named imports."; + } + var ownerName = owner ? getComponentName(owner) : null; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } + invariant( + false, + "Element type is invalid: expected a string (for built-in " + + "components) or a class/function (for composite components) " + + "but got: %s.%s", + type == null ? type : typeof type, + info + ); +} -var endFiberMark = function(fiber, phase, warning$$1) { - var componentName = getComponentName(fiber) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - endMark(label, markName, warning$$1); -}; +function createFiberFromFragment(elements, mode, expirationTime, key) { + var fiber = createFiber(Fragment, elements, key, mode); + fiber.expirationTime = expirationTime; + return fiber; +} -var shouldIgnoreFiber = function(fiber) { - // Host components should be skipped in the timeline. - // We could check typeof fiber.type, but does this work with RN? - switch (fiber.tag) { - case HostRoot: - case HostComponent: - case HostText: - case HostPortal: - case CallComponent: - case ReturnComponent: - case Fragment: - case ContextProvider: - case ContextConsumer: - return true; - default: - return false; - } -}; +function createFiberFromText(content, mode, expirationTime) { + var fiber = createFiber(HostText, content, null, mode); + fiber.expirationTime = expirationTime; + return fiber; +} -var clearPendingPhaseMeasurement = function() { - if (currentPhase !== null && currentPhaseFiber !== null) { - clearFiberMark(currentPhaseFiber, currentPhase); - } - currentPhaseFiber = null; - currentPhase = null; - hasScheduledUpdateInCurrentPhase = false; -}; +function createFiberFromHostInstanceForDeletion() { + var fiber = createFiber(HostComponent, null, null, NoContext); + fiber.type = "DELETED"; + return fiber; +} -var pauseTimers = function() { - // Stops all currently active measurements so that they can be resumed - // if we continue in a later deferred loop from the same unit of work. - var fiber = currentFiber; - while (fiber) { - if (fiber._debugIsCurrentlyTiming) { - endFiberMark(fiber, null, null); - } - fiber = fiber["return"]; - } -}; +function createFiberFromPortal(portal, mode, expirationTime) { + var pendingProps = portal.children !== null ? portal.children : []; + var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); + fiber.expirationTime = expirationTime; + fiber.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, // Used by persistent updates + implementation: portal.implementation + }; + return fiber; +} -var resumeTimersRecursively = function(fiber) { - if (fiber["return"] !== null) { - resumeTimersRecursively(fiber["return"]); - } - if (fiber._debugIsCurrentlyTiming) { - beginFiberMark(fiber, null); - } -}; +// Used for stashing WIP properties to replay failed work in DEV. +function assignFiberPropertiesInDEV(target, source) { + if (target === null) { + // This Fiber's initial properties will always be overwritten. + // We only use a Fiber to ensure the same hidden class so DEV isn't slow. + target = createFiber(IndeterminateComponent, null, null, NoContext); + } + + // This is intentionally written as a list of all properties. + // We tried to use Object.assign() instead but this is called in + // the hottest path, and Object.assign() was too slow: + // https://github.com/facebook/react/issues/12502 + // This code is DEV-only so size is not a concern. + + target.tag = source.tag; + target.key = source.key; + 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.mode = source.mode; + target.effectTag = source.effectTag; + target.nextEffect = source.nextEffect; + target.firstEffect = source.firstEffect; + target.lastEffect = source.lastEffect; + target.expirationTime = source.expirationTime; + target.alternate = source.alternate; + target._debugID = source._debugID; + target._debugSource = source._debugSource; + target._debugOwner = source._debugOwner; + target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming; + return target; +} -var resumeTimers = function() { - // Resumes all measurements that were active during the last deferred loop. - if (currentFiber !== null) { - resumeTimersRecursively(currentFiber); - } -}; +// TODO: This should be lifted into the renderer. -function recordEffect() { - if (enableUserTimingAPI) { - effectCountInCurrentCommit++; - } +function createFiberRoot(containerInfo, isAsync, hydrate) { + // Cyclic construction. This cheats the type system right now because + // stateNode is any. + var uninitializedFiber = createHostRootFiber(isAsync); + var root = { + current: uninitializedFiber, + containerInfo: containerInfo, + pendingChildren: null, + pendingCommitExpirationTime: NoWork, + finishedWork: null, + context: null, + pendingContext: null, + hydrate: hydrate, + remainingExpirationTime: NoWork, + firstBatch: null, + nextScheduledRoot: null + }; + uninitializedFiber.stateNode = root; + return root; } -function recordScheduleUpdate() { - if (enableUserTimingAPI) { - if (isCommitting) { - hasScheduledUpdateInCurrentCommit = true; - } - if ( - currentPhase !== null && - currentPhase !== "componentWillMount" && - currentPhase !== "componentWillReceiveProps" - ) { - hasScheduledUpdateInCurrentPhase = true; - } - } -} +var onCommitFiberRoot = null; +var onCommitFiberUnmount = null; +var hasLoggedError = false; -function startRequestCallbackTimer() { - if (enableUserTimingAPI) { - if (supportsUserTiming && !isWaitingForCallback) { - isWaitingForCallback = true; - beginMark("(Waiting for async callback...)"); +function catchErrors(fn) { + return function(arg) { + try { + return fn(arg); + } catch (err) { + if (true && !hasLoggedError) { + hasLoggedError = true; + warning(false, "React DevTools encountered an error: %s", err); + } } - } + }; } -function stopRequestCallbackTimer(didExpire) { - if (enableUserTimingAPI) { - if (supportsUserTiming) { - isWaitingForCallback = false; - var warning$$1 = didExpire ? "React was blocked by main thread" : null; - endMark( - "(Waiting for async callback...)", - "(Waiting for async callback...)", - warning$$1 +function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools + return false; + } + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; + } + if (!hook.supportsFiber) { + { + warning( + false, + "The installed version of React DevTools is too old and will not work " + + "with the current version of React. Please update React DevTools. " + + "https://fb.me/react-devtools" ); } + // DevTools exists, even though it doesn't support Fiber. + return true; } -} - -function startWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, this is the fiber to unwind from. - currentFiber = fiber; - if (!beginFiberMark(fiber, null)) { - return; + try { + var rendererID = hook.inject(internals); + // We have successfully injected, so now it is safe to set up hooks. + onCommitFiberRoot = catchErrors(function(root) { + return hook.onCommitFiberRoot(rendererID, root); + }); + onCommitFiberUnmount = catchErrors(function(fiber) { + return hook.onCommitFiberUnmount(rendererID, fiber); + }); + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + warning(false, "React DevTools encountered an error: %s.", err); } - fiber._debugIsCurrentlyTiming = true; } + // DevTools exists + return true; } -function cancelWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // Remember we shouldn't complete measurement for this fiber. - // Otherwise flamechart will be deep even for small updates. - fiber._debugIsCurrentlyTiming = false; - clearFiberMark(fiber, null); +function onCommitRoot(root) { + if (typeof onCommitFiberRoot === "function") { + onCommitFiberRoot(root); } } -function stopWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber["return"]; - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - endFiberMark(fiber, null, null); +function onCommitUnmount(fiber) { + if (typeof onCommitFiberUnmount === "function") { + onCommitFiberUnmount(fiber); } } -function stopFailedWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber["return"]; - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - var warning$$1 = "An error was thrown inside this error boundary"; - endFiberMark(fiber, null, warning$$1); +var describeComponentFrame = function(name, source, ownerName) { + return ( + "\n in " + + (name || "Unknown") + + (source + ? " (at " + + source.fileName.replace(/^.*[\\\/]/, "") + + ":" + + source.lineNumber + + ")" + : ownerName ? " (created by " + ownerName + ")" : "") + ); +}; + +function describeFiber(fiber) { + switch (fiber.tag) { + case IndeterminateComponent: + case FunctionalComponent: + case ClassComponent: + case HostComponent: + var owner = fiber._debugOwner; + var source = fiber._debugSource; + var name = getComponentName(fiber); + var ownerName = null; + if (owner) { + ownerName = getComponentName(owner); + } + return describeComponentFrame(name, source, ownerName); + default: + return ""; } } -function startPhaseTimer(fiber, phase) { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - clearPendingPhaseMeasurement(); - if (!beginFiberMark(fiber, phase)) { - return; - } - currentPhaseFiber = fiber; - currentPhase = phase; - } -} - -function stopPhaseTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - if (currentPhase !== null && currentPhaseFiber !== null) { - var warning$$1 = hasScheduledUpdateInCurrentPhase - ? "Scheduled a cascading update" - : null; - endFiberMark(currentPhaseFiber, currentPhase, warning$$1); - } - currentPhase = null; - currentPhaseFiber = null; - } -} - -function startWorkLoopTimer(nextUnitOfWork) { - if (enableUserTimingAPI) { - currentFiber = nextUnitOfWork; - if (!supportsUserTiming) { - return; - } - commitCountInCurrentWorkLoop = 0; - // This is top level call. - // Any other measurements are performed within. - beginMark("(React Tree Reconciliation)"); - // Resume any measurements that were in progress during the last loop. - resumeTimers(); - } -} - -function stopWorkLoopTimer(interruptedBy) { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - var warning$$1 = null; - if (interruptedBy !== null) { - if (interruptedBy.tag === HostRoot) { - warning$$1 = "A top-level update interrupted the previous render"; - } else { - var componentName = getComponentName(interruptedBy) || "Unknown"; - warning$$1 = - "An update to " + componentName + " interrupted the previous render"; - } - } else if (commitCountInCurrentWorkLoop > 1) { - warning$$1 = "There were cascading updates"; - } - commitCountInCurrentWorkLoop = 0; - // Pause any measurements until the next loop. - pauseTimers(); - endMark( - "(React Tree Reconciliation)", - "(React Tree Reconciliation)", - warning$$1 - ); - } +// This function can only be called with a work-in-progress fiber and +// only during begin or complete phase. Do not call it under any other +// circumstances. +function getStackAddendumByWorkInProgressFiber(workInProgress) { + var info = ""; + var node = workInProgress; + do { + info += describeFiber(node); + // Otherwise this return pointer might point to the wrong tree: + node = node["return"]; + } while (node); + return info; } -function startCommitTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - isCommitting = true; - hasScheduledUpdateInCurrentCommit = false; - labelsInCurrentCommit.clear(); - beginMark("(Committing Changes)"); - } -} +/** + * Forked from fbjs/warning: + * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js + * + * Only change is we use console.warn instead of console.error, + * and do nothing when 'console' is not supported. + * This really simplifies the code. + * --- + * Similar to invariant but only logs a warning if the condition is not met. + * This can be used to log issues in development environments in critical + * paths. Removing the logging code for production environments will keep the + * same logic and follow the same code paths. + */ -function stopCommitTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } +var lowPriorityWarning = function() {}; - var warning$$1 = null; - if (hasScheduledUpdateInCurrentCommit) { - warning$$1 = "Lifecycle hook scheduled a cascading update"; - } else if (commitCountInCurrentWorkLoop > 0) { - warning$$1 = "Caused by a cascading update in earlier commit"; +{ + var printWarning = function(format) { + for ( + var _len = arguments.length, + args = Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; } - hasScheduledUpdateInCurrentCommit = false; - commitCountInCurrentWorkLoop++; - isCommitting = false; - labelsInCurrentCommit.clear(); - endMark("(Committing Changes)", "(Committing Changes)", warning$$1); - } -} - -function startCommitHostEffectsTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; + var argIndex = 0; + var message = + "Warning: " + + format.replace(/%s/g, function() { + return args[argIndex++]; + }); + if (typeof console !== "undefined") { + console.warn(message); } - effectCountInCurrentCommit = 0; - beginMark("(Committing Host Effects)"); - } -} + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) {} + }; -function stopCommitHostEffectsTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; + lowPriorityWarning = function(condition, format) { + if (format === undefined) { + throw new Error( + "`warning(condition, format, ...args)` requires a warning " + + "message argument" + ); } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Committing Host Effects: " + count + " Total)", - "(Committing Host Effects)", - null - ); - } -} + if (!condition) { + for ( + var _len2 = arguments.length, + args = Array(_len2 > 2 ? _len2 - 2 : 0), + _key2 = 2; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 2] = arguments[_key2]; + } -function startCommitLifeCyclesTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; + printWarning.apply(undefined, [format].concat(args)); } - effectCountInCurrentCommit = 0; - beginMark("(Calling Lifecycle Methods)"); - } + }; } -function stopCommitLifeCyclesTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Calling Lifecycle Methods: " + count + " Total)", - "(Calling Lifecycle Methods)", - null - ); - } -} +var lowPriorityWarning$1 = lowPriorityWarning; -var warnedAboutMissingGetChildContext = void 0; +var ReactStrictModeWarnings = { + discardPendingWarnings: function() {}, + flushPendingDeprecationWarnings: function() {}, + flushPendingUnsafeLifecycleWarnings: function() {}, + recordDeprecationWarnings: function(fiber, instance) {}, + recordUnsafeLifecycleWarnings: function(fiber, instance) {} +}; { - warnedAboutMissingGetChildContext = {}; -} - -// A cursor to the current merged context object on the stack. -var contextStackCursor = createCursor(emptyObject); -// A cursor to a boolean indicating whether the context has changed. -var didPerformWorkStackCursor = createCursor(false); -// Keep track of the previous context object that was on the stack. -// We use this to get access to the parent context after we have already -// pushed the next context provider, and now need to merge their contexts. -var previousContext = emptyObject; - -function getUnmaskedContext(workInProgress) { - var hasOwnContext = isContextProvider(workInProgress); - if (hasOwnContext) { - // If the fiber is a context provider itself, when we read its context - // we have already pushed its own child context on the stack. A context - // provider should not "see" its own child context. Therefore we read the - // previous (parent) context instead for a context provider. - return previousContext; - } - return contextStackCursor.current; -} + var LIFECYCLE_SUGGESTIONS = { + UNSAFE_componentWillMount: "componentDidMount", + UNSAFE_componentWillReceiveProps: "static getDerivedStateFromProps", + UNSAFE_componentWillUpdate: "componentDidUpdate" + }; -function cacheContext(workInProgress, unmaskedContext, maskedContext) { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; - instance.__reactInternalMemoizedMaskedChildContext = maskedContext; -} + var pendingComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUnsafeLifecycleWarnings = new Map(); -function getMaskedContext(workInProgress, unmaskedContext) { - var type = workInProgress.type; - var contextTypes = type.contextTypes; - if (!contextTypes) { - return emptyObject; - } + // Tracks components we have already warned about. + var didWarnAboutDeprecatedLifecycles = new Set(); + var didWarnAboutUnsafeLifecycles = new Set(); - // Avoid recreating masked context unless unmasked context has changed. - // Failing to do this will result in unnecessary calls to componentWillReceiveProps. - // This may trigger infinite loops if componentWillReceiveProps calls setState. - var instance = workInProgress.stateNode; - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) { - return instance.__reactInternalMemoizedMaskedChildContext; - } + ReactStrictModeWarnings.discardPendingWarnings = function() { + pendingComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUnsafeLifecycleWarnings = new Map(); + }; - var context = {}; - for (var key in contextTypes) { - context[key] = unmaskedContext[key]; - } + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { + pendingUnsafeLifecycleWarnings.forEach(function( + lifecycleWarningsMap, + strictRoot + ) { + var lifecyclesWarningMesages = []; - { - var name = getComponentName(workInProgress) || "Unknown"; - checkPropTypes( - contextTypes, - context, - "context", - name, - ReactDebugCurrentFiber.getCurrentFiberStackAddendum - ); - } - - // Cache unmasked context so we can avoid recreating masked context unless necessary. - // Context is created before the class component is instantiated so check for instance. - if (instance) { - cacheContext(workInProgress, unmaskedContext, context); - } - - return context; -} - -function hasContextChanged() { - return didPerformWorkStackCursor.current; -} - -function isContextConsumer(fiber) { - return fiber.tag === ClassComponent && fiber.type.contextTypes != null; -} - -function isContextProvider(fiber) { - return fiber.tag === ClassComponent && fiber.type.childContextTypes != null; -} - -function popContextProvider(fiber) { - if (!isContextProvider(fiber)) { - return; - } - - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor, fiber); -} - -function popTopLevelContextObject(fiber) { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor, fiber); -} - -function pushTopLevelContextObject(fiber, context, didChange) { - invariant( - contextStackCursor.cursor == null, - "Unexpected context found on stack. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + Object.keys(lifecycleWarningsMap).forEach(function(lifecycle) { + var lifecycleWarnings = lifecycleWarningsMap[lifecycle]; + if (lifecycleWarnings.length > 0) { + var componentNames = new Set(); + lifecycleWarnings.forEach(function(fiber) { + componentNames.add(getComponentName(fiber) || "Component"); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); - push(contextStackCursor, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); -} + var formatted = lifecycle.replace("UNSAFE_", ""); + var suggestion = LIFECYCLE_SUGGESTIONS[lifecycle]; + var sortedComponentNames = Array.from(componentNames) + .sort() + .join(", "); -function processChildContext(fiber, parentContext) { - var instance = fiber.stateNode; - var childContextTypes = fiber.type.childContextTypes; + lifecyclesWarningMesages.push( + formatted + + ": Please update the following components to use " + + (suggestion + " instead: " + sortedComponentNames) + ); + } + }); - // TODO (bvaughn) Replace this behavior with an invariant() in the future. - // It has only been added in Fiber to match the (unintentional) behavior in Stack. - if (typeof instance.getChildContext !== "function") { - { - var componentName = getComponentName(fiber) || "Unknown"; + if (lifecyclesWarningMesages.length > 0) { + var strictRootComponentStack = getStackAddendumByWorkInProgressFiber( + strictRoot + ); - if (!warnedAboutMissingGetChildContext[componentName]) { - warnedAboutMissingGetChildContext[componentName] = true; warning( false, - "%s.childContextTypes is specified but there is no getChildContext() method " + - "on the instance. You can either define getChildContext() on %s or remove " + - "childContextTypes from it.", - componentName, - componentName + "Unsafe lifecycle methods were found within a strict-mode tree:%s" + + "\n\n%s" + + "\n\nLearn more about this warning here:" + + "\nhttps://fb.me/react-strict-mode-warnings", + strictRootComponentStack, + lifecyclesWarningMesages.join("\n\n") ); } - } - return parentContext; - } - - var childContext = void 0; - { - ReactDebugCurrentFiber.setCurrentPhase("getChildContext"); - } - startPhaseTimer(fiber, "getChildContext"); - childContext = instance.getChildContext(); - stopPhaseTimer(); - { - ReactDebugCurrentFiber.setCurrentPhase(null); - } - for (var contextKey in childContext) { - invariant( - contextKey in childContextTypes, - '%s.getChildContext(): key "%s" is not defined in childContextTypes.', - getComponentName(fiber) || "Unknown", - contextKey - ); - } - { - var name = getComponentName(fiber) || "Unknown"; - checkPropTypes( - childContextTypes, - childContext, - "child context", - name, - // In practice, there is one case in which we won't get a stack. It's when - // somebody calls unstable_renderSubtreeIntoContainer() and we process - // context from the parent component instance. The stack will be missing - // because it's outside of the reconciliation, and so the pointer has not - // been set. This is rare and doesn't matter. We'll also remove that API. - ReactDebugCurrentFiber.getCurrentFiberStackAddendum - ); - } + }); - return Object.assign({}, parentContext, childContext); -} + pendingUnsafeLifecycleWarnings = new Map(); + }; -function pushContextProvider(workInProgress) { - if (!isContextProvider(workInProgress)) { - return false; - } + var getStrictRoot = function(fiber) { + var maybeStrictRoot = null; - var instance = workInProgress.stateNode; - // We push the context as early as possible to ensure stack integrity. - // If the instance does not exist yet, we will push null at first, - // and replace it on the stack later when invalidating the context. - var memoizedMergedChildContext = - (instance && instance.__reactInternalMemoizedMergedChildContext) || - emptyObject; - - // Remember the parent context so we can merge with it later. - // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. - previousContext = contextStackCursor.current; - push(contextStackCursor, memoizedMergedChildContext, workInProgress); - push( - didPerformWorkStackCursor, - didPerformWorkStackCursor.current, - workInProgress - ); + while (fiber !== null) { + if (fiber.mode & StrictMode) { + maybeStrictRoot = fiber; + } - return true; -} + fiber = fiber["return"]; + } -function invalidateContextProvider(workInProgress, didChange) { - var instance = workInProgress.stateNode; - invariant( - instance, - "Expected to have an instance by this point. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + return maybeStrictRoot; + }; - if (didChange) { - // Merge parent and own context. - // Skip this if we're not updating due to sCU. - // This avoids unnecessarily recomputing memoized values. - var mergedContext = processChildContext(workInProgress, previousContext); - instance.__reactInternalMemoizedMergedChildContext = mergedContext; - - // Replace the old (or empty) context with the new one. - // It is important to unwind the context in the reverse order. - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor, workInProgress); - // Now push the new context and mark that it has changed. - push(contextStackCursor, mergedContext, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } else { - pop(didPerformWorkStackCursor, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } -} + ReactStrictModeWarnings.flushPendingDeprecationWarnings = function() { + if (pendingComponentWillMountWarnings.length > 0) { + var uniqueNames = new Set(); + pendingComponentWillMountWarnings.forEach(function(fiber) { + uniqueNames.add(getComponentName(fiber) || "Component"); + didWarnAboutDeprecatedLifecycles.add(fiber.type); + }); -function resetContext() { - previousContext = emptyObject; - contextStackCursor.current = emptyObject; - didPerformWorkStackCursor.current = false; -} + var sortedNames = Array.from(uniqueNames) + .sort() + .join(", "); -function findCurrentUnmaskedContext(fiber) { - // Currently this is only used with renderSubtreeIntoContainer; not sure if it - // makes sense elsewhere - invariant( - isFiberMounted(fiber) && fiber.tag === ClassComponent, - "Expected subtree parent to be a mounted class component. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + lowPriorityWarning$1( + false, + "componentWillMount is deprecated and will be removed in the next major version. " + + "Use componentDidMount instead. As a temporary workaround, " + + "you can rename to UNSAFE_componentWillMount." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here:" + + "\nhttps://fb.me/react-async-component-lifecycle-hooks", + sortedNames + ); - var node = fiber; - while (node.tag !== HostRoot) { - if (isContextProvider(node)) { - return node.stateNode.__reactInternalMemoizedMergedChildContext; + pendingComponentWillMountWarnings = []; } - var parent = node["return"]; - invariant( - parent, - "Found unexpected detached subtree parent. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - node = parent; - } - return node.stateNode.context; -} - -// Max 31 bit integer. The max integer size in V8 for 32-bit systems. -// Math.pow(2, 30) - 1 -// 0b111111111111111111111111111111 -var MAX_SIGNED_31_BIT_INT = 1073741823; -// TODO: Use an opaque type once ESLint et al support the syntax + if (pendingComponentWillReceivePropsWarnings.length > 0) { + var _uniqueNames = new Set(); + pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { + _uniqueNames.add(getComponentName(fiber) || "Component"); + didWarnAboutDeprecatedLifecycles.add(fiber.type); + }); -var NoWork = 0; -var Sync = 1; -var Never = MAX_SIGNED_31_BIT_INT; + var _sortedNames = Array.from(_uniqueNames) + .sort() + .join(", "); -var UNIT_SIZE = 10; -var MAGIC_NUMBER_OFFSET = 2; + lowPriorityWarning$1( + false, + "componentWillReceiveProps is deprecated and will be removed in the next major version. " + + "Use static getDerivedStateFromProps instead." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here:" + + "\nhttps://fb.me/react-async-component-lifecycle-hooks", + _sortedNames + ); -// 1 unit of expiration time represents 10ms. -function msToExpirationTime(ms) { - // Always add an offset so that we don't clash with the magic number for NoWork. - return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET; -} + pendingComponentWillReceivePropsWarnings = []; + } -function expirationTimeToMs(expirationTime) { - return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE; -} + if (pendingComponentWillUpdateWarnings.length > 0) { + var _uniqueNames2 = new Set(); + pendingComponentWillUpdateWarnings.forEach(function(fiber) { + _uniqueNames2.add(getComponentName(fiber) || "Component"); + didWarnAboutDeprecatedLifecycles.add(fiber.type); + }); -function ceiling(num, precision) { - return (((num / precision) | 0) + 1) * precision; -} + var _sortedNames2 = Array.from(_uniqueNames2) + .sort() + .join(", "); -function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { - return ceiling( - currentTime + expirationInMs / UNIT_SIZE, - bucketSizeMs / UNIT_SIZE - ); -} + lowPriorityWarning$1( + false, + "componentWillUpdate is deprecated and will be removed in the next major version. " + + "Use componentDidUpdate instead. As a temporary workaround, " + + "you can rename to UNSAFE_componentWillUpdate." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here:" + + "\nhttps://fb.me/react-async-component-lifecycle-hooks", + _sortedNames2 + ); -var NoContext = 0; -var AsyncMode = 1; -var StrictMode = 2; + pendingComponentWillUpdateWarnings = []; + } + }; -var hasBadMapPolyfill = void 0; + ReactStrictModeWarnings.recordDeprecationWarnings = function( + fiber, + instance + ) { + // Dedup strategy: Warn once per component. + if (didWarnAboutDeprecatedLifecycles.has(fiber.type)) { + return; + } -{ - hasBadMapPolyfill = false; - try { - var nonExtensibleObject = Object.preventExtensions({}); - var testMap = new Map([[nonExtensibleObject, null]]); - var testSet = new Set([nonExtensibleObject]); - // This is necessary for Rollup to not consider these unused. - // https://github.com/rollup/rollup/issues/1771 - // TODO: we can remove these if Rollup fixes the bug. - testMap.set(0, 0); - testSet.add(0); - } catch (e) { - // TODO: Consider warning about bad polyfills - hasBadMapPolyfill = true; - } -} + // Don't warn about react-lifecycles-compat polyfilled components. + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } + }; -// A Fiber is work on a Component that needs to be done or was done. There can -// be more than one per component. + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( + fiber, + instance + ) { + var strictRoot = getStrictRoot(fiber); -var debugCounter = void 0; + // Dedup strategy: Warn once per component. + // This is difficult to track any other way since component names + // are often vague and are likely to collide between 3rd party libraries. + // An expand property is probably okay to use here since it's DEV-only, + // and will only be set in the event of serious warnings. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; + } -{ - debugCounter = 1; -} - -function FiberNode(tag, pendingProps, key, mode) { - // Instance - this.tag = tag; - this.key = key; - this.type = null; - this.stateNode = null; - - // Fiber - this["return"] = null; - this.child = null; - this.sibling = null; - this.index = 0; + // Don't warn about react-lifecycles-compat polyfilled components. + // Note that it is sufficient to check for the presence of a + // single lifecycle, componentWillMount, with the polyfill flag. + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning === true + ) { + return; + } - this.ref = null; + var warningsForRoot = void 0; + if (!pendingUnsafeLifecycleWarnings.has(strictRoot)) { + warningsForRoot = { + UNSAFE_componentWillMount: [], + UNSAFE_componentWillReceiveProps: [], + UNSAFE_componentWillUpdate: [] + }; - this.pendingProps = pendingProps; - this.memoizedProps = null; - this.updateQueue = null; - this.memoizedState = null; + pendingUnsafeLifecycleWarnings.set(strictRoot, warningsForRoot); + } else { + warningsForRoot = pendingUnsafeLifecycleWarnings.get(strictRoot); + } - this.mode = mode; + var unsafeLifecycles = []; + if ( + typeof instance.componentWillMount === "function" || + typeof instance.UNSAFE_componentWillMount === "function" + ) { + unsafeLifecycles.push("UNSAFE_componentWillMount"); + } + if ( + typeof instance.componentWillReceiveProps === "function" || + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + unsafeLifecycles.push("UNSAFE_componentWillReceiveProps"); + } + if ( + typeof instance.componentWillUpdate === "function" || + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + unsafeLifecycles.push("UNSAFE_componentWillUpdate"); + } - // Effects - this.effectTag = NoEffect; - this.nextEffect = null; + if (unsafeLifecycles.length > 0) { + unsafeLifecycles.forEach(function(lifecycle) { + warningsForRoot[lifecycle].push(fiber); + }); + } + }; +} - this.firstEffect = null; - this.lastEffect = null; +var debugRenderPhaseSideEffects = false; +var debugRenderPhaseSideEffectsForStrictMode = false; +var enableUserTimingAPI = true; +var enableGetDerivedStateFromCatch = false; +var warnAboutDeprecatedLifecycles = false; +var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; - this.expirationTime = NoWork; +// React Fabric uses persistent reconciler. +var enableMutatingReconciler = false; +var enableNoopReconciler = false; +var enablePersistentReconciler = true; - this.alternate = null; +// Only used in www builds. +function getCurrentFiberOwnerName() { { - this._debugID = debugCounter++; - this._debugSource = null; - this._debugOwner = null; - this._debugIsCurrentlyTiming = false; - if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") { - Object.preventExtensions(this); + var fiber = ReactDebugCurrentFiber.current; + if (fiber === null) { + return null; + } + var owner = fiber._debugOwner; + if (owner !== null && typeof owner !== "undefined") { + return getComponentName(owner); } } + return null; } -// This is a constructor function, rather than a POJO constructor, still -// please ensure we do the following: -// 1) Nobody should add any instance methods on this. Instance methods can be -// more difficult to predict when they get optimized and they are almost -// never inlined properly in static compilers. -// 2) Nobody should rely on `instanceof Fiber` for type testing. We should -// always know when it is a fiber. -// 3) We might want to experiment with using numeric keys since they are easier -// to optimize in a non-JIT environment. -// 4) We can easily go from a constructor to a createFiber object literal if that -// is faster. -// 5) It should be easy to port this to a C struct and keep a C implementation -// compatible. -var createFiber = function(tag, pendingProps, key, mode) { - // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors - return new FiberNode(tag, pendingProps, key, mode); -}; +function getCurrentFiberStackAddendum() { + { + var fiber = ReactDebugCurrentFiber.current; + if (fiber === null) { + return null; + } + // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. + return getStackAddendumByWorkInProgressFiber(fiber); + } + return null; +} -function shouldConstruct(Component) { - return !!(Component.prototype && Component.prototype.isReactComponent); +function resetCurrentFiber() { + ReactDebugCurrentFrame.getCurrentStack = null; + ReactDebugCurrentFiber.current = null; + ReactDebugCurrentFiber.phase = null; } -// This is used to create an alternate fiber to do work on. -function createWorkInProgress(current, pendingProps, expirationTime) { - var workInProgress = current.alternate; - if (workInProgress === null) { - // We use a double buffering pooling technique because we know that we'll - // only ever need at most two versions of a tree. We pool the "other" unused - // node that we're free to reuse. This is lazily created to avoid allocating - // extra objects for things that are never updated. It also allow us to - // reclaim the extra memory if needed. - workInProgress = createFiber( - current.tag, - pendingProps, - current.key, - current.mode - ); - workInProgress.type = current.type; - workInProgress.stateNode = current.stateNode; +function setCurrentFiber(fiber) { + ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; + ReactDebugCurrentFiber.current = fiber; + ReactDebugCurrentFiber.phase = null; +} - { - // DEV-only fields - workInProgress._debugID = current._debugID; - workInProgress._debugSource = current._debugSource; - workInProgress._debugOwner = current._debugOwner; - } +function setCurrentPhase(phase) { + ReactDebugCurrentFiber.phase = phase; +} - workInProgress.alternate = current; - current.alternate = workInProgress; - } else { - workInProgress.pendingProps = pendingProps; +var ReactDebugCurrentFiber = { + current: null, + phase: null, + resetCurrentFiber: resetCurrentFiber, + setCurrentFiber: setCurrentFiber, + setCurrentPhase: setCurrentPhase, + getCurrentFiberOwnerName: getCurrentFiberOwnerName, + getCurrentFiberStackAddendum: getCurrentFiberStackAddendum +}; - // We already have an alternate. - // Reset the effect tag. - workInProgress.effectTag = NoEffect; +// Prefix measurements so that it's possible to filter them. +// Longer prefixes are hard to read in DevTools. +var reactEmoji = "\u269B"; +var warningEmoji = "\u26D4"; +var supportsUserTiming = + typeof performance !== "undefined" && + typeof performance.mark === "function" && + typeof performance.clearMarks === "function" && + typeof performance.measure === "function" && + typeof performance.clearMeasures === "function"; - // The effect list is no longer valid. - workInProgress.nextEffect = null; - workInProgress.firstEffect = null; - workInProgress.lastEffect = null; - } +// Keep track of current fiber so that we know the path to unwind on pause. +// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? +var currentFiber = null; +// If we're in the middle of user code, which fiber and method is it? +// Reusing `currentFiber` would be confusing for this because user code fiber +// can change during commit phase too, but we don't need to unwind it (since +// lifecycles in the commit phase don't resemble a tree). +var currentPhase = null; +var currentPhaseFiber = null; +// Did lifecycle hook schedule an update? This is often a performance problem, +// so we will keep track of it, and include it in the report. +// Track commits caused by cascading updates. +var isCommitting = false; +var hasScheduledUpdateInCurrentCommit = false; +var hasScheduledUpdateInCurrentPhase = false; +var commitCountInCurrentWorkLoop = 0; +var effectCountInCurrentCommit = 0; +var isWaitingForCallback = false; +// During commits, we only show a measurement once per method name +// to avoid stretch the commit phase with measurement overhead. +var labelsInCurrentCommit = new Set(); - workInProgress.expirationTime = expirationTime; +var formatMarkName = function(markName) { + return reactEmoji + " " + markName; +}; - workInProgress.child = current.child; - workInProgress.memoizedProps = current.memoizedProps; - workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; +var formatLabel = function(label, warning$$1) { + var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; + var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; + return "" + prefix + label + suffix; +}; - // These will be overridden during the parent's reconciliation - workInProgress.sibling = current.sibling; - workInProgress.index = current.index; - workInProgress.ref = current.ref; +var beginMark = function(markName) { + performance.mark(formatMarkName(markName)); +}; - return workInProgress; -} +var clearMark = function(markName) { + performance.clearMarks(formatMarkName(markName)); +}; -function createHostRootFiber(isAsync) { - var mode = isAsync ? AsyncMode | StrictMode : NoContext; - return createFiber(HostRoot, null, null, mode); -} +var endMark = function(label, markName, warning$$1) { + var formattedMarkName = formatMarkName(markName); + var formattedLabel = formatLabel(label, warning$$1); + try { + performance.measure(formattedLabel, formattedMarkName); + } catch (err) {} + // If previous mark was missing for some reason, this will throw. + // This could only happen if React crashed in an unexpected place earlier. + // Don't pile on with more errors. -function createFiberFromElement(element, mode, expirationTime) { - var owner = null; - { - owner = element._owner; - } + // Clear marks immediately to avoid growing buffer. + performance.clearMarks(formattedMarkName); + performance.clearMeasures(formattedLabel); +}; - var fiber = void 0; - var type = element.type; - var key = element.key; - var pendingProps = element.props; +var getFiberMarkName = function(label, debugID) { + return label + " (#" + debugID + ")"; +}; - var fiberTag = void 0; - if (typeof type === "function") { - fiberTag = shouldConstruct(type) ? ClassComponent : IndeterminateComponent; - } else if (typeof type === "string") { - fiberTag = HostComponent; +var getFiberLabel = function(componentName, isMounted, phase) { + if (phase === null) { + // These are composite component total time measurements. + return componentName + " [" + (isMounted ? "update" : "mount") + "]"; } else { - switch (type) { - case REACT_FRAGMENT_TYPE: - return createFiberFromFragment( - pendingProps.children, - mode, - expirationTime, - key - ); - case REACT_ASYNC_MODE_TYPE: - fiberTag = Mode; - mode |= AsyncMode | StrictMode; - break; - case REACT_STRICT_MODE_TYPE: - fiberTag = Mode; - mode |= StrictMode; - break; - case REACT_CALL_TYPE: - fiberTag = CallComponent; - break; - case REACT_RETURN_TYPE: - fiberTag = ReturnComponent; - break; - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break; - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break; - default: - if (typeof type.tag === "number") { - // Currently assumed to be a continuation and therefore is a - // fiber already. - // TODO: The yield system is currently broken for updates in - // some cases. The reified yield stores a fiber, but we don't - // know which fiber that is; the current or a workInProgress? - // When the continuation gets rendered here we don't know if we - // can reuse that fiber or if we need to clone it. There is - // probably a clever way to restructure this. - fiber = type; - fiber.pendingProps = pendingProps; - fiber.expirationTime = expirationTime; - return fiber; - } else { - throwOnInvalidElementType(type, owner); - } - break; - } - } else { - throwOnInvalidElementType(type, owner); - } - } + // Composite component methods. + return componentName + "." + phase; + } +}; + +var beginFiberMark = function(fiber, phase) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + + if (isCommitting && labelsInCurrentCommit.has(label)) { + // During the commit phase, we don't show duplicate labels because + // there is a fixed overhead for every measurement, and we don't + // want to stretch the commit phase beyond necessary. + return false; + } + labelsInCurrentCommit.add(label); + + var markName = getFiberMarkName(label, debugID); + beginMark(markName); + return true; +}; + +var clearFiberMark = function(fiber, phase) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + var markName = getFiberMarkName(label, debugID); + clearMark(markName); +}; + +var endFiberMark = function(fiber, phase, warning$$1) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + var markName = getFiberMarkName(label, debugID); + endMark(label, markName, warning$$1); +}; + +var shouldIgnoreFiber = function(fiber) { + // Host components should be skipped in the timeline. + // We could check typeof fiber.type, but does this work with RN? + switch (fiber.tag) { + case HostRoot: + case HostComponent: + case HostText: + case HostPortal: + case CallComponent: + case ReturnComponent: + case Fragment: + case ContextProvider: + case ContextConsumer: + return true; + default: + return false; + } +}; + +var clearPendingPhaseMeasurement = function() { + if (currentPhase !== null && currentPhaseFiber !== null) { + clearFiberMark(currentPhaseFiber, currentPhase); + } + currentPhaseFiber = null; + currentPhase = null; + hasScheduledUpdateInCurrentPhase = false; +}; + +var pauseTimers = function() { + // Stops all currently active measurements so that they can be resumed + // if we continue in a later deferred loop from the same unit of work. + var fiber = currentFiber; + while (fiber) { + if (fiber._debugIsCurrentlyTiming) { + endFiberMark(fiber, null, null); } + fiber = fiber["return"]; } +}; - fiber = createFiber(fiberTag, pendingProps, key, mode); - fiber.type = type; - fiber.expirationTime = expirationTime; +var resumeTimersRecursively = function(fiber) { + if (fiber["return"] !== null) { + resumeTimersRecursively(fiber["return"]); + } + if (fiber._debugIsCurrentlyTiming) { + beginFiberMark(fiber, null); + } +}; - { - fiber._debugSource = element._source; - fiber._debugOwner = element._owner; +var resumeTimers = function() { + // Resumes all measurements that were active during the last deferred loop. + if (currentFiber !== null) { + resumeTimersRecursively(currentFiber); } +}; - return fiber; +function recordEffect() { + if (enableUserTimingAPI) { + effectCountInCurrentCommit++; + } } -function throwOnInvalidElementType(type, owner) { - var info = ""; - { +function recordScheduleUpdate() { + if (enableUserTimingAPI) { + if (isCommitting) { + hasScheduledUpdateInCurrentCommit = true; + } if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) + currentPhase !== null && + currentPhase !== "componentWillMount" && + currentPhase !== "componentWillReceiveProps" ) { - info += - " You likely forgot to export your component from the file " + - "it's defined in, or you might have mixed up default and " + - "named imports."; - } - var ownerName = owner ? getComponentName(owner) : null; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; + hasScheduledUpdateInCurrentPhase = true; } } - invariant( - false, - "Element type is invalid: expected a string (for built-in " + - "components) or a class/function (for composite components) " + - "but got: %s.%s", - type == null ? type : typeof type, - info - ); } -function createFiberFromFragment(elements, mode, expirationTime, key) { - var fiber = createFiber(Fragment, elements, key, mode); - fiber.expirationTime = expirationTime; - return fiber; +function startRequestCallbackTimer() { + if (enableUserTimingAPI) { + if (supportsUserTiming && !isWaitingForCallback) { + isWaitingForCallback = true; + beginMark("(Waiting for async callback...)"); + } + } } -function createFiberFromText(content, mode, expirationTime) { - var fiber = createFiber(HostText, content, null, mode); - fiber.expirationTime = expirationTime; - return fiber; +function stopRequestCallbackTimer(didExpire, expirationTime) { + if (enableUserTimingAPI) { + if (supportsUserTiming) { + isWaitingForCallback = false; + var warning$$1 = didExpire ? "React was blocked by main thread" : null; + endMark( + "(Waiting for async callback... will force flush in " + + expirationTime + + " ms)", + "(Waiting for async callback...)", + warning$$1 + ); + } + } } -function createFiberFromHostInstanceForDeletion() { - var fiber = createFiber(HostComponent, null, null, NoContext); - fiber.type = "DELETED"; - return fiber; +function startWorkTimer(fiber) { + if (enableUserTimingAPI) { + 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; + } } -function createFiberFromPortal(portal, mode, expirationTime) { - var pendingProps = portal.children !== null ? portal.children : []; - var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); - fiber.expirationTime = expirationTime; - fiber.stateNode = { - containerInfo: portal.containerInfo, - pendingChildren: null, // Used by persistent updates - implementation: portal.implementation - }; - return fiber; -} - -// TODO: This should be lifted into the renderer. - -function createFiberRoot(containerInfo, isAsync, hydrate) { - // Cyclic construction. This cheats the type system right now because - // stateNode is any. - var uninitializedFiber = createHostRootFiber(isAsync); - var root = { - current: uninitializedFiber, - containerInfo: containerInfo, - pendingChildren: null, - pendingCommitExpirationTime: NoWork, - finishedWork: null, - context: null, - pendingContext: null, - hydrate: hydrate, - remainingExpirationTime: NoWork, - firstBatch: null, - nextScheduledRoot: null - }; - uninitializedFiber.stateNode = root; - return root; -} - -var onCommitFiberRoot = null; -var onCommitFiberUnmount = null; -var hasLoggedError = false; - -function catchErrors(fn) { - return function(arg) { - try { - return fn(arg); - } catch (err) { - if (true && !hasLoggedError) { - hasLoggedError = true; - warning(false, "React DevTools encountered an error: %s", err); - } +function cancelWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; } - }; + // Remember we shouldn't complete measurement for this fiber. + // Otherwise flamechart will be deep even for small updates. + fiber._debugIsCurrentlyTiming = false; + clearFiberMark(fiber, null); + } } -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { - // No DevTools - return false; - } - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (hook.isDisabled) { - // This isn't a real property on the hook, but it can be set to opt out - // of DevTools integration and associated warnings and logs. - // https://github.com/facebook/react/issues/3877 - return true; - } - if (!hook.supportsFiber) { - { - warning( - false, - "The installed version of React DevTools is too old and will not work " + - "with the current version of React. Please update React DevTools. " + - "https://fb.me/react-devtools" - ); +function stopWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; } - // DevTools exists, even though it doesn't support Fiber. - return true; - } - try { - var rendererID = hook.inject(internals); - // We have successfully injected, so now it is safe to set up hooks. - onCommitFiberRoot = catchErrors(function(root) { - return hook.onCommitFiberRoot(rendererID, root); - }); - onCommitFiberUnmount = catchErrors(function(fiber) { - return hook.onCommitFiberUnmount(rendererID, fiber); - }); - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - warning(false, "React DevTools encountered an error: %s.", err); + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber["return"]; + if (!fiber._debugIsCurrentlyTiming) { + return; } + fiber._debugIsCurrentlyTiming = false; + endFiberMark(fiber, null, null); } - // DevTools exists - return true; } -function onCommitRoot(root) { - if (typeof onCommitFiberRoot === "function") { - onCommitFiberRoot(root); +function stopFailedWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber["return"]; + if (!fiber._debugIsCurrentlyTiming) { + return; + } + fiber._debugIsCurrentlyTiming = false; + var warning$$1 = "An error was thrown inside this error boundary"; + endFiberMark(fiber, null, warning$$1); } } -function onCommitUnmount(fiber) { - if (typeof onCommitFiberUnmount === "function") { - onCommitFiberUnmount(fiber); +function startPhaseTimer(fiber, phase) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + clearPendingPhaseMeasurement(); + if (!beginFiberMark(fiber, phase)) { + return; + } + currentPhaseFiber = fiber; + currentPhase = phase; } } -/** - * Forked from fbjs/warning: - * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js - * - * Only change is we use console.warn instead of console.error, - * and do nothing when 'console' is not supported. - * This really simplifies the code. - * --- - * Similar to invariant but only logs a warning if the condition is not met. - * This can be used to log issues in development environments in critical - * paths. Removing the logging code for production environments will keep the - * same logic and follow the same code paths. - */ - -var lowPriorityWarning = function() {}; - -{ - var printWarning = function(format) { - for ( - var _len = arguments.length, - args = Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; +function stopPhaseTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + if (currentPhase !== null && currentPhaseFiber !== null) { + var warning$$1 = hasScheduledUpdateInCurrentPhase + ? "Scheduled a cascading update" + : null; + endFiberMark(currentPhaseFiber, currentPhase, warning$$1); } + currentPhase = null; + currentPhaseFiber = null; + } +} - var argIndex = 0; - var message = - "Warning: " + - format.replace(/%s/g, function() { - return args[argIndex++]; - }); - if (typeof console !== "undefined") { - console.warn(message); +function startWorkLoopTimer(nextUnitOfWork) { + if (enableUserTimingAPI) { + currentFiber = nextUnitOfWork; + if (!supportsUserTiming) { + return; } - try { - // --- Welcome to debugging React --- - // This error was thrown as a convenience so that you can use this stack - // to find the callsite that caused this warning to fire. - throw new Error(message); - } catch (x) {} - }; + commitCountInCurrentWorkLoop = 0; + // This is top level call. + // Any other measurements are performed within. + beginMark("(React Tree Reconciliation)"); + // Resume any measurements that were in progress during the last loop. + resumeTimers(); + } +} - lowPriorityWarning = function(condition, format) { - if (format === undefined) { - throw new Error( - "`warning(condition, format, ...args)` requires a warning " + - "message argument" - ); +function stopWorkLoopTimer(interruptedBy, didCompleteRoot) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; } - if (!condition) { - for ( - var _len2 = arguments.length, - args = Array(_len2 > 2 ? _len2 - 2 : 0), - _key2 = 2; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 2] = arguments[_key2]; + var warning$$1 = null; + if (interruptedBy !== null) { + if (interruptedBy.tag === HostRoot) { + warning$$1 = "A top-level update interrupted the previous render"; + } else { + var componentName = getComponentName(interruptedBy) || "Unknown"; + warning$$1 = + "An update to " + componentName + " interrupted the previous render"; } + } else if (commitCountInCurrentWorkLoop > 1) { + warning$$1 = "There were cascading updates"; + } + commitCountInCurrentWorkLoop = 0; + var label = didCompleteRoot + ? "(React Tree Reconciliation: Completed Root)" + : "(React Tree Reconciliation: Yielded)"; + // Pause any measurements until the next loop. + pauseTimers(); + endMark(label, "(React Tree Reconciliation)", warning$$1); + } +} - printWarning.apply(undefined, [format].concat(args)); +function startCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; } - }; + isCommitting = true; + hasScheduledUpdateInCurrentCommit = false; + labelsInCurrentCommit.clear(); + beginMark("(Committing Changes)"); + } } -var lowPriorityWarning$1 = lowPriorityWarning; +function stopCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } -var ReactStrictModeWarnings = { - discardPendingWarnings: function() {}, - flushPendingDeprecationWarnings: function() {}, - flushPendingUnsafeLifecycleWarnings: function() {}, - recordDeprecationWarnings: function(fiber, instance) {}, - recordUnsafeLifecycleWarnings: function(fiber, instance) {} -}; + var warning$$1 = null; + if (hasScheduledUpdateInCurrentCommit) { + warning$$1 = "Lifecycle hook scheduled a cascading update"; + } else if (commitCountInCurrentWorkLoop > 0) { + warning$$1 = "Caused by a cascading update in earlier commit"; + } + hasScheduledUpdateInCurrentCommit = false; + commitCountInCurrentWorkLoop++; + isCommitting = false; + labelsInCurrentCommit.clear(); -{ - var LIFECYCLE_SUGGESTIONS = { - UNSAFE_componentWillMount: "componentDidMount", - UNSAFE_componentWillReceiveProps: "static getDerivedStateFromProps", - UNSAFE_componentWillUpdate: "componentDidUpdate" - }; + endMark("(Committing Changes)", "(Committing Changes)", warning$$1); + } +} - var pendingComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUnsafeLifecycleWarnings = new Map(); +function startCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Committing Snapshot Effects)"); + } +} - // Tracks components we have already warned about. - var didWarnAboutDeprecatedLifecycles = new Set(); - var didWarnAboutUnsafeLifecycles = new Set(); +function stopCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Committing Snapshot Effects: " + count + " Total)", + "(Committing Snapshot Effects)", + null + ); + } +} - ReactStrictModeWarnings.discardPendingWarnings = function() { - pendingComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUnsafeLifecycleWarnings = new Map(); - }; +function startCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Committing Host Effects)"); + } +} - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { - pendingUnsafeLifecycleWarnings.forEach(function( - lifecycleWarningsMap, - strictRoot - ) { - var lifecyclesWarningMesages = []; +function stopCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Committing Host Effects: " + count + " Total)", + "(Committing Host Effects)", + null + ); + } +} - Object.keys(lifecycleWarningsMap).forEach(function(lifecycle) { - var lifecycleWarnings = lifecycleWarningsMap[lifecycle]; - if (lifecycleWarnings.length > 0) { - var componentNames = new Set(); - lifecycleWarnings.forEach(function(fiber) { - componentNames.add(getComponentName(fiber) || "Component"); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); +function startCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Calling Lifecycle Methods)"); + } +} - var formatted = lifecycle.replace("UNSAFE_", ""); - var suggestion = LIFECYCLE_SUGGESTIONS[lifecycle]; - var sortedComponentNames = Array.from(componentNames) - .sort() - .join(", "); +function stopCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Calling Lifecycle Methods: " + count + " Total)", + "(Calling Lifecycle Methods)", + null + ); + } +} - lifecyclesWarningMesages.push( - formatted + - ": Please update the following components to use " + - (suggestion + " instead: " + sortedComponentNames) - ); - } - }); +var didWarnUpdateInsideUpdate = void 0; - if (lifecyclesWarningMesages.length > 0) { - var strictRootComponentStack = getStackAddendumByWorkInProgressFiber( - strictRoot - ); +{ + didWarnUpdateInsideUpdate = false; +} - warning( - false, - "Unsafe lifecycle methods were found within a strict-mode tree:%s" + - "\n\n%s" + - "\n\nLearn more about this warning here:" + - "\nhttps://fb.me/react-strict-mode-warnings", - strictRootComponentStack, - lifecyclesWarningMesages.join("\n\n") - ); - } - }); +// Callbacks are not validated until invocation - pendingUnsafeLifecycleWarnings = new Map(); +// Singly linked-list of updates. When an update is scheduled, it is added to +// the queue of the current fiber and the work-in-progress fiber. The two queues +// are separate but they share a persistent structure. +// +// During reconciliation, updates are removed from the work-in-progress fiber, +// but they remain on the current fiber. That ensures that if a work-in-progress +// is aborted, the aborted updates are recovered by cloning from current. +// +// The work-in-progress queue is always a subset of the current queue. +// +// When the tree is committed, the work-in-progress becomes the current. + +function createUpdateQueue(baseState) { + var queue = { + baseState: baseState, + expirationTime: NoWork, + first: null, + last: null, + callbackList: null, + hasForceUpdate: false, + isInitialized: false, + capturedValues: null }; + { + queue.isProcessing = false; + } + return queue; +} - var getStrictRoot = function(fiber) { - var maybeStrictRoot = null; +function insertUpdateIntoQueue(queue, update) { + // Append the update to the end of the list. + if (queue.last === null) { + // Queue is empty + queue.first = queue.last = update; + } else { + queue.last.next = update; + queue.last = update; + } + if ( + queue.expirationTime === NoWork || + queue.expirationTime > update.expirationTime + ) { + queue.expirationTime = update.expirationTime; + } +} - while (fiber !== null) { - if (fiber.mode & StrictMode) { - maybeStrictRoot = fiber; - } +var q1 = void 0; +var q2 = void 0; +function ensureUpdateQueues(fiber) { + q1 = q2 = null; + // We'll have at least one and at most two distinct update queues. + var alternateFiber = fiber.alternate; + var queue1 = fiber.updateQueue; + if (queue1 === null) { + // TODO: We don't know what the base state will be until we begin work. + // It depends on which fiber is the next current. Initialize with an empty + // base state, then set to the memoizedState when rendering. Not super + // happy with this approach. + queue1 = fiber.updateQueue = createUpdateQueue(null); + } - fiber = fiber["return"]; + var queue2 = void 0; + if (alternateFiber !== null) { + queue2 = alternateFiber.updateQueue; + if (queue2 === null) { + queue2 = alternateFiber.updateQueue = createUpdateQueue(null); } + } else { + queue2 = null; + } + queue2 = queue2 !== queue1 ? queue2 : null; - return maybeStrictRoot; - }; - - ReactStrictModeWarnings.flushPendingDeprecationWarnings = function() { - if (pendingComponentWillMountWarnings.length > 0) { - var uniqueNames = new Set(); - pendingComponentWillMountWarnings.forEach(function(fiber) { - uniqueNames.add(getComponentName(fiber) || "Component"); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); + // Use module variables instead of returning a tuple + q1 = queue1; + q2 = queue2; +} - var sortedNames = Array.from(uniqueNames) - .sort() - .join(", "); +function insertUpdateIntoFiber(fiber, update) { + ensureUpdateQueues(fiber); + var queue1 = q1; + var queue2 = q2; - lowPriorityWarning$1( - false, - "componentWillMount is deprecated and will be removed in the next major version. " + - "Use componentDidMount instead. As a temporary workaround, " + - "you can rename to UNSAFE_componentWillMount." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here:" + - "\nhttps://fb.me/react-async-component-lifecycle-hooks", - sortedNames - ); - - pendingComponentWillMountWarnings = []; - } - - if (pendingComponentWillReceivePropsWarnings.length > 0) { - var _uniqueNames = new Set(); - pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { - _uniqueNames.add(getComponentName(fiber) || "Component"); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); - - var _sortedNames = Array.from(_uniqueNames) - .sort() - .join(", "); - - lowPriorityWarning$1( - false, - "componentWillReceiveProps is deprecated and will be removed in the next major version. " + - "Use static getDerivedStateFromProps instead." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here:" + - "\nhttps://fb.me/react-async-component-lifecycle-hooks", - _sortedNames - ); - - pendingComponentWillReceivePropsWarnings = []; - } - - if (pendingComponentWillUpdateWarnings.length > 0) { - var _uniqueNames2 = new Set(); - pendingComponentWillUpdateWarnings.forEach(function(fiber) { - _uniqueNames2.add(getComponentName(fiber) || "Component"); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); - - var _sortedNames2 = Array.from(_uniqueNames2) - .sort() - .join(", "); - - lowPriorityWarning$1( - false, - "componentWillUpdate is deprecated and will be removed in the next major version. " + - "Use componentDidUpdate instead. As a temporary workaround, " + - "you can rename to UNSAFE_componentWillUpdate." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here:" + - "\nhttps://fb.me/react-async-component-lifecycle-hooks", - _sortedNames2 - ); - - pendingComponentWillUpdateWarnings = []; - } - }; - - ReactStrictModeWarnings.recordDeprecationWarnings = function( - fiber, - instance - ) { - // Dedup strategy: Warn once per component. - if (didWarnAboutDeprecatedLifecycles.has(fiber.type)) { - return; - } - - // Don't warn about react-lifecycles-compat polyfilled components. - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); - } - if (typeof instance.componentWillUpdate === "function") { - pendingComponentWillUpdateWarnings.push(fiber); - } - }; - - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( - fiber, - instance - ) { - var strictRoot = getStrictRoot(fiber); - - // Dedup strategy: Warn once per component. - // This is difficult to track any other way since component names - // are often vague and are likely to collide between 3rd party libraries. - // An expand property is probably okay to use here since it's DEV-only, - // and will only be set in the event of serious warnings. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } - - // Don't warn about react-lifecycles-compat polyfilled components. - // Note that it is sufficient to check for the presence of a - // single lifecycle, componentWillMount, with the polyfill flag. - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning === true - ) { - return; - } - - var warningsForRoot = void 0; - if (!pendingUnsafeLifecycleWarnings.has(strictRoot)) { - warningsForRoot = { - UNSAFE_componentWillMount: [], - UNSAFE_componentWillReceiveProps: [], - UNSAFE_componentWillUpdate: [] - }; - - pendingUnsafeLifecycleWarnings.set(strictRoot, warningsForRoot); - } else { - warningsForRoot = pendingUnsafeLifecycleWarnings.get(strictRoot); - } - - var unsafeLifecycles = []; - if ( - typeof instance.componentWillMount === "function" || - typeof instance.UNSAFE_componentWillMount === "function" - ) { - unsafeLifecycles.push("UNSAFE_componentWillMount"); - } - if ( - typeof instance.componentWillReceiveProps === "function" || - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - unsafeLifecycles.push("UNSAFE_componentWillReceiveProps"); - } - if ( - typeof instance.componentWillUpdate === "function" || - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - unsafeLifecycles.push("UNSAFE_componentWillUpdate"); - } - - if (unsafeLifecycles.length > 0) { - unsafeLifecycles.forEach(function(lifecycle) { - warningsForRoot[lifecycle].push(fiber); - }); - } - }; -} - -var didWarnUpdateInsideUpdate = void 0; - -{ - didWarnUpdateInsideUpdate = false; -} - -// Callbacks are not validated until invocation - -// Singly linked-list of updates. When an update is scheduled, it is added to -// the queue of the current fiber and the work-in-progress fiber. The two queues -// are separate but they share a persistent structure. -// -// During reconciliation, updates are removed from the work-in-progress fiber, -// but they remain on the current fiber. That ensures that if a work-in-progress -// is aborted, the aborted updates are recovered by cloning from current. -// -// The work-in-progress queue is always a subset of the current queue. -// -// When the tree is committed, the work-in-progress becomes the current. - -function createUpdateQueue(baseState) { - var queue = { - baseState: baseState, - expirationTime: NoWork, - first: null, - last: null, - callbackList: null, - hasForceUpdate: false, - isInitialized: false, - capturedValues: null - }; - { - queue.isProcessing = false; - } - return queue; -} - -function insertUpdateIntoQueue(queue, update) { - // Append the update to the end of the list. - if (queue.last === null) { - // Queue is empty - queue.first = queue.last = update; - } else { - queue.last.next = update; - queue.last = update; - } - if ( - queue.expirationTime === NoWork || - queue.expirationTime > update.expirationTime - ) { - queue.expirationTime = update.expirationTime; - } -} - -var q1 = void 0; -var q2 = void 0; -function ensureUpdateQueues(fiber) { - q1 = q2 = null; - // We'll have at least one and at most two distinct update queues. - var alternateFiber = fiber.alternate; - var queue1 = fiber.updateQueue; - if (queue1 === null) { - // TODO: We don't know what the base state will be until we begin work. - // It depends on which fiber is the next current. Initialize with an empty - // base state, then set to the memoizedState when rendering. Not super - // happy with this approach. - queue1 = fiber.updateQueue = createUpdateQueue(null); - } - - var queue2 = void 0; - if (alternateFiber !== null) { - queue2 = alternateFiber.updateQueue; - if (queue2 === null) { - queue2 = alternateFiber.updateQueue = createUpdateQueue(null); - } - } else { - queue2 = null; - } - queue2 = queue2 !== queue1 ? queue2 : null; - - // Use module variables instead of returning a tuple - q1 = queue1; - q2 = queue2; -} - -function insertUpdateIntoFiber(fiber, update) { - ensureUpdateQueues(fiber); - var queue1 = q1; - var queue2 = q2; - - // Warn if an update is scheduled from inside an updater function. - { - if ( - (queue1.isProcessing || (queue2 !== null && queue2.isProcessing)) && - !didWarnUpdateInsideUpdate - ) { - warning( + // Warn if an update is scheduled from inside an updater function. + { + if ( + (queue1.isProcessing || (queue2 !== null && queue2.isProcessing)) && + !didWarnUpdateInsideUpdate + ) { + warning( false, "An update (setState, replaceState, or forceUpdate) was scheduled " + "from inside an update function. Update functions should be pure, " + @@ -6102,23 +5865,26 @@ var isArray = Array.isArray; var didWarnAboutStateAssignmentForComponent = void 0; var didWarnAboutUndefinedDerivedState = void 0; var didWarnAboutUninitializedState = void 0; -var didWarnAboutWillReceivePropsAndDerivedState = void 0; +var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = void 0; +var didWarnAboutLegacyLifecyclesAndDerivedState = void 0; var warnOnInvalidCallback = void 0; { - didWarnAboutStateAssignmentForComponent = {}; - didWarnAboutUndefinedDerivedState = {}; - didWarnAboutUninitializedState = {}; - didWarnAboutWillReceivePropsAndDerivedState = {}; + didWarnAboutStateAssignmentForComponent = new Set(); + didWarnAboutUndefinedDerivedState = new Set(); + didWarnAboutUninitializedState = new Set(); + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); + didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); - var didWarnOnInvalidCallback = {}; + var didWarnOnInvalidCallback = new Set(); warnOnInvalidCallback = function(callback, callerName) { if (callback === null || typeof callback === "function") { return; } var key = callerName + "_" + callback; - if (!didWarnOnInvalidCallback[key]) { + if (!didWarnOnInvalidCallback.has(key)) { + didWarnOnInvalidCallback.add(key); warning( false, "%s(...): Expected the last optional `callback` argument to be a " + @@ -6126,7 +5892,6 @@ var warnOnInvalidCallback = void 0; callerName, callback ); - didWarnOnInvalidCallback[key] = true; } }; @@ -6165,12 +5930,20 @@ function callGetDerivedStateFromCatch(ctor, capturedValues) { } var ReactFiberClassComponent = function( + legacyContext, scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState ) { + var cacheContext = legacyContext.cacheContext, + getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + isContextConsumer = legacyContext.isContextConsumer, + hasContextChanged = legacyContext.hasContextChanged; + // Class component state updater + var updater = { isMounted: isMounted, enqueueSetState: function(instance, partialState, callback) { @@ -6261,12 +6034,14 @@ var ReactFiberClassComponent = function( stopPhaseTimer(); { - warning( - shouldUpdate !== undefined, - "%s.shouldComponentUpdate(): Returned undefined instead of a " + - "boolean value. Make sure to return true or false.", - getComponentName(workInProgress) || "Unknown" - ); + !(shouldUpdate !== undefined) + ? warning( + false, + "%s.shouldComponentUpdate(): Returned undefined instead of a " + + "boolean value. Make sure to return true or false.", + getComponentName(workInProgress) || "Component" + ) + : void 0; } return shouldUpdate; @@ -6285,7 +6060,7 @@ var ReactFiberClassComponent = function( var instance = workInProgress.stateNode; var type = workInProgress.type; { - var name = getComponentName(workInProgress); + var name = getComponentName(workInProgress) || "Component"; var renderPresent = instance.render; if (!renderPresent) { @@ -6310,47 +6085,57 @@ var ReactFiberClassComponent = function( !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state; - warning( - noGetInitialStateOnES6, - "getInitialState was defined on %s, a plain JavaScript class. " + - "This is only supported for classes created using React.createClass. " + - "Did you mean to define a state property instead?", - name - ); - var noGetDefaultPropsOnES6 = + !noGetInitialStateOnES6 + ? warning( + false, + "getInitialState was defined on %s, a plain JavaScript class. " + + "This is only supported for classes created using React.createClass. " + + "Did you mean to define a state property instead?", + name + ) + : void 0; + var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved; - warning( - noGetDefaultPropsOnES6, - "getDefaultProps was defined on %s, a plain JavaScript class. " + - "This is only supported for classes created using React.createClass. " + - "Use a static property to define defaultProps instead.", - name - ); + !noGetDefaultPropsOnES6 + ? warning( + false, + "getDefaultProps was defined on %s, a plain JavaScript class. " + + "This is only supported for classes created using React.createClass. " + + "Use a static property to define defaultProps instead.", + name + ) + : void 0; var noInstancePropTypes = !instance.propTypes; - warning( - noInstancePropTypes, - "propTypes was defined as an instance property on %s. Use a static " + - "property to define propTypes instead.", - name - ); + !noInstancePropTypes + ? warning( + false, + "propTypes was defined as an instance property on %s. Use a static " + + "property to define propTypes instead.", + name + ) + : void 0; var noInstanceContextTypes = !instance.contextTypes; - warning( - noInstanceContextTypes, - "contextTypes was defined as an instance property on %s. Use a static " + - "property to define contextTypes instead.", - name - ); + !noInstanceContextTypes + ? warning( + false, + "contextTypes was defined as an instance property on %s. Use a static " + + "property to define contextTypes instead.", + name + ) + : void 0; var noComponentShouldUpdate = typeof instance.componentShouldUpdate !== "function"; - warning( - noComponentShouldUpdate, - "%s has a method called " + - "componentShouldUpdate(). Did you mean shouldComponentUpdate()? " + - "The name is phrased as a question because the function is " + - "expected to return a value.", - name - ); + !noComponentShouldUpdate + ? warning( + false, + "%s has a method called " + + "componentShouldUpdate(). Did you mean shouldComponentUpdate()? " + + "The name is phrased as a question because the function is " + + "expected to return a value.", + name + ) + : void 0; if ( type.prototype && type.prototype.isPureReactComponent && @@ -6366,73 +6151,128 @@ var ReactFiberClassComponent = function( } var noComponentDidUnmount = typeof instance.componentDidUnmount !== "function"; - warning( - noComponentDidUnmount, - "%s has a method called " + - "componentDidUnmount(). But there is no such lifecycle method. " + - "Did you mean componentWillUnmount()?", - name - ); + !noComponentDidUnmount + ? warning( + false, + "%s has a method called " + + "componentDidUnmount(). But there is no such lifecycle method. " + + "Did you mean componentWillUnmount()?", + name + ) + : void 0; var noComponentDidReceiveProps = typeof instance.componentDidReceiveProps !== "function"; - warning( - noComponentDidReceiveProps, - "%s has a method called " + - "componentDidReceiveProps(). But there is no such lifecycle method. " + - "If you meant to update the state in response to changing props, " + - "use componentWillReceiveProps(). If you meant to fetch data or " + - "run side-effects or mutations after React has updated the UI, use componentDidUpdate().", - name - ); + !noComponentDidReceiveProps + ? warning( + false, + "%s has a method called " + + "componentDidReceiveProps(). But there is no such lifecycle method. " + + "If you meant to update the state in response to changing props, " + + "use componentWillReceiveProps(). If you meant to fetch data or " + + "run side-effects or mutations after React has updated the UI, use componentDidUpdate().", + name + ) + : void 0; var noComponentWillRecieveProps = typeof instance.componentWillRecieveProps !== "function"; - warning( - noComponentWillRecieveProps, - "%s has a method called " + - "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", - name - ); + !noComponentWillRecieveProps + ? warning( + false, + "%s has a method called " + + "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", + name + ) + : void 0; var noUnsafeComponentWillRecieveProps = typeof instance.UNSAFE_componentWillRecieveProps !== "function"; - warning( - noUnsafeComponentWillRecieveProps, - "%s has a method called " + - "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", - name - ); + !noUnsafeComponentWillRecieveProps + ? warning( + false, + "%s has a method called " + + "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", + name + ) + : void 0; var hasMutatedProps = instance.props !== workInProgress.pendingProps; - warning( - instance.props === undefined || !hasMutatedProps, - "%s(...): When calling super() in `%s`, make sure to pass " + - "up the same props that your component's constructor was passed.", - name, - name - ); + !(instance.props === undefined || !hasMutatedProps) + ? warning( + false, + "%s(...): When calling super() in `%s`, make sure to pass " + + "up the same props that your component's constructor was passed.", + name, + name + ) + : void 0; var noInstanceDefaultProps = !instance.defaultProps; - warning( - noInstanceDefaultProps, - "Setting defaultProps as an instance property on %s is not supported and will be ignored." + - " Instead, define defaultProps as a static property on %s.", - name, - name - ); - } + !noInstanceDefaultProps + ? warning( + false, + "Setting defaultProps as an instance property on %s is not supported and will be ignored." + + " Instead, define defaultProps as a static property on %s.", + name, + name + ) + : void 0; - var state = instance.state; - if (state && (typeof state !== "object" || isArray(state))) { - warning( - false, - "%s.state: must be set to an object or null", - getComponentName(workInProgress) - ); - } - if (typeof instance.getChildContext === "function") { - warning( - typeof type.childContextTypes === "object", - "%s.getChildContext(): childContextTypes must be defined in order to " + - "use getChildContext().", - getComponentName(workInProgress) - ); + if ( + typeof instance.getSnapshotBeforeUpdate === "function" && + typeof instance.componentDidUpdate !== "function" && + typeof instance.componentDidUpdate !== "function" && + !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(type) + ) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(type); + warning( + false, + "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + + "This component defines getSnapshotBeforeUpdate() only.", + getComponentName(workInProgress) + ); + } + + var noInstanceGetDerivedStateFromProps = + typeof instance.getDerivedStateFromProps !== "function"; + !noInstanceGetDerivedStateFromProps + ? warning( + false, + "%s: getDerivedStateFromProps() is defined as an instance method " + + "and will be ignored. Instead, declare it as a static method.", + name + ) + : void 0; + var noInstanceGetDerivedStateFromCatch = + typeof instance.getDerivedStateFromCatch !== "function"; + !noInstanceGetDerivedStateFromCatch + ? warning( + false, + "%s: getDerivedStateFromCatch() is defined as an instance method " + + "and will be ignored. Instead, declare it as a static method.", + name + ) + : void 0; + var noStaticGetSnapshotBeforeUpdate = + typeof type.getSnapshotBeforeUpdate !== "function"; + !noStaticGetSnapshotBeforeUpdate + ? warning( + false, + "%s: getSnapshotBeforeUpdate() is defined as a static method " + + "and will be ignored. Instead, declare it as an instance method.", + name + ) + : void 0; + var _state = instance.state; + if (_state && (typeof _state !== "object" || isArray(_state))) { + warning(false, "%s.state: must be set to an object or null", name); + } + if (typeof instance.getChildContext === "function") { + !(typeof type.childContextTypes === "object") + ? warning( + false, + "%s.getChildContext(): childContextTypes must be defined in order to " + + "use getChildContext().", + name + ) + : void 0; + } } } @@ -6480,8 +6320,9 @@ var ReactFiberClassComponent = function( typeof ctor.getDerivedStateFromProps === "function" && state === null ) { - var componentName = getComponentName(workInProgress) || "Unknown"; - if (!didWarnAboutUninitializedState[componentName]) { + var componentName = getComponentName(workInProgress) || "Component"; + if (!didWarnAboutUninitializedState.has(componentName)) { + didWarnAboutUninitializedState.add(componentName); warning( false, "%s: Did not properly initialize state during construction. " + @@ -6489,7 +6330,75 @@ var ReactFiberClassComponent = function( componentName, instance.state === null ? "null" : "undefined" ); - didWarnAboutUninitializedState[componentName] = true; + } + } + + // If new component APIs are defined, "unsafe" lifecycles won't be called. + // Warn about these lifecycles if they are present. + // Don't warn about react-lifecycles-compat polyfilled methods though. + if ( + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function" + ) { + var foundWillMountName = null; + var foundWillReceivePropsName = null; + var foundWillUpdateName = null; + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + foundWillMountName = "componentWillMount"; + } else if (typeof instance.UNSAFE_componentWillMount === "function") { + foundWillMountName = "UNSAFE_componentWillMount"; + } + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + foundWillReceivePropsName = "componentWillReceiveProps"; + } else if ( + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + } + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + foundWillUpdateName = "componentWillUpdate"; + } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { + foundWillUpdateName = "UNSAFE_componentWillUpdate"; + } + if ( + foundWillMountName !== null || + foundWillReceivePropsName !== null || + foundWillUpdateName !== null + ) { + var _componentName = getComponentName(workInProgress) || "Component"; + var newApiName = + typeof ctor.getDerivedStateFromProps === "function" + ? "getDerivedStateFromProps()" + : "getSnapshotBeforeUpdate()"; + if ( + !didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName) + ) { + didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); + warning( + false, + "Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n" + + "%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n" + + "The above lifecycles should be removed. Learn more about this warning here:\n" + + "https://fb.me/react-async-component-lifecycle-hooks", + _componentName, + newApiName, + foundWillMountName !== null ? "\n " + foundWillMountName : "", + foundWillReceivePropsName !== null + ? "\n " + foundWillReceivePropsName + : "", + foundWillUpdateName !== null ? "\n " + foundWillUpdateName : "" + ); + } } } } @@ -6499,7 +6408,8 @@ var ReactFiberClassComponent = function( var partialState = callGetDerivedStateFromProps( workInProgress, instance, - props + props, + state ); if (partialState !== null && partialState !== undefined) { @@ -6542,7 +6452,7 @@ var ReactFiberClassComponent = function( "%s.componentWillMount(): Assigning directly to this.state is " + "deprecated (except inside a component's " + "constructor). Use setState instead.", - getComponentName(workInProgress) + getComponentName(workInProgress) || "Component" ); } updater.enqueueReplaceState(instance, instance.state, null); @@ -6568,7 +6478,8 @@ var ReactFiberClassComponent = function( if (instance.state !== oldState) { { var componentName = getComponentName(workInProgress) || "Component"; - if (!didWarnAboutStateAssignmentForComponent[componentName]) { + if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { + didWarnAboutStateAssignmentForComponent.add(componentName); warning( false, "%s.componentWillReceiveProps(): Assigning directly to " + @@ -6576,69 +6487,47 @@ var ReactFiberClassComponent = function( "constructor). Use setState instead.", componentName ); - didWarnAboutStateAssignmentForComponent[componentName] = true; } } updater.enqueueReplaceState(instance, instance.state, null); } } - function callGetDerivedStateFromProps(workInProgress, instance, props) { + function callGetDerivedStateFromProps( + workInProgress, + instance, + nextProps, + prevState + ) { var type = workInProgress.type; if (typeof type.getDerivedStateFromProps === "function") { - { - // Don't warn about react-lifecycles-compat polyfilled components - if ( - (typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== - true) || - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - var componentName = getComponentName(workInProgress) || "Unknown"; - if (!didWarnAboutWillReceivePropsAndDerivedState[componentName]) { - warning( - false, - "%s: Defines both componentWillReceiveProps() and static " + - "getDerivedStateFromProps() methods. We recommend using " + - "only getDerivedStateFromProps().", - componentName - ); - didWarnAboutWillReceivePropsAndDerivedState[componentName] = true; - } - } - } - if ( debugRenderPhaseSideEffects || (debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictMode) ) { // Invoke method an extra time to help detect side-effects. - type.getDerivedStateFromProps.call( - null, - props, - workInProgress.memoizedState - ); + type.getDerivedStateFromProps.call(null, nextProps, prevState); } var partialState = type.getDerivedStateFromProps.call( null, - props, - workInProgress.memoizedState + nextProps, + prevState ); { if (partialState === undefined) { - var _componentName = getComponentName(workInProgress) || "Unknown"; - if (!didWarnAboutUndefinedDerivedState[_componentName]) { + var componentName = getComponentName(workInProgress) || "Component"; + if (!didWarnAboutUndefinedDerivedState.has(componentName)) { + didWarnAboutUndefinedDerivedState.add(componentName); warning( false, "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + "You have returned undefined.", - _componentName + componentName ); - didWarnAboutUndefinedDerivedState[_componentName] = _componentName; } } } @@ -6682,11 +6571,12 @@ var ReactFiberClassComponent = function( } // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( + typeof ctor.getDerivedStateFromProps !== "function" && + typeof instance.getSnapshotBeforeUpdate !== "function" && (typeof instance.UNSAFE_componentWillMount === "function" || - typeof instance.componentWillMount === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + typeof instance.componentWillMount === "function") ) { callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's @@ -6719,16 +6609,20 @@ var ReactFiberClassComponent = function( var newUnmaskedContext = getUnmaskedContext(workInProgress); var newContext = getMaskedContext(workInProgress, newUnmaskedContext); + var hasNewLifecycles = + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function"; + // Note: During these life-cycles, instance.props/instance.state are what // ever the previously attempted to render - not the "current". However, // during componentDidUpdate we pass the "current" props. // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( + !hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + typeof instance.componentWillReceiveProps === "function") ) { if (oldProps !== newProps || oldContext !== newContext) { callComponentWillReceiveProps( @@ -6740,15 +6634,6 @@ var ReactFiberClassComponent = function( } } - var derivedStateFromProps = void 0; - if (oldProps !== newProps) { - derivedStateFromProps = callGetDerivedStateFromProps( - workInProgress, - instance, - newProps - ); - } - // Compute the next state using the memoized state and the update queue. var oldState = workInProgress.memoizedState; // TODO: Previous state can be null. @@ -6785,6 +6670,18 @@ var ReactFiberClassComponent = function( newState = oldState; } + var derivedStateFromProps = void 0; + if (oldProps !== newProps) { + // The prevState parameter should be the partially updated state. + // Otherwise, spreading state in return values could override updates. + derivedStateFromProps = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + newState + ); + } + if (derivedStateFromProps !== null && derivedStateFromProps !== undefined) { // Render-phase updates (like this) should not be added to the update queue, // So that multiple render passes do not enqueue multiple updates. @@ -6793,6 +6690,17 @@ var ReactFiberClassComponent = function( newState === null || newState === undefined ? derivedStateFromProps : Object.assign({}, newState, derivedStateFromProps); + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue = workInProgress.updateQueue; + if (_updateQueue !== null) { + _updateQueue.baseState = Object.assign( + {}, + _updateQueue.baseState, + derivedStateFromProps + ); + } } if (derivedStateFromCatch !== null && derivedStateFromCatch !== undefined) { // Render-phase updates (like this) should not be added to the update queue, @@ -6802,6 +6710,17 @@ var ReactFiberClassComponent = function( newState === null || newState === undefined ? derivedStateFromCatch : Object.assign({}, newState, derivedStateFromCatch); + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue2 = workInProgress.updateQueue; + if (_updateQueue2 !== null) { + _updateQueue2.baseState = Object.assign( + {}, + _updateQueue2.baseState, + derivedStateFromCatch + ); + } } if ( @@ -6832,22 +6751,22 @@ var ReactFiberClassComponent = function( if (shouldUpdate) { // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( - (typeof instance.UNSAFE_componentWillUpdate === "function" || - typeof instance.componentWillUpdate === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillMount === "function" || + typeof instance.componentWillMount === "function") ) { - startPhaseTimer(workInProgress, "componentWillUpdate"); - if (typeof instance.componentWillUpdate === "function") { - instance.componentWillUpdate(newProps, newState, newContext); + startPhaseTimer(workInProgress, "componentWillMount"); + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); } - if (typeof instance.UNSAFE_componentWillUpdate === "function") { - instance.UNSAFE_componentWillUpdate(newProps, newState, newContext); + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); } stopPhaseTimer(); } - if (typeof instance.componentDidUpdate === "function") { + if (typeof instance.componentDidMount === "function") { workInProgress.effectTag |= Update; } } else { @@ -6884,16 +6803,20 @@ var ReactFiberClassComponent = function( var newUnmaskedContext = getUnmaskedContext(workInProgress); var newContext = getMaskedContext(workInProgress, newUnmaskedContext); + var hasNewLifecycles = + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function"; + // Note: During these life-cycles, instance.props/instance.state are what // ever the previously attempted to render - not the "current". However, // during componentDidUpdate we pass the "current" props. // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( + !hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + typeof instance.componentWillReceiveProps === "function") ) { if (oldProps !== newProps || oldContext !== newContext) { callComponentWillReceiveProps( @@ -6905,20 +6828,12 @@ var ReactFiberClassComponent = function( } } - var derivedStateFromProps = void 0; - if (oldProps !== newProps) { - derivedStateFromProps = callGetDerivedStateFromProps( - workInProgress, - instance, - newProps - ); - } - // Compute the next state using the memoized state and the update queue. var oldState = workInProgress.memoizedState; // TODO: Previous state can be null. var newState = void 0; var derivedStateFromCatch = void 0; + if (workInProgress.updateQueue !== null) { newState = processUpdateQueue( current, @@ -6950,6 +6865,18 @@ var ReactFiberClassComponent = function( newState = oldState; } + var derivedStateFromProps = void 0; + if (oldProps !== newProps) { + // The prevState parameter should be the partially updated state. + // Otherwise, spreading state in return values could override updates. + derivedStateFromProps = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + newState + ); + } + if (derivedStateFromProps !== null && derivedStateFromProps !== undefined) { // Render-phase updates (like this) should not be added to the update queue, // So that multiple render passes do not enqueue multiple updates. @@ -6958,6 +6885,17 @@ var ReactFiberClassComponent = function( newState === null || newState === undefined ? derivedStateFromProps : Object.assign({}, newState, derivedStateFromProps); + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue3 = workInProgress.updateQueue; + if (_updateQueue3 !== null) { + _updateQueue3.baseState = Object.assign( + {}, + _updateQueue3.baseState, + derivedStateFromProps + ); + } } if (derivedStateFromCatch !== null && derivedStateFromCatch !== undefined) { // Render-phase updates (like this) should not be added to the update queue, @@ -6967,6 +6905,17 @@ var ReactFiberClassComponent = function( newState === null || newState === undefined ? derivedStateFromCatch : Object.assign({}, newState, derivedStateFromCatch); + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue4 = workInProgress.updateQueue; + if (_updateQueue4 !== null) { + _updateQueue4.baseState = Object.assign( + {}, + _updateQueue4.baseState, + derivedStateFromCatch + ); + } } if ( @@ -6988,6 +6937,14 @@ var ReactFiberClassComponent = function( workInProgress.effectTag |= Update; } } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Snapshot; + } + } return false; } @@ -7002,11 +6959,11 @@ var ReactFiberClassComponent = function( if (shouldUpdate) { // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( + !hasNewLifecycles && (typeof instance.UNSAFE_componentWillUpdate === "function" || - typeof instance.componentWillUpdate === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + typeof instance.componentWillUpdate === "function") ) { startPhaseTimer(workInProgress, "componentWillUpdate"); if (typeof instance.componentWillUpdate === "function") { @@ -7020,6 +6977,9 @@ var ReactFiberClassComponent = function( if (typeof instance.componentDidUpdate === "function") { workInProgress.effectTag |= Update; } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + workInProgress.effectTag |= Snapshot; + } } else { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. @@ -7031,6 +6991,14 @@ var ReactFiberClassComponent = function( workInProgress.effectTag |= Update; } } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Snapshot; + } + } // If shouldComponentUpdate returned false, we should still update the // memoized props/state to indicate that this work can be reused. @@ -7870,13 +7838,15 @@ function ChildReconciler(shouldTrackSideEffects) { if (typeof newChildrenIterable.entries === "function") { var possibleMap = newChildrenIterable; if (possibleMap.entries === iteratorFn) { - warning( - didWarnAboutMaps, - "Using Maps as children is unsupported and will likely yield " + - "unexpected results. Convert it to a sequence/iterable of keyed " + - "ReactElements instead.%s", - getCurrentFiberStackAddendum$1() - ); + !didWarnAboutMaps + ? warning( + false, + "Using Maps as children is unsupported and will likely yield " + + "unexpected results. Convert it to a sequence/iterable of keyed " + + "ReactElements instead.%s", + getCurrentFiberStackAddendum$1() + ) + : void 0; didWarnAboutMaps = true; } } @@ -8318,71 +8288,6 @@ function cloneChildFibers(current, workInProgress) { newChild.sibling = null; } -var changedBitsStack = []; -var currentValueStack = []; -var stack = []; -var index$1 = -1; - -var rendererSigil = void 0; -{ - // Use this to detect multiple renderers using the same context - rendererSigil = {}; -} - -function pushProvider(providerFiber) { - var context = providerFiber.type.context; - index$1 += 1; - changedBitsStack[index$1] = context._changedBits; - currentValueStack[index$1] = context._currentValue; - stack[index$1] = providerFiber; - context._currentValue = providerFiber.pendingProps.value; - context._changedBits = providerFiber.stateNode; - - { - warning( - context._currentRenderer === null || - context._currentRenderer === rendererSigil, - "Detected multiple renderers concurrently rendering the " + - "same context provider. This is currently unsupported." - ); - context._currentRenderer = rendererSigil; - } -} - -function popProvider(providerFiber) { - { - warning( - index$1 > -1 && providerFiber === stack[index$1], - "Unexpected pop." - ); - } - var changedBits = changedBitsStack[index$1]; - var currentValue = currentValueStack[index$1]; - changedBitsStack[index$1] = null; - currentValueStack[index$1] = null; - stack[index$1] = null; - index$1 -= 1; - var context = providerFiber.type.context; - context._currentValue = currentValue; - context._changedBits = changedBits; -} - -function resetProviderStack() { - for (var i = index$1; i > -1; i--) { - var providerFiber = stack[i]; - var context = providerFiber.type.context; - context._currentValue = context._defaultValue; - context._changedBits = 0; - changedBitsStack[i] = null; - currentValueStack[i] = null; - stack[i] = null; - { - context._currentRenderer = null; - } - } - index$1 = -1; -} - var didWarnAboutBadClass = void 0; var didWarnAboutGetDerivedStateOnFunctionalComponent = void 0; var didWarnAboutStatelessRefs = void 0; @@ -8396,6 +8301,8 @@ var didWarnAboutStatelessRefs = void 0; var ReactFiberBeginWork = function( config, hostContext, + legacyContext, + newContext, hydrationContext, scheduleWork, computeExpirationForFiber @@ -8404,12 +8311,20 @@ var ReactFiberBeginWork = function( shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree; var pushHostContext = hostContext.pushHostContext, pushHostContainer = hostContext.pushHostContainer; + var pushProvider = newContext.pushProvider; + var getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + hasLegacyContextChanged = legacyContext.hasContextChanged, + pushLegacyContextProvider = legacyContext.pushContextProvider, + pushTopLevelContextObject = legacyContext.pushTopLevelContextObject, + invalidateContextProvider = legacyContext.invalidateContextProvider; var enterHydrationState = hydrationContext.enterHydrationState, resetHydrationState = hydrationContext.resetHydrationState, tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance; var _ReactFiberClassCompo = ReactFiberClassComponent( + legacyContext, scheduleWork, computeExpirationForFiber, memoizeProps, @@ -8467,9 +8382,17 @@ var ReactFiberBeginWork = function( } } + function updateForwardRef(current, workInProgress) { + var render = workInProgress.type.render; + var nextChildren = render(workInProgress.pendingProps, workInProgress.ref); + reconcileChildren(current, workInProgress, nextChildren); + memoizeProps(workInProgress, nextChildren); + return workInProgress.child; + } + function updateFragment(current, workInProgress) { var nextChildren = workInProgress.pendingProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (workInProgress.memoizedProps === nextChildren) { @@ -8482,7 +8405,7 @@ var ReactFiberBeginWork = function( function updateMode(current, workInProgress) { var nextChildren = workInProgress.pendingProps.children; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if ( @@ -8511,7 +8434,7 @@ var ReactFiberBeginWork = function( var fn = workInProgress.type; var nextProps = workInProgress.pendingProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else { @@ -8544,7 +8467,7 @@ var ReactFiberBeginWork = function( // Push context providers early to prevent context stack mismatches. // During mounting we don't know the child context yet as the instance doesn't exist. // We will invalidate the child context in finishClassComponent() right after rendering. - var hasContext = pushContextProvider(workInProgress); + var hasContext = pushLegacyContextProvider(workInProgress); var shouldUpdate = void 0; if (current === null) { if (workInProgress.stateNode === null) { @@ -8769,7 +8692,7 @@ var ReactFiberBeginWork = function( var nextProps = workInProgress.pendingProps; var prevProps = current !== null ? current.memoizedProps : null; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (memoizedProps === nextProps) { @@ -8889,7 +8812,8 @@ var ReactFiberBeginWork = function( var partialState = callGetDerivedStateFromProps( workInProgress, value, - props + props, + workInProgress.memoizedState ); if (partialState !== null && partialState !== undefined) { @@ -8904,7 +8828,7 @@ var ReactFiberBeginWork = function( // Push context providers early to prevent context stack mismatches. // During mounting we don't know the child context yet as the instance doesn't exist. // We will invalidate the child context in finishClassComponent() right after rendering. - var hasContext = pushContextProvider(workInProgress); + var hasContext = pushLegacyContextProvider(workInProgress); adoptClassInstance(workInProgress, value); mountClassInstance(workInProgress, renderExpirationTime); return finishClassComponent( @@ -8922,11 +8846,13 @@ var ReactFiberBeginWork = function( var _Component = workInProgress.type; if (_Component) { - warning( - !_Component.childContextTypes, - "%s(...): childContextTypes cannot be defined on a functional component.", - _Component.displayName || _Component.name || "Component" - ); + !!_Component.childContextTypes + ? warning( + false, + "%s(...): childContextTypes cannot be defined on a functional component.", + _Component.displayName || _Component.name || "Component" + ) + : void 0; } if (workInProgress.ref !== null) { var info = ""; @@ -8977,7 +8903,7 @@ var ReactFiberBeginWork = function( function updateCallComponent(current, workInProgress, renderExpirationTime) { var nextProps = workInProgress.pendingProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (workInProgress.memoizedProps === nextProps) { @@ -9020,7 +8946,7 @@ var ReactFiberBeginWork = function( ) { pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); var nextChildren = workInProgress.pendingProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (workInProgress.memoizedProps === nextChildren) { @@ -9054,6 +8980,10 @@ var ReactFiberBeginWork = function( renderExpirationTime ) { var fiber = workInProgress.child; + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber["return"] = workInProgress; + } while (fiber !== null) { var nextFiber = void 0; // Visit this fiber. @@ -9141,12 +9071,12 @@ var ReactFiberBeginWork = function( renderExpirationTime ) { var providerType = workInProgress.type; - var context = providerType.context; + var context = providerType._context; var newProps = workInProgress.pendingProps; var oldProps = workInProgress.memoizedProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (oldProps === newProps) { @@ -9194,12 +9124,14 @@ var ReactFiberBeginWork = function( ? context._calculateChangedBits(oldValue, newValue) : MAX_SIGNED_31_BIT_INT; { - warning( - (changedBits & MAX_SIGNED_31_BIT_INT) === changedBits, - "calculateChangedBits: Expected the return value to be a " + - "31-bit integer. Instead received: %s", - changedBits - ); + !((changedBits & MAX_SIGNED_31_BIT_INT) === changedBits) + ? warning( + false, + "calculateChangedBits: Expected the return value to be a " + + "31-bit integer. Instead received: %s", + changedBits + ) + : void 0; } changedBits |= 0; @@ -9242,7 +9174,7 @@ var ReactFiberBeginWork = function( var newValue = context._currentValue; var changedBits = context._changedBits; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (changedBits === 0 && oldProps === newProps) { @@ -9267,21 +9199,23 @@ var ReactFiberBeginWork = function( changedBits, renderExpirationTime ); - } else if (oldProps !== null && oldProps.children === newProps.children) { - // No change. Bailout early if children are the same. - return bailoutOnAlreadyFinishedWork(current, workInProgress); } + // There is no bailout on `children` equality because we expect people + // to often pass a bound method as a child, but it may reference + // `this.state` or `this.props` (and thus needs to re-render on `setState`). var render = newProps.children; { - warning( - typeof render === "function", - "A context consumer was rendered with multiple children, or a child " + - "that isn't a function. A context consumer expects a single child " + - "that is a function. If you did pass a function, make sure there " + - "is no trailing or leading whitespace around it." - ); + !(typeof render === "function") + ? warning( + false, + "A context consumer was rendered with multiple children, or a child " + + "that isn't a function. A context consumer expects a single child " + + "that is a function. If you did pass a function, make sure there " + + "is no trailing or leading whitespace around it." + ) + : void 0; } var newChildren = render(newValue); @@ -9339,7 +9273,7 @@ var ReactFiberBeginWork = function( pushHostRootContext(workInProgress); break; case ClassComponent: - pushContextProvider(workInProgress); + pushLegacyContextProvider(workInProgress); break; case HostPortal: pushHostContainer( @@ -9420,6 +9354,8 @@ var ReactFiberBeginWork = function( workInProgress, renderExpirationTime ); + case ForwardRef: + return updateForwardRef(current, workInProgress); case Fragment: return updateFragment(current, workInProgress); case Mode: @@ -9450,7 +9386,13 @@ var ReactFiberBeginWork = function( }; }; -var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { +var ReactFiberCompleteWork = function( + config, + hostContext, + legacyContext, + newContext, + hydrationContext +) { var createInstance = config.createInstance, createTextInstance = config.createTextInstance, appendInitialChild = config.appendInitialChild, @@ -9462,6 +9404,9 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { popHostContext = hostContext.popHostContext, getHostContext = hostContext.getHostContext, popHostContainer = hostContext.popHostContainer; + var popLegacyContextProvider = legacyContext.popContextProvider, + popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject; + var popProvider = newContext.popProvider; var prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance, prepareToHydrateHostTextInstance = @@ -9777,7 +9722,7 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { return null; case ClassComponent: { // We are leaving this subtree, so pop context if any. - popContextProvider(workInProgress); + popLegacyContextProvider(workInProgress); // If this component caught an error, schedule an error log effect. var instance = workInProgress.stateNode; @@ -9796,7 +9741,7 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { } case HostRoot: { popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); + popTopLevelLegacyContextObject(workInProgress); var fiberRoot = workInProgress.stateNode; if (fiberRoot.pendingContext) { fiberRoot.context = fiberRoot.pendingContext; @@ -9972,6 +9917,8 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { case ReturnComponent: // Does nothing. return null; + case ForwardRef: + return null; case Fragment: return null; case Mode: @@ -10021,11 +9968,16 @@ function createCapturedValue(value, source) { var ReactFiberUnwindWork = function( hostContext, + legacyContext, + newContext, scheduleWork, isAlreadyFailedLegacyErrorBoundary ) { var popHostContainer = hostContext.popHostContainer, popHostContext = hostContext.popHostContext; + var popLegacyContextProvider = legacyContext.popContextProvider, + popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject; + var popProvider = newContext.popProvider; function throwException(returnFiber, sourceFiber, rawValue) { // The source fiber did not complete. @@ -10081,7 +10033,7 @@ var ReactFiberUnwindWork = function( function unwindWork(workInProgress) { switch (workInProgress.tag) { case ClassComponent: { - popContextProvider(workInProgress); + popLegacyContextProvider(workInProgress); var effectTag = workInProgress.effectTag; if (effectTag & ShouldCapture) { workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture; @@ -10091,7 +10043,7 @@ var ReactFiberUnwindWork = function( } case HostRoot: { popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); + popTopLevelLegacyContextObject(workInProgress); var _effectTag = workInProgress.effectTag; if (_effectTag & ShouldCapture) { workInProgress.effectTag = (_effectTag & ~ShouldCapture) | DidCapture; @@ -10113,9 +10065,37 @@ var ReactFiberUnwindWork = function( return null; } } + + function unwindInterruptedWork(interruptedWork) { + switch (interruptedWork.tag) { + case ClassComponent: { + popLegacyContextProvider(interruptedWork); + break; + } + case HostRoot: { + popHostContainer(interruptedWork); + popTopLevelLegacyContextObject(interruptedWork); + break; + } + case HostComponent: { + popHostContext(interruptedWork); + break; + } + case HostPortal: + popHostContainer(interruptedWork); + break; + case ContextProvider: + popProvider(interruptedWork); + break; + default: + break; + } + } + return { throwException: throwException, - unwindWork: unwindWork + unwindWork: unwindWork, + unwindInterruptedWork: unwindInterruptedWork }; }; @@ -10190,8 +10170,13 @@ var invokeGuardedCallback$3 = ReactErrorUtils.invokeGuardedCallback; var hasCaughtError$1 = ReactErrorUtils.hasCaughtError; var clearCaughtError$1 = ReactErrorUtils.clearCaughtError; -function logError(boundary, errorInfo) { - var source = errorInfo.source; +var didWarnAboutUndefinedSnapshotBeforeUpdate = null; +{ + didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); +} + +function logError(boundary, errorInfo) { + var source = errorInfo.source; var stack = errorInfo.stack; if (stack === null) { stack = getStackAddendumByWorkInProgressFiber(source); @@ -10199,21 +10184,19 @@ function logError(boundary, errorInfo) { var capturedError = { componentName: source !== null ? getComponentName(source) : null, - error: errorInfo.value, - errorBoundary: boundary, componentStack: stack !== null ? stack : "", + error: errorInfo.value, + errorBoundary: null, errorBoundaryName: null, errorBoundaryFound: false, willRetry: false }; - if (boundary !== null) { + if (boundary !== null && boundary.tag === ClassComponent) { + capturedError.errorBoundary = boundary.stateNode; capturedError.errorBoundaryName = getComponentName(boundary); - capturedError.errorBoundaryFound = capturedError.willRetry = - boundary.tag === ClassComponent; - } else { - capturedError.errorBoundaryName = null; - capturedError.errorBoundaryFound = capturedError.willRetry = false; + capturedError.errorBoundaryFound = true; + capturedError.willRetry = true; } try { @@ -10277,7 +10260,59 @@ var ReactFiberCommitWork = function( } } } else { - ref.value = null; + ref.current = null; + } + } + } + + function commitBeforeMutationLifeCycles(current, finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: { + if (finishedWork.effectTag & Snapshot) { + if (current !== null) { + var prevProps = current.memoizedProps; + var prevState = current.memoizedState; + startPhaseTimer(finishedWork, "getSnapshotBeforeUpdate"); + var _instance = finishedWork.stateNode; + _instance.props = finishedWork.memoizedProps; + _instance.state = finishedWork.memoizedState; + var snapshot = _instance.getSnapshotBeforeUpdate( + prevProps, + prevState + ); + { + var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; + if ( + snapshot === undefined && + !didWarnSet.has(finishedWork.type) + ) { + didWarnSet.add(finishedWork.type); + warning( + false, + "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + + "must be returned. You have returned undefined.", + getComponentName(finishedWork) + ); + } + } + _instance.__reactInternalSnapshotBeforeUpdate = snapshot; + stopPhaseTimer(); + } + } + return; + } + case HostRoot: + case HostComponent: + case HostText: + case HostPortal: + // Nothing to do for these component types + return; + default: { + invariant( + false, + "This unit of work tag should not have side-effects. This error is " + + "likely caused by a bug in React. Please file an issue." + ); } } } @@ -10291,50 +10326,54 @@ var ReactFiberCommitWork = function( ) { switch (finishedWork.tag) { case ClassComponent: { - var _instance = finishedWork.stateNode; + var _instance2 = finishedWork.stateNode; if (finishedWork.effectTag & Update) { if (current === null) { startPhaseTimer(finishedWork, "componentDidMount"); - _instance.props = finishedWork.memoizedProps; - _instance.state = finishedWork.memoizedState; - _instance.componentDidMount(); + _instance2.props = finishedWork.memoizedProps; + _instance2.state = finishedWork.memoizedState; + _instance2.componentDidMount(); stopPhaseTimer(); } else { var prevProps = current.memoizedProps; var prevState = current.memoizedState; startPhaseTimer(finishedWork, "componentDidUpdate"); - _instance.props = finishedWork.memoizedProps; - _instance.state = finishedWork.memoizedState; - _instance.componentDidUpdate(prevProps, prevState); + _instance2.props = finishedWork.memoizedProps; + _instance2.state = finishedWork.memoizedState; + _instance2.componentDidUpdate( + prevProps, + prevState, + _instance2.__reactInternalSnapshotBeforeUpdate + ); stopPhaseTimer(); } } var updateQueue = finishedWork.updateQueue; if (updateQueue !== null) { - commitCallbacks(updateQueue, _instance); + commitCallbacks(updateQueue, _instance2); } return; } case HostRoot: { var _updateQueue = finishedWork.updateQueue; if (_updateQueue !== null) { - var _instance2 = null; + var _instance3 = null; if (finishedWork.child !== null) { switch (finishedWork.child.tag) { case HostComponent: - _instance2 = getPublicInstance(finishedWork.child.stateNode); + _instance3 = getPublicInstance(finishedWork.child.stateNode); break; case ClassComponent: - _instance2 = finishedWork.child.stateNode; + _instance3 = finishedWork.child.stateNode; break; } } - commitCallbacks(_updateQueue, _instance2); + commitCallbacks(_updateQueue, _instance3); } return; } case HostComponent: { - var _instance3 = finishedWork.stateNode; + var _instance4 = finishedWork.stateNode; // Renderers may schedule work to be done after host components are mounted // (eg DOM renderer may schedule auto-focus for inputs and form controls). @@ -10343,7 +10382,7 @@ var ReactFiberCommitWork = function( if (current === null && finishedWork.effectTag & Update) { var type = finishedWork.type; var props = finishedWork.memoizedProps; - commitMount(_instance3, type, props, finishedWork); + commitMount(_instance4, type, props, finishedWork); } return; @@ -10371,7 +10410,7 @@ var ReactFiberCommitWork = function( case ClassComponent: { var ctor = finishedWork.type; - var _instance4 = finishedWork.stateNode; + var _instance5 = finishedWork.stateNode; var updateQueue = finishedWork.updateQueue; invariant( updateQueue !== null && updateQueue.capturedValues !== null, @@ -10388,16 +10427,19 @@ var ReactFiberCommitWork = function( // This gets reset before we yield back to the browser. // TODO: Warn in strict mode if getDerivedStateFromCatch is // not defined. - markLegacyErrorBoundaryAsFailed(_instance4); + markLegacyErrorBoundaryAsFailed(_instance5); } - _instance4.props = finishedWork.memoizedProps; - _instance4.state = finishedWork.memoizedState; + _instance5.props = finishedWork.memoizedProps; + _instance5.state = finishedWork.memoizedState; for (var i = 0; i < capturedErrors.length; i++) { var errorInfo = capturedErrors[i]; var _error = errorInfo.value; + var stack = errorInfo.stack; logError(finishedWork, errorInfo); - _instance4.componentDidCatch(_error); + _instance5.componentDidCatch(_error, { + componentStack: stack !== null ? stack : "" + }); } } break; @@ -10430,19 +10472,31 @@ var ReactFiberCommitWork = function( function commitAttachRef(finishedWork) { var ref = finishedWork.ref; if (ref !== null) { - var _instance5 = finishedWork.stateNode; + var _instance6 = finishedWork.stateNode; var instanceToUse = void 0; switch (finishedWork.tag) { case HostComponent: - instanceToUse = getPublicInstance(_instance5); + instanceToUse = getPublicInstance(_instance6); break; default: - instanceToUse = _instance5; + instanceToUse = _instance6; } if (typeof ref === "function") { ref(instanceToUse); } else { - ref.value = instanceToUse; + { + if (!ref.hasOwnProperty("current")) { + warning( + false, + "Unexpected ref object provided for %s. " + + "Use either a ref-setter function or React.createRef().%s", + getComponentName(finishedWork), + getStackAddendumByWorkInProgressFiber(finishedWork) + ); + } + } + + ref.current = instanceToUse; } } } @@ -10453,7 +10507,7 @@ var ReactFiberCommitWork = function( if (typeof currentRef === "function") { currentRef(null); } else { - currentRef.value = null; + currentRef.current = null; } } } @@ -10469,9 +10523,9 @@ var ReactFiberCommitWork = function( switch (current.tag) { case ClassComponent: { safelyDetachRef(current); - var _instance6 = current.stateNode; - if (typeof _instance6.componentWillUnmount === "function") { - safelyCallComponentWillUnmount(current, _instance6); + var _instance7 = current.stateNode; + if (typeof _instance7.componentWillUnmount === "function") { + safelyCallComponentWillUnmount(current, _instance7); } return; } @@ -10608,6 +10662,7 @@ var ReactFiberCommitWork = function( }, commitLifeCycles: commitLifeCycles, + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, commitErrorLogging: commitErrorLogging, commitAttachRef: commitAttachRef, commitDetachRef: commitDetachRef @@ -10767,635 +10822,1063 @@ var ReactFiberCommitWork = function( } } - function unmountHostComponents(current) { - // We only have the top Fiber that was inserted but we need recurse down its - var node = current; + function unmountHostComponents(current) { + // We only have the top Fiber that was inserted but we need recurse down its + var node = current; + + // Each iteration, currentParent is populated with node's host parent if not + // currentParentIsValid. + var currentParentIsValid = false; + var currentParent = void 0; + var currentParentIsContainer = void 0; + + while (true) { + if (!currentParentIsValid) { + var parent = node["return"]; + findParent: while (true) { + invariant( + parent !== null, + "Expected to find a host parent. This error is likely caused by " + + "a bug in React. Please file an issue." + ); + switch (parent.tag) { + case HostComponent: + currentParent = parent.stateNode; + currentParentIsContainer = false; + break findParent; + case HostRoot: + currentParent = parent.stateNode.containerInfo; + currentParentIsContainer = true; + break findParent; + case HostPortal: + currentParent = parent.stateNode.containerInfo; + currentParentIsContainer = true; + break findParent; + } + parent = parent["return"]; + } + currentParentIsValid = true; + } + + if (node.tag === HostComponent || node.tag === HostText) { + commitNestedUnmounts(node); + // After all the children have unmounted, it is now safe to remove the + // node from the tree. + if (currentParentIsContainer) { + removeChildFromContainer(currentParent, node.stateNode); + } else { + removeChild(currentParent, node.stateNode); + } + // Don't visit children because we already visited them. + } else if (node.tag === HostPortal) { + // When we go into a portal, it becomes the parent to remove from. + // We will reassign it back when we pop the portal on the way up. + currentParent = node.stateNode.containerInfo; + // Visit children because portals might contain host components. + if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + } else { + commitUnmount(node); + // Visit children because we may find more host components below. + if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + } + if (node === current) { + return; + } + while (node.sibling === null) { + if (node["return"] === null || node["return"] === current) { + return; + } + node = node["return"]; + if (node.tag === HostPortal) { + // When we go out of the portal, we need to restore the parent. + // Since we don't keep a stack of them, we will search for it. + currentParentIsValid = false; + } + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + + function commitDeletion(current) { + // Recursively delete all host nodes from the parent. + // Detach refs and call componentWillUnmount() on the whole subtree. + unmountHostComponents(current); + detachFiber(current); + } + + function commitWork(current, finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: { + return; + } + case HostComponent: { + var _instance8 = finishedWork.stateNode; + if (_instance8 != null) { + // Commit the work prepared earlier. + var newProps = finishedWork.memoizedProps; + // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + var oldProps = current !== null ? current.memoizedProps : newProps; + var type = finishedWork.type; + // TODO: Type the updateQueue to be specific to host components. + var updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + if (updatePayload !== null) { + commitUpdate( + _instance8, + updatePayload, + type, + oldProps, + newProps, + finishedWork + ); + } + } + return; + } + case HostText: { + invariant( + finishedWork.stateNode !== null, + "This should have a text node initialized. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + var textInstance = finishedWork.stateNode; + var newText = finishedWork.memoizedProps; + // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + var oldText = current !== null ? current.memoizedProps : newText; + commitTextUpdate(textInstance, oldText, newText); + return; + } + case HostRoot: { + return; + } + default: { + invariant( + false, + "This unit of work tag should not have side-effects. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } + } + + function commitResetTextContent(current) { + resetTextContent(current.stateNode); + } + + if (enableMutatingReconciler) { + return { + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, + commitResetTextContent: commitResetTextContent, + commitPlacement: commitPlacement, + commitDeletion: commitDeletion, + commitWork: commitWork, + commitLifeCycles: commitLifeCycles, + commitErrorLogging: commitErrorLogging, + commitAttachRef: commitAttachRef, + commitDetachRef: commitDetachRef + }; + } else { + invariant(false, "Mutating reconciler is disabled."); + } +}; + +var NO_CONTEXT = {}; + +var ReactFiberHostContext = function(config, stack) { + var getChildHostContext = config.getChildHostContext, + getRootHostContext = config.getRootHostContext; + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop; + + var contextStackCursor = createCursor(NO_CONTEXT); + var contextFiberStackCursor = createCursor(NO_CONTEXT); + var rootInstanceStackCursor = createCursor(NO_CONTEXT); + + function requiredContext(c) { + invariant( + c !== NO_CONTEXT, + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + return c; + } + + function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; + } + + function pushHostContainer(fiber, nextRootInstance) { + // Push current root instance onto the stack; + // This allows us to reset root when portals are popped. + push(rootInstanceStackCursor, nextRootInstance, fiber); + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + + // Finally, we need to push the host context to the stack. + // However, we can't just call getRootHostContext() and push it because + // we'd have a different number of entries on the stack depending on + // whether getRootHostContext() throws somewhere in renderer code or not. + // So we push an empty value first. This lets us safely unwind on errors. + push(contextStackCursor, NO_CONTEXT, fiber); + var nextRootContext = getRootHostContext(nextRootInstance); + // Now that we know this function doesn't throw, replace it. + pop(contextStackCursor, fiber); + push(contextStackCursor, nextRootContext, fiber); + } + + function popHostContainer(fiber) { + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + } + + function getHostContext() { + var context = requiredContext(contextStackCursor.current); + return context; + } + + function pushHostContext(fiber) { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + var context = requiredContext(contextStackCursor.current); + var nextContext = getChildHostContext(context, fiber.type, rootInstance); + + // Don't push this Fiber's context unless it's unique. + if (context === nextContext) { + return; + } + + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, nextContext, fiber); + } + + function popHostContext(fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + if (contextFiberStackCursor.current !== fiber) { + return; + } + + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + } + + return { + getHostContext: getHostContext, + getRootHostContainer: getRootHostContainer, + popHostContainer: popHostContainer, + popHostContext: popHostContext, + pushHostContainer: pushHostContainer, + pushHostContext: pushHostContext + }; +}; + +var ReactFiberHydrationContext = function(config) { + var shouldSetTextContent = config.shouldSetTextContent, + hydration = config.hydration; + + // If this doesn't have hydration mode. + + if (!hydration) { + return { + enterHydrationState: function() { + return false; + }, + resetHydrationState: function() {}, + tryToClaimNextHydratableInstance: function() {}, + prepareToHydrateHostInstance: function() { + invariant( + false, + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + }, + prepareToHydrateHostTextInstance: function() { + invariant( + false, + "Expected prepareToHydrateHostTextInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + }, + popHydrationState: function(fiber) { + return false; + } + }; + } + + var canHydrateInstance = hydration.canHydrateInstance, + canHydrateTextInstance = hydration.canHydrateTextInstance, + getNextHydratableSibling = hydration.getNextHydratableSibling, + getFirstHydratableChild = hydration.getFirstHydratableChild, + hydrateInstance = hydration.hydrateInstance, + hydrateTextInstance = hydration.hydrateTextInstance, + didNotMatchHydratedContainerTextInstance = + hydration.didNotMatchHydratedContainerTextInstance, + didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance, + didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance, + didNotHydrateInstance = hydration.didNotHydrateInstance, + didNotFindHydratableContainerInstance = + hydration.didNotFindHydratableContainerInstance, + didNotFindHydratableContainerTextInstance = + hydration.didNotFindHydratableContainerTextInstance, + didNotFindHydratableInstance = hydration.didNotFindHydratableInstance, + didNotFindHydratableTextInstance = + hydration.didNotFindHydratableTextInstance; + + // The deepest Fiber on the stack involved in a hydration context. + // This may have been an insertion or a hydration. + + var hydrationParentFiber = null; + var nextHydratableInstance = null; + var isHydrating = false; + + function enterHydrationState(fiber) { + var parentInstance = fiber.stateNode.containerInfo; + nextHydratableInstance = getFirstHydratableChild(parentInstance); + hydrationParentFiber = fiber; + isHydrating = true; + return true; + } + + function deleteHydratableInstance(returnFiber, instance) { + { + switch (returnFiber.tag) { + case HostRoot: + didNotHydrateContainerInstance( + returnFiber.stateNode.containerInfo, + instance + ); + break; + case HostComponent: + didNotHydrateInstance( + returnFiber.type, + returnFiber.memoizedProps, + returnFiber.stateNode, + instance + ); + break; + } + } + + var childToDelete = createFiberFromHostInstanceForDeletion(); + childToDelete.stateNode = instance; + childToDelete["return"] = returnFiber; + childToDelete.effectTag = Deletion; + + // This might seem like it belongs on progressedFirstDeletion. However, + // these children are not part of the reconciliation list of children. + // Even if we abort and rereconcile the children, that will try to hydrate + // again and the nodes are still in the host tree so these will be + // recreated. + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = childToDelete; + returnFiber.lastEffect = childToDelete; + } else { + returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; + } + } + + function insertNonHydratedInstance(returnFiber, fiber) { + fiber.effectTag |= Placement; + { + switch (returnFiber.tag) { + case HostRoot: { + var parentContainer = returnFiber.stateNode.containerInfo; + switch (fiber.tag) { + case HostComponent: + var type = fiber.type; + var props = fiber.pendingProps; + didNotFindHydratableContainerInstance( + parentContainer, + type, + props + ); + break; + case HostText: + var text = fiber.pendingProps; + didNotFindHydratableContainerTextInstance(parentContainer, text); + break; + } + break; + } + case HostComponent: { + var parentType = returnFiber.type; + var parentProps = returnFiber.memoizedProps; + var parentInstance = returnFiber.stateNode; + switch (fiber.tag) { + case HostComponent: + var _type = fiber.type; + var _props = fiber.pendingProps; + didNotFindHydratableInstance( + parentType, + parentProps, + parentInstance, + _type, + _props + ); + break; + case HostText: + var _text = fiber.pendingProps; + didNotFindHydratableTextInstance( + parentType, + parentProps, + parentInstance, + _text + ); + break; + } + break; + } + default: + return; + } + } + } + + function tryHydrate(fiber, nextInstance) { + switch (fiber.tag) { + case HostComponent: { + var type = fiber.type; + var props = fiber.pendingProps; + var instance = canHydrateInstance(nextInstance, type, props); + if (instance !== null) { + fiber.stateNode = instance; + return true; + } + return false; + } + case HostText: { + var text = fiber.pendingProps; + var textInstance = canHydrateTextInstance(nextInstance, text); + if (textInstance !== null) { + fiber.stateNode = textInstance; + return true; + } + return false; + } + default: + return false; + } + } + + function tryToClaimNextHydratableInstance(fiber) { + if (!isHydrating) { + return; + } + var nextInstance = nextHydratableInstance; + if (!nextInstance) { + // Nothing to hydrate. Make it an insertion. + insertNonHydratedInstance(hydrationParentFiber, fiber); + isHydrating = false; + hydrationParentFiber = fiber; + return; + } + if (!tryHydrate(fiber, nextInstance)) { + // If we can't hydrate this instance let's try the next one. + // We use this as a heuristic. It's based on intuition and not data so it + // might be flawed or unnecessary. + nextInstance = getNextHydratableSibling(nextInstance); + if (!nextInstance || !tryHydrate(fiber, nextInstance)) { + // Nothing to hydrate. Make it an insertion. + insertNonHydratedInstance(hydrationParentFiber, fiber); + isHydrating = false; + hydrationParentFiber = fiber; + return; + } + // We matched the next one, we'll now assume that the first one was + // superfluous and we'll delete it. Since we can't eagerly delete it + // we'll have to schedule a deletion. To do that, this node needs a dummy + // fiber associated with it. + deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance); + } + hydrationParentFiber = fiber; + nextHydratableInstance = getFirstHydratableChild(nextInstance); + } + + function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext + ) { + var instance = fiber.stateNode; + var updatePayload = hydrateInstance( + instance, + fiber.type, + fiber.memoizedProps, + rootContainerInstance, + hostContext, + fiber + ); + // TODO: Type this specific to this type of component. + fiber.updateQueue = updatePayload; + // If the update payload indicates that there is a change or if there + // is a new ref we mark this as an update. + if (updatePayload !== null) { + return true; + } + return false; + } + + function prepareToHydrateHostTextInstance(fiber) { + var textInstance = fiber.stateNode; + var textContent = fiber.memoizedProps; + var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber); + { + if (shouldUpdate) { + // We assume that prepareToHydrateHostTextInstance is called in a context where the + // hydration parent is the parent host component of this host text. + var returnFiber = hydrationParentFiber; + if (returnFiber !== null) { + switch (returnFiber.tag) { + case HostRoot: { + var parentContainer = returnFiber.stateNode.containerInfo; + didNotMatchHydratedContainerTextInstance( + parentContainer, + textInstance, + textContent + ); + break; + } + case HostComponent: { + var parentType = returnFiber.type; + var parentProps = returnFiber.memoizedProps; + var parentInstance = returnFiber.stateNode; + didNotMatchHydratedTextInstance( + parentType, + parentProps, + parentInstance, + textInstance, + textContent + ); + break; + } + } + } + } + } + return shouldUpdate; + } + + function popToNextHostParent(fiber) { + var parent = fiber["return"]; + while ( + parent !== null && + parent.tag !== HostComponent && + parent.tag !== HostRoot + ) { + parent = parent["return"]; + } + hydrationParentFiber = parent; + } + + function popHydrationState(fiber) { + if (fiber !== hydrationParentFiber) { + // We're deeper than the current hydration context, inside an inserted + // tree. + return false; + } + if (!isHydrating) { + // If we're not currently hydrating but we're in a hydration context, then + // we were an insertion and now need to pop up reenter hydration of our + // siblings. + popToNextHostParent(fiber); + isHydrating = true; + return false; + } + + var type = fiber.type; + + // If we have any remaining hydratable nodes, we need to delete them now. + // We only do this deeper than head and body since they tend to have random + // other nodes in them. We also ignore components with pure text content in + // side of them. + // TODO: Better heuristic. + if ( + fiber.tag !== HostComponent || + (type !== "head" && + type !== "body" && + !shouldSetTextContent(type, fiber.memoizedProps)) + ) { + var nextInstance = nextHydratableInstance; + while (nextInstance) { + deleteHydratableInstance(fiber, nextInstance); + nextInstance = getNextHydratableSibling(nextInstance); + } + } + + popToNextHostParent(fiber); + nextHydratableInstance = hydrationParentFiber + ? getNextHydratableSibling(fiber.stateNode) + : null; + return true; + } + + function resetHydrationState() { + hydrationParentFiber = null; + nextHydratableInstance = null; + isHydrating = false; + } - // Each iteration, currentParent is populated with node's host parent if not - // currentParentIsValid. - var currentParentIsValid = false; - var currentParent = void 0; - var currentParentIsContainer = void 0; + return { + enterHydrationState: enterHydrationState, + resetHydrationState: resetHydrationState, + tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance, + prepareToHydrateHostInstance: prepareToHydrateHostInstance, + prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance, + popHydrationState: popHydrationState + }; +}; - while (true) { - if (!currentParentIsValid) { - var parent = node["return"]; - findParent: while (true) { - invariant( - parent !== null, - "Expected to find a host parent. This error is likely caused by " + - "a bug in React. Please file an issue." - ); - switch (parent.tag) { - case HostComponent: - currentParent = parent.stateNode; - currentParentIsContainer = false; - break findParent; - case HostRoot: - currentParent = parent.stateNode.containerInfo; - currentParentIsContainer = true; - break findParent; - case HostPortal: - currentParent = parent.stateNode.containerInfo; - currentParentIsContainer = true; - break findParent; - } - parent = parent["return"]; - } - currentParentIsValid = true; - } +// This lets us hook into Fiber to debug what it's doing. +// See https://github.com/facebook/react/pull/8033. +// This is not part of the public API, not even for React DevTools. +// You may only inject a debugTool if you work on React Fiber itself. +var ReactFiberInstrumentation = { + debugTool: null +}; - if (node.tag === HostComponent || node.tag === HostText) { - commitNestedUnmounts(node); - // After all the children have unmounted, it is now safe to remove the - // node from the tree. - if (currentParentIsContainer) { - removeChildFromContainer(currentParent, node.stateNode); - } else { - removeChild(currentParent, node.stateNode); - } - // Don't visit children because we already visited them. - } else if (node.tag === HostPortal) { - // When we go into a portal, it becomes the parent to remove from. - // We will reassign it back when we pop the portal on the way up. - currentParent = node.stateNode.containerInfo; - // Visit children because portals might contain host components. - if (node.child !== null) { - node.child["return"] = node; - node = node.child; - continue; - } - } else { - commitUnmount(node); - // Visit children because we may find more host components below. - if (node.child !== null) { - node.child["return"] = node; - node = node.child; - continue; - } - } - if (node === current) { - return; - } - while (node.sibling === null) { - if (node["return"] === null || node["return"] === current) { - return; - } - node = node["return"]; - if (node.tag === HostPortal) { - // When we go out of the portal, we need to restore the parent. - // Since we don't keep a stack of them, we will search for it. - currentParentIsValid = false; - } - } - node.sibling["return"] = node["return"]; - node = node.sibling; +var ReactFiberInstrumentation_1 = ReactFiberInstrumentation; + +var warnedAboutMissingGetChildContext = void 0; + +{ + warnedAboutMissingGetChildContext = {}; +} + +var ReactFiberLegacyContext = function(stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop; + + // A cursor to the current merged context object on the stack. + + var contextStackCursor = createCursor(emptyObject); + // A cursor to a boolean indicating whether the context has changed. + var didPerformWorkStackCursor = createCursor(false); + // Keep track of the previous context object that was on the stack. + // We use this to get access to the parent context after we have already + // pushed the next context provider, and now need to merge their contexts. + var previousContext = emptyObject; + + function getUnmaskedContext(workInProgress) { + var hasOwnContext = isContextProvider(workInProgress); + if (hasOwnContext) { + // If the fiber is a context provider itself, when we read its context + // we have already pushed its own child context on the stack. A context + // provider should not "see" its own child context. Therefore we read the + // previous (parent) context instead for a context provider. + return previousContext; } + return contextStackCursor.current; } - function commitDeletion(current) { - // Recursively delete all host nodes from the parent. - // Detach refs and call componentWillUnmount() on the whole subtree. - unmountHostComponents(current); - detachFiber(current); + function cacheContext(workInProgress, unmaskedContext, maskedContext) { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; } - function commitWork(current, finishedWork) { - switch (finishedWork.tag) { - case ClassComponent: { - return; - } - case HostComponent: { - var _instance7 = finishedWork.stateNode; - if (_instance7 != null) { - // Commit the work prepared earlier. - var newProps = finishedWork.memoizedProps; - // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. - var oldProps = current !== null ? current.memoizedProps : newProps; - var type = finishedWork.type; - // TODO: Type the updateQueue to be specific to host components. - var updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null; - if (updatePayload !== null) { - commitUpdate( - _instance7, - updatePayload, - type, - oldProps, - newProps, - finishedWork - ); - } - } - return; - } - case HostText: { - invariant( - finishedWork.stateNode !== null, - "This should have a text node initialized. This error is likely " + - "caused by a bug in React. Please file an issue." - ); - var textInstance = finishedWork.stateNode; - var newText = finishedWork.memoizedProps; - // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. - var oldText = current !== null ? current.memoizedProps : newText; - commitTextUpdate(textInstance, oldText, newText); - return; - } - case HostRoot: { - return; - } - default: { - invariant( - false, - "This unit of work tag should not have side-effects. This error is " + - "likely caused by a bug in React. Please file an issue." - ); - } + function getMaskedContext(workInProgress, unmaskedContext) { + var type = workInProgress.type; + var contextTypes = type.contextTypes; + if (!contextTypes) { + return emptyObject; + } + + // Avoid recreating masked context unless unmasked context has changed. + // Failing to do this will result in unnecessary calls to componentWillReceiveProps. + // This may trigger infinite loops if componentWillReceiveProps calls setState. + var instance = workInProgress.stateNode; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) { + return instance.__reactInternalMemoizedMaskedChildContext; + } + + var context = {}; + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; + } + + { + var name = getComponentName(workInProgress) || "Unknown"; + checkPropTypes( + contextTypes, + context, + "context", + name, + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + ); + } + + // Cache unmasked context so we can avoid recreating masked context unless necessary. + // Context is created before the class component is instantiated so check for instance. + if (instance) { + cacheContext(workInProgress, unmaskedContext, context); } + + return context; } - function commitResetTextContent(current) { - resetTextContent(current.stateNode); + function hasContextChanged() { + return didPerformWorkStackCursor.current; } - if (enableMutatingReconciler) { - return { - commitResetTextContent: commitResetTextContent, - commitPlacement: commitPlacement, - commitDeletion: commitDeletion, - commitWork: commitWork, - commitLifeCycles: commitLifeCycles, - commitErrorLogging: commitErrorLogging, - commitAttachRef: commitAttachRef, - commitDetachRef: commitDetachRef - }; - } else { - invariant(false, "Mutating reconciler is disabled."); + function isContextConsumer(fiber) { + return fiber.tag === ClassComponent && fiber.type.contextTypes != null; } -}; -var NO_CONTEXT = {}; + function isContextProvider(fiber) { + return fiber.tag === ClassComponent && fiber.type.childContextTypes != null; + } -var ReactFiberHostContext = function(config) { - var getChildHostContext = config.getChildHostContext, - getRootHostContext = config.getRootHostContext; + function popContextProvider(fiber) { + if (!isContextProvider(fiber)) { + return; + } - var contextStackCursor = createCursor(NO_CONTEXT); - var contextFiberStackCursor = createCursor(NO_CONTEXT); - var rootInstanceStackCursor = createCursor(NO_CONTEXT); + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + } - function requiredContext(c) { + function popTopLevelContextObject(fiber) { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + } + + function pushTopLevelContextObject(fiber, context, didChange) { invariant( - c !== NO_CONTEXT, - "Expected host context to exist. This error is likely caused by a bug " + - "in React. Please file an issue." + contextStackCursor.cursor == null, + "Unexpected context found on stack. " + + "This error is likely caused by a bug in React. Please file an issue." ); - return c; + + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); } - function getRootHostContainer() { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - return rootInstance; + function processChildContext(fiber, parentContext) { + var instance = fiber.stateNode; + var childContextTypes = fiber.type.childContextTypes; + + // TODO (bvaughn) Replace this behavior with an invariant() in the future. + // It has only been added in Fiber to match the (unintentional) behavior in Stack. + if (typeof instance.getChildContext !== "function") { + { + var componentName = getComponentName(fiber) || "Unknown"; + + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; + warning( + false, + "%s.childContextTypes is specified but there is no getChildContext() method " + + "on the instance. You can either define getChildContext() on %s or remove " + + "childContextTypes from it.", + componentName, + componentName + ); + } + } + return parentContext; + } + + var childContext = void 0; + { + ReactDebugCurrentFiber.setCurrentPhase("getChildContext"); + } + startPhaseTimer(fiber, "getChildContext"); + childContext = instance.getChildContext(); + stopPhaseTimer(); + { + ReactDebugCurrentFiber.setCurrentPhase(null); + } + for (var contextKey in childContext) { + invariant( + contextKey in childContextTypes, + '%s.getChildContext(): key "%s" is not defined in childContextTypes.', + getComponentName(fiber) || "Unknown", + contextKey + ); + } + { + var name = getComponentName(fiber) || "Unknown"; + checkPropTypes( + childContextTypes, + childContext, + "child context", + name, + // In practice, there is one case in which we won't get a stack. It's when + // somebody calls unstable_renderSubtreeIntoContainer() and we process + // context from the parent component instance. The stack will be missing + // because it's outside of the reconciliation, and so the pointer has not + // been set. This is rare and doesn't matter. We'll also remove that API. + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + ); + } + + return Object.assign({}, parentContext, childContext); } - function pushHostContainer(fiber, nextRootInstance) { - // Push current root instance onto the stack; - // This allows us to reset root when portals are popped. - push(rootInstanceStackCursor, nextRootInstance, fiber); - - var nextRootContext = getRootHostContext(nextRootInstance); - - // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor, nextRootContext, fiber); - } + function pushContextProvider(workInProgress) { + if (!isContextProvider(workInProgress)) { + return false; + } - function popHostContainer(fiber) { - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); - pop(rootInstanceStackCursor, fiber); - } + var instance = workInProgress.stateNode; + // We push the context as early as possible to ensure stack integrity. + // If the instance does not exist yet, we will push null at first, + // and replace it on the stack later when invalidating the context. + var memoizedMergedChildContext = + (instance && instance.__reactInternalMemoizedMergedChildContext) || + emptyObject; + + // Remember the parent context so we can merge with it later. + // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. + previousContext = contextStackCursor.current; + push(contextStackCursor, memoizedMergedChildContext, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); - function getHostContext() { - var context = requiredContext(contextStackCursor.current); - return context; + return true; } - function pushHostContext(fiber) { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - var context = requiredContext(contextStackCursor.current); - var nextContext = getChildHostContext(context, fiber.type, rootInstance); + function invalidateContextProvider(workInProgress, didChange) { + var instance = workInProgress.stateNode; + invariant( + instance, + "Expected to have an instance by this point. " + + "This error is likely caused by a bug in React. Please file an issue." + ); - // Don't push this Fiber's context unless it's unique. - if (context === nextContext) { - return; + if (didChange) { + // Merge parent and own context. + // Skip this if we're not updating due to sCU. + // This avoids unnecessarily recomputing memoized values. + var mergedContext = processChildContext(workInProgress, previousContext); + instance.__reactInternalMemoizedMergedChildContext = mergedContext; + + // Replace the old (or empty) context with the new one. + // It is important to unwind the context in the reverse order. + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); + // Now push the new context and mark that it has changed. + push(contextStackCursor, mergedContext, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } else { + pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); } - - // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor, nextContext, fiber); } - function popHostContext(fiber) { - // Do not pop unless this Fiber provided the current context. - // pushHostContext() only pushes Fibers that provide unique contexts. - if (contextFiberStackCursor.current !== fiber) { - return; - } - - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); - } + function findCurrentUnmaskedContext(fiber) { + // Currently this is only used with renderSubtreeIntoContainer; not sure if it + // makes sense elsewhere + invariant( + isFiberMounted(fiber) && fiber.tag === ClassComponent, + "Expected subtree parent to be a mounted class component. " + + "This error is likely caused by a bug in React. Please file an issue." + ); - function resetHostContainer() { - contextStackCursor.current = NO_CONTEXT; - rootInstanceStackCursor.current = NO_CONTEXT; + var node = fiber; + while (node.tag !== HostRoot) { + if (isContextProvider(node)) { + return node.stateNode.__reactInternalMemoizedMergedChildContext; + } + var parent = node["return"]; + invariant( + parent, + "Found unexpected detached subtree parent. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + node = parent; + } + return node.stateNode.context; } return { - getHostContext: getHostContext, - getRootHostContainer: getRootHostContainer, - popHostContainer: popHostContainer, - popHostContext: popHostContext, - pushHostContainer: pushHostContainer, - pushHostContext: pushHostContext, - resetHostContainer: resetHostContainer + getUnmaskedContext: getUnmaskedContext, + cacheContext: cacheContext, + getMaskedContext: getMaskedContext, + hasContextChanged: hasContextChanged, + isContextConsumer: isContextConsumer, + isContextProvider: isContextProvider, + popContextProvider: popContextProvider, + popTopLevelContextObject: popTopLevelContextObject, + pushTopLevelContextObject: pushTopLevelContextObject, + processChildContext: processChildContext, + pushContextProvider: pushContextProvider, + invalidateContextProvider: invalidateContextProvider, + findCurrentUnmaskedContext: findCurrentUnmaskedContext }; }; -var ReactFiberHydrationContext = function(config) { - var shouldSetTextContent = config.shouldSetTextContent, - hydration = config.hydration; +var ReactFiberNewContext = function(stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop; - // If this doesn't have hydration mode. + var providerCursor = createCursor(null); + var valueCursor = createCursor(null); + var changedBitsCursor = createCursor(0); - if (!hydration) { - return { - enterHydrationState: function() { - return false; - }, - resetHydrationState: function() {}, - tryToClaimNextHydratableInstance: function() {}, - prepareToHydrateHostInstance: function() { - invariant( - false, - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - }, - prepareToHydrateHostTextInstance: function() { - invariant( - false, - "Expected prepareToHydrateHostTextInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - }, - popHydrationState: function(fiber) { - return false; - } - }; + var rendererSigil = void 0; + { + // Use this to detect multiple renderers using the same context + rendererSigil = {}; } - var canHydrateInstance = hydration.canHydrateInstance, - canHydrateTextInstance = hydration.canHydrateTextInstance, - getNextHydratableSibling = hydration.getNextHydratableSibling, - getFirstHydratableChild = hydration.getFirstHydratableChild, - hydrateInstance = hydration.hydrateInstance, - hydrateTextInstance = hydration.hydrateTextInstance, - didNotMatchHydratedContainerTextInstance = - hydration.didNotMatchHydratedContainerTextInstance, - didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance, - didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance, - didNotHydrateInstance = hydration.didNotHydrateInstance, - didNotFindHydratableContainerInstance = - hydration.didNotFindHydratableContainerInstance, - didNotFindHydratableContainerTextInstance = - hydration.didNotFindHydratableContainerTextInstance, - didNotFindHydratableInstance = hydration.didNotFindHydratableInstance, - didNotFindHydratableTextInstance = - hydration.didNotFindHydratableTextInstance; - - // The deepest Fiber on the stack involved in a hydration context. - // This may have been an insertion or a hydration. + function pushProvider(providerFiber) { + var context = providerFiber.type._context; - var hydrationParentFiber = null; - var nextHydratableInstance = null; - var isHydrating = false; + push(changedBitsCursor, context._changedBits, providerFiber); + push(valueCursor, context._currentValue, providerFiber); + push(providerCursor, providerFiber, providerFiber); - function enterHydrationState(fiber) { - var parentInstance = fiber.stateNode.containerInfo; - nextHydratableInstance = getFirstHydratableChild(parentInstance); - hydrationParentFiber = fiber; - isHydrating = true; - return true; - } + context._currentValue = providerFiber.pendingProps.value; + context._changedBits = providerFiber.stateNode; - function deleteHydratableInstance(returnFiber, instance) { { - switch (returnFiber.tag) { - case HostRoot: - didNotHydrateContainerInstance( - returnFiber.stateNode.containerInfo, - instance - ); - break; - case HostComponent: - didNotHydrateInstance( - returnFiber.type, - returnFiber.memoizedProps, - returnFiber.stateNode, - instance - ); - break; - } + !( + context._currentRenderer === null || + context._currentRenderer === rendererSigil + ) + ? warning( + false, + "Detected multiple renderers concurrently rendering the " + + "same context provider. This is currently unsupported." + ) + : void 0; + context._currentRenderer = rendererSigil; } + } - var childToDelete = createFiberFromHostInstanceForDeletion(); - childToDelete.stateNode = instance; - childToDelete["return"] = returnFiber; - childToDelete.effectTag = Deletion; + function popProvider(providerFiber) { + var changedBits = changedBitsCursor.current; + var currentValue = valueCursor.current; - // This might seem like it belongs on progressedFirstDeletion. However, - // these children are not part of the reconciliation list of children. - // Even if we abort and rereconcile the children, that will try to hydrate - // again and the nodes are still in the host tree so these will be - // recreated. - if (returnFiber.lastEffect !== null) { - returnFiber.lastEffect.nextEffect = childToDelete; - returnFiber.lastEffect = childToDelete; - } else { - returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; - } + pop(providerCursor, providerFiber); + pop(valueCursor, providerFiber); + pop(changedBitsCursor, providerFiber); + + var context = providerFiber.type._context; + context._currentValue = currentValue; + context._changedBits = changedBits; } - function insertNonHydratedInstance(returnFiber, fiber) { - fiber.effectTag |= Placement; - { - switch (returnFiber.tag) { - case HostRoot: { - var parentContainer = returnFiber.stateNode.containerInfo; - switch (fiber.tag) { - case HostComponent: - var type = fiber.type; - var props = fiber.pendingProps; - didNotFindHydratableContainerInstance( - parentContainer, - type, - props - ); - break; - case HostText: - var text = fiber.pendingProps; - didNotFindHydratableContainerTextInstance(parentContainer, text); - break; - } - break; - } - case HostComponent: { - var parentType = returnFiber.type; - var parentProps = returnFiber.memoizedProps; - var parentInstance = returnFiber.stateNode; - switch (fiber.tag) { - case HostComponent: - var _type = fiber.type; - var _props = fiber.pendingProps; - didNotFindHydratableInstance( - parentType, - parentProps, - parentInstance, - _type, - _props - ); - break; - case HostText: - var _text = fiber.pendingProps; - didNotFindHydratableTextInstance( - parentType, - parentProps, - parentInstance, - _text - ); - break; - } - break; - } - default: - return; - } - } + return { + pushProvider: pushProvider, + popProvider: popProvider + }; +}; + +var ReactFiberStack = function() { + var valueStack = []; + + var fiberStack = void 0; + + { + fiberStack = []; } - function tryHydrate(fiber, nextInstance) { - switch (fiber.tag) { - case HostComponent: { - var type = fiber.type; - var props = fiber.pendingProps; - var instance = canHydrateInstance(nextInstance, type, props); - if (instance !== null) { - fiber.stateNode = instance; - return true; - } - return false; - } - case HostText: { - var text = fiber.pendingProps; - var textInstance = canHydrateTextInstance(nextInstance, text); - if (textInstance !== null) { - fiber.stateNode = textInstance; - return true; - } - return false; - } - default: - return false; - } + var index = -1; + + function createCursor(defaultValue) { + return { + current: defaultValue + }; } - function tryToClaimNextHydratableInstance(fiber) { - if (!isHydrating) { - return; - } - var nextInstance = nextHydratableInstance; - if (!nextInstance) { - // Nothing to hydrate. Make it an insertion. - insertNonHydratedInstance(hydrationParentFiber, fiber); - isHydrating = false; - hydrationParentFiber = fiber; - return; - } - if (!tryHydrate(fiber, nextInstance)) { - // If we can't hydrate this instance let's try the next one. - // We use this as a heuristic. It's based on intuition and not data so it - // might be flawed or unnecessary. - nextInstance = getNextHydratableSibling(nextInstance); - if (!nextInstance || !tryHydrate(fiber, nextInstance)) { - // Nothing to hydrate. Make it an insertion. - insertNonHydratedInstance(hydrationParentFiber, fiber); - isHydrating = false; - hydrationParentFiber = fiber; - return; - } - // We matched the next one, we'll now assume that the first one was - // superfluous and we'll delete it. Since we can't eagerly delete it - // we'll have to schedule a deletion. To do that, this node needs a dummy - // fiber associated with it. - deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance); - } - hydrationParentFiber = fiber; - nextHydratableInstance = getFirstHydratableChild(nextInstance); + function isEmpty() { + return index === -1; } - function prepareToHydrateHostInstance( - fiber, - rootContainerInstance, - hostContext - ) { - var instance = fiber.stateNode; - var updatePayload = hydrateInstance( - instance, - fiber.type, - fiber.memoizedProps, - rootContainerInstance, - hostContext, - fiber - ); - // TODO: Type this specific to this type of component. - fiber.updateQueue = updatePayload; - // If the update payload indicates that there is a change or if there - // is a new ref we mark this as an update. - if (updatePayload !== null) { - return true; + function pop(cursor, fiber) { + if (index < 0) { + { + warning(false, "Unexpected pop."); + } + return; } - return false; - } - function prepareToHydrateHostTextInstance(fiber) { - var textInstance = fiber.stateNode; - var textContent = fiber.memoizedProps; - var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber); { - if (shouldUpdate) { - // We assume that prepareToHydrateHostTextInstance is called in a context where the - // hydration parent is the parent host component of this host text. - var returnFiber = hydrationParentFiber; - if (returnFiber !== null) { - switch (returnFiber.tag) { - case HostRoot: { - var parentContainer = returnFiber.stateNode.containerInfo; - didNotMatchHydratedContainerTextInstance( - parentContainer, - textInstance, - textContent - ); - break; - } - case HostComponent: { - var parentType = returnFiber.type; - var parentProps = returnFiber.memoizedProps; - var parentInstance = returnFiber.stateNode; - didNotMatchHydratedTextInstance( - parentType, - parentProps, - parentInstance, - textInstance, - textContent - ); - break; - } - } - } + if (fiber !== fiberStack[index]) { + warning(false, "Unexpected Fiber popped."); } } - return shouldUpdate; - } - function popToNextHostParent(fiber) { - var parent = fiber["return"]; - while ( - parent !== null && - parent.tag !== HostComponent && - parent.tag !== HostRoot - ) { - parent = parent["return"]; + cursor.current = valueStack[index]; + + valueStack[index] = null; + + { + fiberStack[index] = null; } - hydrationParentFiber = parent; + + index--; } - function popHydrationState(fiber) { - if (fiber !== hydrationParentFiber) { - // We're deeper than the current hydration context, inside an inserted - // tree. - return false; - } - if (!isHydrating) { - // If we're not currently hydrating but we're in a hydration context, then - // we were an insertion and now need to pop up reenter hydration of our - // siblings. - popToNextHostParent(fiber); - isHydrating = true; - return false; + function push(cursor, value, fiber) { + index++; + + valueStack[index] = cursor.current; + + { + fiberStack[index] = fiber; } - var type = fiber.type; + cursor.current = value; + } - // If we have any remaining hydratable nodes, we need to delete them now. - // We only do this deeper than head and body since they tend to have random - // other nodes in them. We also ignore components with pure text content in - // side of them. - // TODO: Better heuristic. - if ( - fiber.tag !== HostComponent || - (type !== "head" && - type !== "body" && - !shouldSetTextContent(type, fiber.memoizedProps)) - ) { - var nextInstance = nextHydratableInstance; - while (nextInstance) { - deleteHydratableInstance(fiber, nextInstance); - nextInstance = getNextHydratableSibling(nextInstance); + function checkThatStackIsEmpty() { + { + if (index !== -1) { + warning( + false, + "Expected an empty stack. Something was not reset properly." + ); } } - - popToNextHostParent(fiber); - nextHydratableInstance = hydrationParentFiber - ? getNextHydratableSibling(fiber.stateNode) - : null; - return true; } - function resetHydrationState() { - hydrationParentFiber = null; - nextHydratableInstance = null; - isHydrating = false; + function resetStackAfterFatalErrorInDev() { + { + index = -1; + valueStack.length = 0; + fiberStack.length = 0; + } } return { - enterHydrationState: enterHydrationState, - resetHydrationState: resetHydrationState, - tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance, - prepareToHydrateHostInstance: prepareToHydrateHostInstance, - prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance, - popHydrationState: popHydrationState + createCursor: createCursor, + isEmpty: isEmpty, + pop: pop, + push: push, + checkThatStackIsEmpty: checkThatStackIsEmpty, + resetStackAfterFatalErrorInDev: resetStackAfterFatalErrorInDev }; }; -// This lets us hook into Fiber to debug what it's doing. -// See https://github.com/facebook/react/pull/8033. -// This is not part of the public API, not even for React DevTools. -// You may only inject a debugTool if you work on React Fiber itself. -var ReactFiberInstrumentation = { - debugTool: null -}; - -var ReactFiberInstrumentation_1 = ReactFiberInstrumentation; - var invokeGuardedCallback$2 = ReactErrorUtils.invokeGuardedCallback; var hasCaughtError = ReactErrorUtils.hasCaughtError; var clearCaughtError = ReactErrorUtils.clearCaughtError; @@ -11411,17 +11894,19 @@ var warnAboutInvalidUpdates = void 0; var didWarnStateUpdateForUnmountedComponent = {}; warnAboutUpdateOnUnmounted = function(fiber) { + // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. var componentName = getComponentName(fiber) || "ReactClass"; if (didWarnStateUpdateForUnmountedComponent[componentName]) { return; } warning( false, - "Can only update a mounted or mounting " + - "component. This usually means you called setState, replaceState, " + - "or forceUpdate on an unmounted component. This is a no-op.\n\nPlease " + - "check the code for the %s component.", - componentName + "Can't call setState (or forceUpdate) on an unmounted component. This " + + "is a no-op, but it indicates a memory leak in your application. To " + + "fix, cancel all subscriptions and asynchronous tasks in the " + + "componentWillUnmount method.%s", + getStackAddendumByWorkInProgressFiber(fiber) ); didWarnStateUpdateForUnmountedComponent[componentName] = true; }; @@ -11456,16 +11941,23 @@ var warnAboutInvalidUpdates = void 0; } var ReactFiberScheduler = function(config) { - var hostContext = ReactFiberHostContext(config); + var stack = ReactFiberStack(); + var hostContext = ReactFiberHostContext(config, stack); + var legacyContext = ReactFiberLegacyContext(stack); + var newContext = ReactFiberNewContext(stack); var popHostContext = hostContext.popHostContext, popHostContainer = hostContext.popHostContainer; + var popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject, + popLegacyContextProvider = legacyContext.popContextProvider; + var popProvider = newContext.popProvider; var hydrationContext = ReactFiberHydrationContext(config); - var resetHostContainer = hostContext.resetHostContainer; var _ReactFiberBeginWork = ReactFiberBeginWork( config, hostContext, + legacyContext, + newContext, hydrationContext, scheduleWork, computeExpirationForFiber @@ -11475,17 +11967,22 @@ var ReactFiberScheduler = function(config) { var _ReactFiberCompleteWo = ReactFiberCompleteWork( config, hostContext, + legacyContext, + newContext, hydrationContext ), completeWork = _ReactFiberCompleteWo.completeWork; var _ReactFiberUnwindWork = ReactFiberUnwindWork( hostContext, + legacyContext, + newContext, scheduleWork, isAlreadyFailedLegacyErrorBoundary ), throwException = _ReactFiberUnwindWork.throwException, - unwindWork = _ReactFiberUnwindWork.unwindWork; + unwindWork = _ReactFiberUnwindWork.unwindWork, + unwindInterruptedWork = _ReactFiberUnwindWork.unwindInterruptedWork; var _ReactFiberCommitWork = ReactFiberCommitWork( config, @@ -11495,6 +11992,8 @@ var ReactFiberScheduler = function(config) { markLegacyErrorBoundaryAsFailed, recalculateCurrentTime ), + commitBeforeMutationLifeCycles = + _ReactFiberCommitWork.commitBeforeMutationLifeCycles, commitResetTextContent = _ReactFiberCommitWork.commitResetTextContent, commitPlacement = _ReactFiberCommitWork.commitPlacement, commitDeletion = _ReactFiberCommitWork.commitDeletion, @@ -11546,21 +12045,29 @@ var ReactFiberScheduler = function(config) { var stashedWorkInProgressProperties = void 0; var replayUnitOfWork = void 0; + var isReplayingFailedUnitOfWork = void 0; + var originalReplayError = void 0; + var rethrowOriginalError = void 0; if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { stashedWorkInProgressProperties = null; - replayUnitOfWork = function(failedUnitOfWork, isAsync) { - // Retore the original state of the work-in-progress - Object.assign(failedUnitOfWork, stashedWorkInProgressProperties); + isReplayingFailedUnitOfWork = false; + originalReplayError = null; + replayUnitOfWork = function(failedUnitOfWork, error, isAsync) { + // Restore the original state of the work-in-progress + assignFiberPropertiesInDEV( + failedUnitOfWork, + stashedWorkInProgressProperties + ); switch (failedUnitOfWork.tag) { case HostRoot: popHostContainer(failedUnitOfWork); - popTopLevelContextObject(failedUnitOfWork); + popTopLevelLegacyContextObject(failedUnitOfWork); break; case HostComponent: popHostContext(failedUnitOfWork); break; case ClassComponent: - popContextProvider(failedUnitOfWork); + popLegacyContextProvider(failedUnitOfWork); break; case HostPortal: popHostContainer(failedUnitOfWork); @@ -11570,28 +12077,36 @@ var ReactFiberScheduler = function(config) { break; } // Replay the begin phase. + isReplayingFailedUnitOfWork = true; + originalReplayError = error; invokeGuardedCallback$2(null, workLoop, null, isAsync); + isReplayingFailedUnitOfWork = false; + originalReplayError = null; if (hasCaughtError()) { clearCaughtError(); } else { - // This should be unreachable because the render phase is - // idempotent + // If the begin phase did not fail the second time, set this pointer + // back to the original value. + nextUnitOfWork = failedUnitOfWork; } }; + rethrowOriginalError = function() { + throw originalReplayError; + }; } - function resetContextStack() { - // Reset the stack - reset(); - // Reset the cursors - resetContext(); - resetHostContainer(); - - // TODO: Unify new context implementation with other stacks - resetProviderStack(); + function resetStack() { + if (nextUnitOfWork !== null) { + var interruptedWork = nextUnitOfWork["return"]; + while (interruptedWork !== null) { + unwindInterruptedWork(interruptedWork); + interruptedWork = interruptedWork["return"]; + } + } { ReactStrictModeWarnings.discardPendingWarnings(); + stack.checkThatStackIsEmpty(); } nextRoot = null; @@ -11609,6 +12124,7 @@ var ReactFiberScheduler = function(config) { recordEffect(); var effectTag = nextEffect.effectTag; + if (effectTag & ContentReset) { commitResetTextContent(nextEffect); } @@ -11666,6 +12182,22 @@ var ReactFiberScheduler = function(config) { } } + function commitBeforeMutationLifecycles() { + while (nextEffect !== null) { + var effectTag = nextEffect.effectTag; + + if (effectTag & Snapshot) { + recordEffect(); + var current = nextEffect.alternate; + commitBeforeMutationLifeCycles(current, nextEffect); + } + + // Don't cleanup effects yet; + // This will be done by commitAllLifeCycles() + nextEffect = nextEffect.nextEffect; + } + } + function commitAllLifeCycles( finishedRoot, currentTime, @@ -11773,16 +12305,14 @@ var ReactFiberScheduler = function(config) { prepareForCommit(root.containerInfo); - // Commit all the side-effects within a tree. We'll do this in two passes. - // The first pass performs all the host insertions, updates, deletions and - // ref unmounts. + // Invoke instances of getSnapshotBeforeUpdate before mutation. nextEffect = firstEffect; - startCommitHostEffectsTimer(); + startCommitSnapshotEffectsTimer(); while (nextEffect !== null) { var didError = false; var error = void 0; { - invokeGuardedCallback$2(null, commitAllHostEffects, null); + invokeGuardedCallback$2(null, commitBeforeMutationLifecycles, null); if (hasCaughtError()) { didError = true; error = clearCaughtError(); @@ -11801,6 +12331,36 @@ var ReactFiberScheduler = function(config) { } } } + stopCommitSnapshotEffectsTimer(); + + // Commit all the side-effects within a tree. We'll do this in two passes. + // The first pass performs all the host insertions, updates, deletions and + // ref unmounts. + nextEffect = firstEffect; + startCommitHostEffectsTimer(); + while (nextEffect !== null) { + var _didError = false; + var _error = void 0; + { + invokeGuardedCallback$2(null, commitAllHostEffects, null); + if (hasCaughtError()) { + _didError = true; + _error = clearCaughtError(); + } + } + if (_didError) { + invariant( + nextEffect !== null, + "Should have next effect. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + onCommitPhaseError(nextEffect, _error); + // Clean-up + if (nextEffect !== null) { + nextEffect = nextEffect.nextEffect; + } + } + } stopCommitHostEffectsTimer(); resetAfterCommit(root.containerInfo); @@ -11818,8 +12378,8 @@ var ReactFiberScheduler = function(config) { nextEffect = firstEffect; startCommitLifeCyclesTimer(); while (nextEffect !== null) { - var _didError = false; - var _error = void 0; + var _didError2 = false; + var _error2 = void 0; { invokeGuardedCallback$2( null, @@ -11830,17 +12390,17 @@ var ReactFiberScheduler = function(config) { committedExpirationTime ); if (hasCaughtError()) { - _didError = true; - _error = clearCaughtError(); + _didError2 = true; + _error2 = clearCaughtError(); } } - if (_didError) { + if (_didError2) { invariant( nextEffect !== null, "Should have next effect. This error is likely caused by a bug " + "in React. Please file an issue." ); - onCommitPhaseError(nextEffect, _error); + onCommitPhaseError(nextEffect, _error2); if (nextEffect !== null) { nextEffect = nextEffect.nextEffect; } @@ -12064,12 +12624,21 @@ var ReactFiberScheduler = function(config) { } if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { - stashedWorkInProgressProperties = Object.assign({}, workInProgress); + stashedWorkInProgressProperties = assignFiberPropertiesInDEV( + stashedWorkInProgressProperties, + workInProgress + ); } var next = beginWork(current, workInProgress, nextRenderExpirationTime); - { ReactDebugCurrentFiber.resetCurrentFiber(); + if (isReplayingFailedUnitOfWork) { + // Currently replaying a failed unit of work. This should be unreachable, + // because the render phase is meant to be idempotent, and it should + // have thrown again. Since it didn't, rethrow the original error, so + // React's internal stack is not misaligned. + rethrowOriginalError(); + } } if (true && ReactFiberInstrumentation_1.debugTool) { ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress); @@ -12115,7 +12684,7 @@ var ReactFiberScheduler = function(config) { nextUnitOfWork === null ) { // Reset the stack and start working from the root. - resetContextStack(); + resetStack(); nextRoot = root; nextRenderExpirationTime = expirationTime; nextUnitOfWork = createWorkInProgress( @@ -12143,13 +12712,18 @@ var ReactFiberScheduler = function(config) { if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { var failedUnitOfWork = nextUnitOfWork; - replayUnitOfWork(failedUnitOfWork, isAsync); + replayUnitOfWork(failedUnitOfWork, thrownValue, isAsync); } var sourceFiber = nextUnitOfWork; var returnFiber = sourceFiber["return"]; if (returnFiber === null) { - // This is a fatal error. + // This is the root. The root could capture its own errors. However, + // we don't know if it errors before or after we pushed the host + // context. This information is needed to avoid a stack mismatch. + // Because we're not sure, treat this as a fatal error. We could track + // which phase it fails in, but doesn't seem worth it. At least + // for now. didFatal = true; onUncaughtError(thrownValue); break; @@ -12161,23 +12735,32 @@ var ReactFiberScheduler = function(config) { } while (true); // We're done performing work. Time to clean up. - stopWorkLoopTimer(interruptedBy); - interruptedBy = null; + var didCompleteRoot = false; isWorking = false; // Yield back to main thread. if (didFatal) { + stopWorkLoopTimer(interruptedBy, didCompleteRoot); + interruptedBy = null; // There was a fatal error. + { + stack.resetStackAfterFatalErrorInDev(); + } return null; } else if (nextUnitOfWork === null) { // We reached the root. if (isRootReadyForCommit) { + didCompleteRoot = true; + stopWorkLoopTimer(interruptedBy, didCompleteRoot); + interruptedBy = null; // The root successfully completed. It's ready for commit. root.pendingCommitExpirationTime = expirationTime; var finishedWork = root.current.alternate; return finishedWork; } else { // The root did not complete. + stopWorkLoopTimer(interruptedBy, didCompleteRoot); + interruptedBy = null; invariant( false, "Expired work should have completed. This error is likely caused " + @@ -12185,6 +12768,8 @@ var ReactFiberScheduler = function(config) { ); } } else { + stopWorkLoopTimer(interruptedBy, didCompleteRoot); + interruptedBy = null; // There's more work to do, but we ran out of time. Yield back to // the renderer. return null; @@ -12368,9 +12953,17 @@ var ReactFiberScheduler = function(config) { ) { // This is an interruption. (Used for performance tracking.) interruptedBy = fiber; - resetContextStack(); + resetStack(); } - if (nextRoot !== root || !isWorking) { + if ( + // If we're in the render phase, we don't need to schedule this root + // for an update, because we'll do it before we exit... + !isWorking || + isCommitting || + // ...unless this is a different root than the one we're rendering. + nextRoot !== root + ) { + // Add this root to the root schedule. requestWork(root, expirationTime); } if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { @@ -12630,7 +13223,8 @@ var ReactFiberScheduler = function(config) { if (enableUserTimingAPI && deadline !== null) { var didExpire = nextFlushedExpirationTime < recalculateCurrentTime(); - stopRequestCallbackTimer(didExpire); + var timeout = expirationTimeToMs(nextFlushedExpirationTime); + stopRequestCallbackTimer(didExpire, timeout); } if (isAsync) { @@ -12690,7 +13284,11 @@ var ReactFiberScheduler = function(config) { // Perform work on root as if the given expiration time is the current time. // This has the effect of synchronously flushing all work up to and // including the given time. + nextFlushedRoot = root; + nextFlushedExpirationTime = expirationTime; performWorkOnRoot(root, expirationTime, false); + // Flush any sync work that was scheduled by lifecycles + performSyncWork(); finishRendering(); } @@ -12939,7 +13537,8 @@ var ReactFiberScheduler = function(config) { syncUpdates: syncUpdates, interactiveUpdates: interactiveUpdates, flushInteractiveUpdates: flushInteractiveUpdates, - computeUniqueAsyncExpiration: computeUniqueAsyncExpiration + computeUniqueAsyncExpiration: computeUniqueAsyncExpiration, + legacyContext: legacyContext }; }; @@ -12952,18 +13551,6 @@ var didWarnAboutNestedUpdates = void 0; // 0 is PROD, 1 is DEV. // Might add PROFILE later. -function getContextForSubtree(parentComponent) { - if (!parentComponent) { - return emptyObject; - } - - var fiber = get(parentComponent); - var parentContext = findCurrentUnmaskedContext(fiber); - return isContextProvider(fiber) - ? processChildContext(fiber, parentContext) - : parentContext; -} - var ReactFiberReconciler$1 = function(config) { var getPublicInstance = config.getPublicInstance; @@ -12982,7 +13569,24 @@ var ReactFiberReconciler$1 = function(config) { deferredUpdates = _ReactFiberScheduler.deferredUpdates, syncUpdates = _ReactFiberScheduler.syncUpdates, interactiveUpdates = _ReactFiberScheduler.interactiveUpdates, - flushInteractiveUpdates = _ReactFiberScheduler.flushInteractiveUpdates; + flushInteractiveUpdates = _ReactFiberScheduler.flushInteractiveUpdates, + legacyContext = _ReactFiberScheduler.legacyContext; + + var findCurrentUnmaskedContext = legacyContext.findCurrentUnmaskedContext, + isContextProvider = legacyContext.isContextProvider, + processChildContext = legacyContext.processChildContext; + + function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyObject; + } + + var fiber = get(parentComponent); + var parentContext = findCurrentUnmaskedContext(fiber); + return isContextProvider(fiber) + ? processChildContext(fiber, parentContext) + : parentContext; + } function scheduleRootUpdate( current, @@ -13011,12 +13615,14 @@ var ReactFiberReconciler$1 = function(config) { callback = callback === undefined ? null : callback; { - warning( - callback === null || typeof callback === "function", - "render(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callback - ); + !(callback === null || typeof callback === "function") + ? warning( + false, + "render(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callback + ) + : void 0; } var update = { diff --git a/Libraries/Renderer/ReactFabric-prod.js b/Libraries/Renderer/ReactFabric-prod.js index 950e09890f8203..c12ebd601c84d0 100644 --- a/Libraries/Renderer/ReactFabric-prod.js +++ b/Libraries/Renderer/ReactFabric-prod.js @@ -945,6 +945,9 @@ var hasSymbol = "function" === typeof Symbol && Symbol["for"], REACT_PROVIDER_TYPE = hasSymbol ? Symbol["for"]("react.provider") : 60109, REACT_CONTEXT_TYPE = hasSymbol ? Symbol["for"]("react.context") : 60110, REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol["for"]("react.async_mode") : 60111, + REACT_FORWARD_REF_TYPE = hasSymbol + ? Symbol["for"]("react.forward_ref") + : 60112, MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { if (null === maybeIterable || "undefined" === typeof maybeIterable) @@ -1491,7 +1494,8 @@ var ReactNativeComponent = (function(_React$Component) { frameDeadlineObject = { timeRemaining: function() { return frameDeadline - now(); - } + }, + didTimeout: !1 }; function setTimeoutCallback() { frameDeadline = now() + 5; @@ -1630,136 +1634,6 @@ function findCurrentHostFiberWithNoPortals(parent) { } return null; } -var valueStack = [], - index = -1; -function pop(cursor) { - 0 > index || - ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); -} -function push(cursor, value) { - index++; - valueStack[index] = cursor.current; - cursor.current = value; -} -function getStackAddendumByWorkInProgressFiber(workInProgress) { - var info = ""; - do { - a: switch (workInProgress.tag) { - case 0: - case 1: - case 2: - case 5: - var owner = workInProgress._debugOwner, - source = workInProgress._debugSource; - var JSCompiler_inline_result = getComponentName(workInProgress); - var ownerName = null; - owner && (ownerName = getComponentName(owner)); - owner = source; - JSCompiler_inline_result = - "\n in " + - (JSCompiler_inline_result || "Unknown") + - (owner - ? " (at " + - owner.fileName.replace(/^.*[\\\/]/, "") + - ":" + - owner.lineNumber + - ")" - : ownerName ? " (created by " + ownerName + ")" : ""); - break a; - default: - JSCompiler_inline_result = ""; - } - info += JSCompiler_inline_result; - workInProgress = workInProgress["return"]; - } while (workInProgress); - return info; -} -new Set(); -var contextStackCursor = { current: emptyObject }, - didPerformWorkStackCursor = { current: !1 }, - previousContext = emptyObject; -function getUnmaskedContext(workInProgress) { - return isContextProvider(workInProgress) - ? previousContext - : contextStackCursor.current; -} -function getMaskedContext(workInProgress, unmaskedContext) { - var contextTypes = workInProgress.type.contextTypes; - if (!contextTypes) return emptyObject; - var instance = workInProgress.stateNode; - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) - return instance.__reactInternalMemoizedMaskedChildContext; - var context = {}, - key; - for (key in contextTypes) context[key] = unmaskedContext[key]; - instance && - ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); - return context; -} -function isContextProvider(fiber) { - return 2 === fiber.tag && null != fiber.type.childContextTypes; -} -function popContextProvider(fiber) { - isContextProvider(fiber) && - (pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber)); -} -function pushTopLevelContextObject(fiber, context, didChange) { - invariant( - null == contextStackCursor.cursor, - "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." - ); - push(contextStackCursor, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); -} -function processChildContext(fiber, parentContext) { - var instance = fiber.stateNode, - childContextTypes = fiber.type.childContextTypes; - if ("function" !== typeof instance.getChildContext) return parentContext; - instance = instance.getChildContext(); - for (var contextKey in instance) - invariant( - contextKey in childContextTypes, - '%s.getChildContext(): key "%s" is not defined in childContextTypes.', - getComponentName(fiber) || "Unknown", - contextKey - ); - return Object.assign({}, parentContext, instance); -} -function pushContextProvider(workInProgress) { - if (!isContextProvider(workInProgress)) return !1; - var instance = workInProgress.stateNode; - instance = - (instance && instance.__reactInternalMemoizedMergedChildContext) || - emptyObject; - previousContext = contextStackCursor.current; - push(contextStackCursor, instance, workInProgress); - push( - didPerformWorkStackCursor, - didPerformWorkStackCursor.current, - workInProgress - ); - return !0; -} -function invalidateContextProvider(workInProgress, didChange) { - var instance = workInProgress.stateNode; - invariant( - instance, - "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." - ); - if (didChange) { - var mergedContext = processChildContext(workInProgress, previousContext); - instance.__reactInternalMemoizedMergedChildContext = mergedContext; - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor, workInProgress); - push(contextStackCursor, mergedContext, workInProgress); - } else pop(didPerformWorkStackCursor, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); -} function FiberNode(tag, pendingProps, key, mode) { this.tag = tag; this.key = key; @@ -1843,6 +1717,9 @@ function createFiberFromElement(element, mode, expirationTime) { case REACT_CONTEXT_TYPE: fiberTag = 12; break; + case REACT_FORWARD_REF_TYPE: + fiberTag = 14; + break; default: if ("number" === typeof type.tag) return ( @@ -1923,6 +1800,40 @@ function onCommitRoot(root) { function onCommitUnmount(fiber) { "function" === typeof onCommitFiberUnmount && onCommitFiberUnmount(fiber); } +function getStackAddendumByWorkInProgressFiber(workInProgress) { + var info = ""; + do { + a: switch (workInProgress.tag) { + case 0: + case 1: + case 2: + case 5: + var owner = workInProgress._debugOwner, + source = workInProgress._debugSource; + var JSCompiler_inline_result = getComponentName(workInProgress); + var ownerName = null; + owner && (ownerName = getComponentName(owner)); + owner = source; + JSCompiler_inline_result = + "\n in " + + (JSCompiler_inline_result || "Unknown") + + (owner + ? " (at " + + owner.fileName.replace(/^.*[\\\/]/, "") + + ":" + + owner.lineNumber + + ")" + : ownerName ? " (created by " + ownerName + ")" : ""); + break a; + default: + JSCompiler_inline_result = ""; + } + info += JSCompiler_inline_result; + workInProgress = workInProgress["return"]; + } while (workInProgress); + return info; +} +new Set(); function createUpdateQueue(baseState) { return { baseState: baseState, @@ -2078,6 +1989,7 @@ function commitCallbacks(queue, context) { } } function ReactFiberClassComponent( + legacyContext, scheduleWork, computeExpirationForFiber, memoizeProps, @@ -2125,71 +2037,80 @@ function ReactFiberClassComponent( instance.state !== workInProgress && updater.enqueueReplaceState(instance, instance.state, null); } - function callGetDerivedStateFromProps(workInProgress, instance, props) { - instance = workInProgress.type; - if ("function" === typeof instance.getDerivedStateFromProps) - return instance.getDerivedStateFromProps.call( + function callGetDerivedStateFromProps( + workInProgress, + instance, + nextProps, + prevState + ) { + workInProgress = workInProgress.type; + if ("function" === typeof workInProgress.getDerivedStateFromProps) + return workInProgress.getDerivedStateFromProps.call( null, - props, - workInProgress.memoizedState + nextProps, + prevState ); } - var updater = { - isMounted: isMounted, - enqueueSetState: function(instance, partialState, callback) { - instance = instance._reactInternalFiber; - callback = void 0 === callback ? null : callback; - var expirationTime = computeExpirationForFiber(instance); - insertUpdateIntoFiber(instance, { - expirationTime: expirationTime, - partialState: partialState, - callback: callback, - isReplace: !1, - isForced: !1, - capturedValue: null, - next: null - }); - scheduleWork(instance, expirationTime); - }, - enqueueReplaceState: function(instance, state, callback) { - instance = instance._reactInternalFiber; - callback = void 0 === callback ? null : callback; - var expirationTime = computeExpirationForFiber(instance); - insertUpdateIntoFiber(instance, { - expirationTime: expirationTime, - partialState: state, - callback: callback, - isReplace: !0, - isForced: !1, - capturedValue: null, - next: null - }); - scheduleWork(instance, expirationTime); - }, - enqueueForceUpdate: function(instance, callback) { - instance = instance._reactInternalFiber; - callback = void 0 === callback ? null : callback; - var expirationTime = computeExpirationForFiber(instance); - insertUpdateIntoFiber(instance, { - expirationTime: expirationTime, - partialState: null, - callback: callback, - isReplace: !1, - isForced: !0, - capturedValue: null, - next: null - }); - scheduleWork(instance, expirationTime); - } - }; + var cacheContext = legacyContext.cacheContext, + getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + isContextConsumer = legacyContext.isContextConsumer, + hasContextChanged = legacyContext.hasContextChanged, + updater = { + isMounted: isMounted, + enqueueSetState: function(instance, partialState, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: partialState, + callback: callback, + isReplace: !1, + isForced: !1, + capturedValue: null, + next: null + }); + scheduleWork(instance, expirationTime); + }, + enqueueReplaceState: function(instance, state, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: state, + callback: callback, + isReplace: !0, + isForced: !1, + capturedValue: null, + next: null + }); + scheduleWork(instance, expirationTime); + }, + enqueueForceUpdate: function(instance, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: null, + callback: callback, + isReplace: !1, + isForced: !0, + capturedValue: null, + next: null + }); + scheduleWork(instance, expirationTime); + } + }; return { adoptClassInstance: adoptClassInstance, callGetDerivedStateFromProps: callGetDerivedStateFromProps, constructClassInstance: function(workInProgress, props) { var ctor = workInProgress.type, unmaskedContext = getUnmaskedContext(workInProgress), - needsContext = - 2 === workInProgress.tag && null != workInProgress.type.contextTypes, + needsContext = isContextConsumer(workInProgress), context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject; @@ -2198,7 +2119,7 @@ function ReactFiberClassComponent( null !== ctor.state && void 0 !== ctor.state ? ctor.state : null; adoptClassInstance(workInProgress, ctor); workInProgress.memoizedState = state; - props = callGetDerivedStateFromProps(workInProgress, ctor, props); + props = callGetDerivedStateFromProps(workInProgress, ctor, props, state); null !== props && void 0 !== props && (workInProgress.memoizedState = Object.assign( @@ -2206,10 +2127,7 @@ function ReactFiberClassComponent( workInProgress.memoizedState, props )); - needsContext && - ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + needsContext && cacheContext(workInProgress, unmaskedContext, context); return ctor; }, mountClassInstance: function(workInProgress, renderExpirationTime) { @@ -2222,9 +2140,10 @@ function ReactFiberClassComponent( instance.state = workInProgress.memoizedState; instance.refs = emptyObject; instance.context = getMaskedContext(workInProgress, unmaskedContext); - ("function" !== typeof instance.UNSAFE_componentWillMount && - "function" !== typeof instance.componentWillMount) || - "function" === typeof ctor.getDerivedStateFromProps || + "function" === typeof ctor.getDerivedStateFromProps || + "function" === typeof instance.getSnapshotBeforeUpdate || + ("function" !== typeof instance.UNSAFE_componentWillMount && + "function" !== typeof instance.componentWillMount) || ((ctor = instance.state), "function" === typeof instance.componentWillMount && instance.componentWillMount(), @@ -2255,9 +2174,11 @@ function ReactFiberClassComponent( oldContext = instance.context, newUnmaskedContext = getUnmaskedContext(workInProgress); newUnmaskedContext = getMaskedContext(workInProgress, newUnmaskedContext); - ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && - "function" !== typeof instance.componentWillReceiveProps) || + (ctor = "function" === typeof ctor.getDerivedStateFromProps || + "function" === typeof instance.getSnapshotBeforeUpdate) || + ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && + "function" !== typeof instance.componentWillReceiveProps) || ((oldProps !== newProps || oldContext !== newUnmaskedContext) && callComponentWillReceiveProps( workInProgress, @@ -2265,14 +2186,7 @@ function ReactFiberClassComponent( newProps, newUnmaskedContext )); - oldContext = void 0; - oldProps !== newProps && - (oldContext = callGetDerivedStateFromProps( - workInProgress, - instance, - newProps - )); - var oldState = workInProgress.memoizedState; + oldContext = workInProgress.memoizedState; renderExpirationTime = null !== workInProgress.updateQueue ? processUpdateQueue( @@ -2283,18 +2197,33 @@ function ReactFiberClassComponent( newProps, renderExpirationTime ) - : oldState; - null !== oldContext && - void 0 !== oldContext && - (renderExpirationTime = + : oldContext; + var derivedStateFromProps = void 0; + oldProps !== newProps && + (derivedStateFromProps = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + renderExpirationTime + )); + if (null !== derivedStateFromProps && void 0 !== derivedStateFromProps) { + renderExpirationTime = null === renderExpirationTime || void 0 === renderExpirationTime - ? oldContext - : Object.assign({}, renderExpirationTime, oldContext)); + ? derivedStateFromProps + : Object.assign({}, renderExpirationTime, derivedStateFromProps); + var _updateQueue = workInProgress.updateQueue; + null !== _updateQueue && + (_updateQueue.baseState = Object.assign( + {}, + _updateQueue.baseState, + derivedStateFromProps + )); + } if ( !( oldProps !== newProps || - oldState !== renderExpirationTime || - didPerformWorkStackCursor.current || + oldContext !== renderExpirationTime || + hasContextChanged() || (null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate) ) @@ -2308,26 +2237,18 @@ function ReactFiberClassComponent( workInProgress, oldProps, newProps, - oldState, + oldContext, renderExpirationTime, newUnmaskedContext )) - ? (("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - "function" === typeof ctor.getDerivedStateFromProps || - ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate( - newProps, - renderExpirationTime, - newUnmaskedContext - ), - "function" === typeof instance.UNSAFE_componentWillUpdate && - instance.UNSAFE_componentWillUpdate( - newProps, - renderExpirationTime, - newUnmaskedContext - )), - "function" === typeof instance.componentDidUpdate && + ? (ctor || + ("function" !== typeof instance.UNSAFE_componentWillMount && + "function" !== typeof instance.componentWillMount) || + ("function" === typeof instance.componentWillMount && + instance.componentWillMount(), + "function" === typeof instance.UNSAFE_componentWillMount && + instance.UNSAFE_componentWillMount()), + "function" === typeof instance.componentDidMount && (workInProgress.effectTag |= 4)) : ("function" === typeof instance.componentDidMount && (workInProgress.effectTag |= 4), @@ -2352,9 +2273,11 @@ function ReactFiberClassComponent( oldContext = instance.context, newUnmaskedContext = getUnmaskedContext(workInProgress); newUnmaskedContext = getMaskedContext(workInProgress, newUnmaskedContext); - ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && - "function" !== typeof instance.componentWillReceiveProps) || + (ctor = "function" === typeof ctor.getDerivedStateFromProps || + "function" === typeof instance.getSnapshotBeforeUpdate) || + ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && + "function" !== typeof instance.componentWillReceiveProps) || ((oldProps !== newProps || oldContext !== newUnmaskedContext) && callComponentWillReceiveProps( workInProgress, @@ -2362,13 +2285,6 @@ function ReactFiberClassComponent( newProps, newUnmaskedContext )); - var derivedStateFromProps = void 0; - oldProps !== newProps && - (derivedStateFromProps = callGetDerivedStateFromProps( - workInProgress, - instance, - newProps - )); oldContext = workInProgress.memoizedState; renderExpirationTime = null !== workInProgress.updateQueue @@ -2381,17 +2297,32 @@ function ReactFiberClassComponent( renderExpirationTime ) : oldContext; - null !== derivedStateFromProps && - void 0 !== derivedStateFromProps && - (renderExpirationTime = + var derivedStateFromProps = void 0; + oldProps !== newProps && + (derivedStateFromProps = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + renderExpirationTime + )); + if (null !== derivedStateFromProps && void 0 !== derivedStateFromProps) { + renderExpirationTime = null === renderExpirationTime || void 0 === renderExpirationTime ? derivedStateFromProps - : Object.assign({}, renderExpirationTime, derivedStateFromProps)); + : Object.assign({}, renderExpirationTime, derivedStateFromProps); + var _updateQueue3 = workInProgress.updateQueue; + null !== _updateQueue3 && + (_updateQueue3.baseState = Object.assign( + {}, + _updateQueue3.baseState, + derivedStateFromProps + )); + } if ( !( oldProps !== newProps || oldContext !== renderExpirationTime || - didPerformWorkStackCursor.current || + hasContextChanged() || (null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate) ) @@ -2401,6 +2332,10 @@ function ReactFiberClassComponent( (oldProps === current.memoizedProps && oldContext === current.memoizedState) || (workInProgress.effectTag |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldContext === current.memoizedState) || + (workInProgress.effectTag |= 2048), !1 ); (derivedStateFromProps = checkShouldComponentUpdate( @@ -2411,9 +2346,9 @@ function ReactFiberClassComponent( renderExpirationTime, newUnmaskedContext )) - ? (("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - "function" === typeof ctor.getDerivedStateFromProps || + ? (ctor || + ("function" !== typeof instance.UNSAFE_componentWillUpdate && + "function" !== typeof instance.componentWillUpdate) || ("function" === typeof instance.componentWillUpdate && instance.componentWillUpdate( newProps, @@ -2427,11 +2362,17 @@ function ReactFiberClassComponent( newUnmaskedContext )), "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4)) + (workInProgress.effectTag |= 4), + "function" === typeof instance.getSnapshotBeforeUpdate && + (workInProgress.effectTag |= 2048)) : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldContext === current.memoizedState) || (workInProgress.effectTag |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldContext === current.memoizedState) || + (workInProgress.effectTag |= 2048), memoizeProps(workInProgress, newProps), memoizeState(workInProgress, renderExpirationTime)); instance.props = newProps; @@ -3114,34 +3055,12 @@ function ChildReconciler(shouldTrackSideEffects) { }; } var reconcileChildFibers = ChildReconciler(!0), - mountChildFibers = ChildReconciler(!1), - changedBitsStack = [], - currentValueStack = [], - stack = [], - index$1 = -1; -function pushProvider(providerFiber) { - var context = providerFiber.type.context; - index$1 += 1; - changedBitsStack[index$1] = context._changedBits; - currentValueStack[index$1] = context._currentValue; - stack[index$1] = providerFiber; - context._currentValue = providerFiber.pendingProps.value; - context._changedBits = providerFiber.stateNode; -} -function popProvider(providerFiber) { - var changedBits = changedBitsStack[index$1], - currentValue = currentValueStack[index$1]; - changedBitsStack[index$1] = null; - currentValueStack[index$1] = null; - stack[index$1] = null; - --index$1; - providerFiber = providerFiber.type.context; - providerFiber._currentValue = currentValue; - providerFiber._changedBits = changedBits; -} + mountChildFibers = ChildReconciler(!1); function ReactFiberBeginWork( config, hostContext, + legacyContext, + newContext, hydrationContext, scheduleWork, computeExpirationForFiber @@ -3238,7 +3157,12 @@ function ReactFiberBeginWork( changedBits, renderExpirationTime ) { - for (var fiber = workInProgress.child; null !== fiber; ) { + var fiber = workInProgress.child; + for ( + null !== fiber && (fiber["return"] = workInProgress); + null !== fiber; + + ) { switch (fiber.tag) { case 12: var nextFiber = fiber.stateNode | 0; @@ -3294,10 +3218,10 @@ function ReactFiberBeginWork( workInProgress, renderExpirationTime ) { - var context = workInProgress.type.context, + var context = workInProgress.type._context, newProps = workInProgress.pendingProps, oldProps = workInProgress.memoizedProps; - if (!didPerformWorkStackCursor.current && oldProps === newProps) + if (!hasLegacyContextChanged() && oldProps === newProps) return ( (workInProgress.stateNode = 0), pushProvider(workInProgress), @@ -3384,11 +3308,19 @@ function ReactFiberBeginWork( shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree, pushHostContext = hostContext.pushHostContext, pushHostContainer = hostContext.pushHostContainer, + pushProvider = newContext.pushProvider, + getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + hasLegacyContextChanged = legacyContext.hasContextChanged, + pushLegacyContextProvider = legacyContext.pushContextProvider, + pushTopLevelContextObject = legacyContext.pushTopLevelContextObject, + invalidateContextProvider = legacyContext.invalidateContextProvider, enterHydrationState = hydrationContext.enterHydrationState, resetHydrationState = hydrationContext.resetHydrationState, tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance; config = ReactFiberClassComponent( + legacyContext, scheduleWork, computeExpirationForFiber, function(workInProgress, nextProps) { @@ -3415,7 +3347,7 @@ function ReactFiberBeginWork( pushHostRootContext(workInProgress); break; case 2: - pushContextProvider(workInProgress); + pushLegacyContextProvider(workInProgress); break; case 4: pushHostContainer( @@ -3452,7 +3384,8 @@ function ReactFiberBeginWork( ((props = callGetDerivedStateFromProps( workInProgress, fn, - props + props, + workInProgress.memoizedState )), null !== props && void 0 !== props && @@ -3461,7 +3394,7 @@ function ReactFiberBeginWork( workInProgress.memoizedState, props ))), - (props = pushContextProvider(workInProgress)), + (props = pushLegacyContextProvider(workInProgress)), adoptClassInstance(workInProgress, fn), mountClassInstance(workInProgress, renderExpirationTime), (current = finishClassComponent( @@ -3481,7 +3414,7 @@ function ReactFiberBeginWork( return ( (props = workInProgress.type), (renderExpirationTime = workInProgress.pendingProps), - didPerformWorkStackCursor.current || + hasLegacyContextChanged() || workInProgress.memoizedProps !== renderExpirationTime ? ((fn = getUnmaskedContext(workInProgress)), (fn = getMaskedContext(workInProgress, fn)), @@ -3497,7 +3430,7 @@ function ReactFiberBeginWork( current ); case 2: - props = pushContextProvider(workInProgress); + props = pushLegacyContextProvider(workInProgress); null === current ? null === workInProgress.stateNode ? (constructClassInstance( @@ -3579,7 +3512,7 @@ function ReactFiberBeginWork( updateQueue = workInProgress.memoizedProps; fn = workInProgress.pendingProps; unmaskedContext = null !== current ? current.memoizedProps : null; - if (!didPerformWorkStackCursor.current && updateQueue === fn) { + if (!hasLegacyContextChanged() && updateQueue === fn) { if ( (updateQueue = workInProgress.mode & 1 && @@ -3621,7 +3554,7 @@ function ReactFiberBeginWork( case 7: return ( (props = workInProgress.pendingProps), - didPerformWorkStackCursor.current || + hasLegacyContextChanged() || workInProgress.memoizedProps !== props || (props = workInProgress.memoizedProps), (fn = props.children), @@ -3651,8 +3584,7 @@ function ReactFiberBeginWork( workInProgress.stateNode.containerInfo ), (props = workInProgress.pendingProps), - didPerformWorkStackCursor.current || - workInProgress.memoizedProps !== props + hasLegacyContextChanged() || workInProgress.memoizedProps !== props ? (null === current ? (workInProgress.child = reconcileChildFibers( workInProgress, @@ -3669,10 +3601,21 @@ function ReactFiberBeginWork( )), current ); + case 14: + return ( + (renderExpirationTime = workInProgress.type.render), + (renderExpirationTime = renderExpirationTime( + workInProgress.pendingProps, + workInProgress.ref + )), + reconcileChildren(current, workInProgress, renderExpirationTime), + (workInProgress.memoizedProps = renderExpirationTime), + workInProgress.child + ); case 10: return ( (renderExpirationTime = workInProgress.pendingProps), - didPerformWorkStackCursor.current || + hasLegacyContextChanged() || workInProgress.memoizedProps !== renderExpirationTime ? (reconcileChildren( current, @@ -3690,7 +3633,7 @@ function ReactFiberBeginWork( case 11: return ( (renderExpirationTime = workInProgress.pendingProps.children), - didPerformWorkStackCursor.current || + hasLegacyContextChanged() || (null !== renderExpirationTime && workInProgress.memoizedProps !== renderExpirationTime) ? (reconcileChildren( @@ -3713,43 +3656,33 @@ function ReactFiberBeginWork( renderExpirationTime ); case 12: - a: { - fn = workInProgress.type; - unmaskedContext = workInProgress.pendingProps; - updateQueue = workInProgress.memoizedProps; - props = fn._currentValue; - var changedBits = fn._changedBits; - if ( - didPerformWorkStackCursor.current || - 0 !== changedBits || - updateQueue !== unmaskedContext - ) { - workInProgress.memoizedProps = unmaskedContext; - var observedBits = unmaskedContext.unstable_observedBits; - if (void 0 === observedBits || null === observedBits) - observedBits = 1073741823; - workInProgress.stateNode = observedBits; - if (0 !== (changedBits & observedBits)) - propagateContextChange( - workInProgress, - fn, - changedBits, - renderExpirationTime - ); - else if ( - null !== updateQueue && - updateQueue.children === unmaskedContext.children - ) { - current = bailoutOnAlreadyFinishedWork(current, workInProgress); - break a; - } - renderExpirationTime = unmaskedContext.children; - renderExpirationTime = renderExpirationTime(props); - reconcileChildren(current, workInProgress, renderExpirationTime); - current = workInProgress.child; - } else - current = bailoutOnAlreadyFinishedWork(current, workInProgress); - } + fn = workInProgress.type; + unmaskedContext = workInProgress.pendingProps; + var oldProps = workInProgress.memoizedProps; + props = fn._currentValue; + updateQueue = fn._changedBits; + if ( + hasLegacyContextChanged() || + 0 !== updateQueue || + oldProps !== unmaskedContext + ) { + workInProgress.memoizedProps = unmaskedContext; + oldProps = unmaskedContext.unstable_observedBits; + if (void 0 === oldProps || null === oldProps) oldProps = 1073741823; + workInProgress.stateNode = oldProps; + 0 !== (updateQueue & oldProps) && + propagateContextChange( + workInProgress, + fn, + updateQueue, + renderExpirationTime + ); + renderExpirationTime = unmaskedContext.children; + renderExpirationTime = renderExpirationTime(props); + reconcileChildren(current, workInProgress, renderExpirationTime); + current = workInProgress.child; + } else + current = bailoutOnAlreadyFinishedWork(current, workInProgress); return current; default: invariant( @@ -3760,7 +3693,13 @@ function ReactFiberBeginWork( } }; } -function ReactFiberCompleteWork(config, hostContext, hydrationContext) { +function ReactFiberCompleteWork( + config, + hostContext, + legacyContext, + newContext, + hydrationContext +) { function markUpdate(workInProgress) { workInProgress.effectTag |= 4; } @@ -3793,6 +3732,9 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { popHostContext = hostContext.popHostContext, getHostContext = hostContext.getHostContext, popHostContainer = hostContext.popHostContainer, + popLegacyContextProvider = legacyContext.popContextProvider, + popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject, + popProvider = newContext.popProvider, prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance, prepareToHydrateHostTextInstance = @@ -3892,7 +3834,7 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { return null; case 2: return ( - popContextProvider(workInProgress), + popLegacyContextProvider(workInProgress), (current = workInProgress.stateNode), (newProps = workInProgress.updateQueue), null !== newProps && @@ -3905,8 +3847,7 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { ); case 3: popHostContainer(workInProgress); - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor, workInProgress); + popTopLevelLegacyContextObject(workInProgress); newProps = workInProgress.stateNode; newProps.pendingContext && ((newProps.context = newProps.pendingContext), @@ -4058,6 +3999,8 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { return (workInProgress.tag = 7), null; case 9: return null; + case 14: + return null; case 10: return null; case 11: @@ -4088,11 +4031,16 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { } function ReactFiberUnwindWork( hostContext, + legacyContext, + newContext, scheduleWork, isAlreadyFailedLegacyErrorBoundary ) { var popHostContainer = hostContext.popHostContainer, - popHostContext = hostContext.popHostContext; + popHostContext = hostContext.popHostContext, + popLegacyContextProvider = legacyContext.popContextProvider, + popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject, + popProvider = newContext.popProvider; return { throwException: function(returnFiber, sourceFiber, rawValue) { sourceFiber.effectTag |= 512; @@ -4133,7 +4081,7 @@ function ReactFiberUnwindWork( unwindWork: function(workInProgress) { switch (workInProgress.tag) { case 2: - popContextProvider(workInProgress); + popLegacyContextProvider(workInProgress); var effectTag = workInProgress.effectTag; return effectTag & 1024 ? ((workInProgress.effectTag = (effectTag & -1025) | 64), @@ -4142,8 +4090,7 @@ function ReactFiberUnwindWork( case 3: return ( popHostContainer(workInProgress), - pop(didPerformWorkStackCursor, workInProgress), - pop(contextStackCursor, workInProgress), + popTopLevelLegacyContextObject(workInProgress), (effectTag = workInProgress.effectTag), effectTag & 1024 ? ((workInProgress.effectTag = (effectTag & -1025) | 64), @@ -4159,6 +4106,25 @@ function ReactFiberUnwindWork( default: return null; } + }, + unwindInterruptedWork: function(interruptedWork) { + switch (interruptedWork.tag) { + case 2: + popLegacyContextProvider(interruptedWork); + break; + case 3: + popHostContainer(interruptedWork); + popTopLevelLegacyContextObject(interruptedWork); + break; + case 5: + popHostContext(interruptedWork); + break; + case 4: + popHostContainer(interruptedWork); + break; + case 13: + popProvider(interruptedWork); + } } }; } @@ -4167,7 +4133,7 @@ function logError(boundary, errorInfo) { null === errorInfo.stack && getStackAddendumByWorkInProgressFiber(source); null !== source && getComponentName(source); errorInfo = errorInfo.value; - null !== boundary && getComponentName(boundary); + null !== boundary && 2 === boundary.tag && getComponentName(boundary); try { (errorInfo && errorInfo.suppressReactErrorLogging) || console.error(errorInfo); @@ -4191,7 +4157,32 @@ function ReactFiberCommitWork( } catch (refError) { captureError(current, refError); } - else ref.value = null; + else ref.current = null; + } + function commitBeforeMutationLifeCycles(current, finishedWork) { + switch (finishedWork.tag) { + case 2: + if (finishedWork.effectTag & 2048 && null !== current) { + var prevProps = current.memoizedProps, + prevState = current.memoizedState; + current = finishedWork.stateNode; + current.props = finishedWork.memoizedProps; + current.state = finishedWork.memoizedState; + finishedWork = current.getSnapshotBeforeUpdate(prevProps, prevState); + current.__reactInternalSnapshotBeforeUpdate = finishedWork; + } + break; + case 3: + case 5: + case 6: + case 4: + break; + default: + invariant( + !1, + "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." + ); + } } function commitLifeCycles(finishedRoot, current, finishedWork) { switch (finishedWork.tag) { @@ -4207,7 +4198,11 @@ function ReactFiberCommitWork( current = current.memoizedState; finishedRoot.props = finishedWork.memoizedProps; finishedRoot.state = finishedWork.memoizedState; - finishedRoot.componentDidUpdate(prevProps, current); + finishedRoot.componentDidUpdate( + prevProps, + current, + finishedRoot.__reactInternalSnapshotBeforeUpdate + ); } finishedWork = finishedWork.updateQueue; null !== finishedWork && commitCallbacks(finishedWork, finishedRoot); @@ -4267,9 +4262,12 @@ function ReactFiberCommitWork( onUncaughtError.state = finishedWork.memoizedState; for (ctor = 0; ctor < capturedErrors.length; ctor++) { updateQueue = capturedErrors[ctor]; - var _error = updateQueue.value; + var _error = updateQueue.value, + stack = updateQueue.stack; logError(finishedWork, updateQueue); - onUncaughtError.componentDidCatch(_error); + onUncaughtError.componentDidCatch(_error, { + componentStack: null !== stack ? stack : "" + }); } break; case 3: @@ -4295,23 +4293,25 @@ function ReactFiberCommitWork( function commitAttachRef(finishedWork) { var ref = finishedWork.ref; if (null !== ref) { - var _instance5 = finishedWork.stateNode; + var _instance6 = finishedWork.stateNode; switch (finishedWork.tag) { case 5: - finishedWork = getPublicInstance(_instance5); + finishedWork = getPublicInstance(_instance6); break; default: - finishedWork = _instance5; + finishedWork = _instance6; } "function" === typeof ref ? ref(finishedWork) - : (ref.value = finishedWork); + : (ref.current = finishedWork); } } function commitDetachRef(current) { current = current.ref; null !== current && - ("function" === typeof current ? current(null) : (current.value = null)); + ("function" === typeof current + ? current(null) + : (current.current = null)); } function commitNestedUnmounts(root) { for (var node = root; ; ) { @@ -4320,12 +4320,12 @@ function ReactFiberCommitWork( switch (current.tag) { case 2: safelyDetachRef(current); - var _instance6 = current.stateNode; - if ("function" === typeof _instance6.componentWillUnmount) + var _instance7 = current.stateNode; + if ("function" === typeof _instance7.componentWillUnmount) try { - (_instance6.props = current.memoizedProps), - (_instance6.state = current.memoizedState), - _instance6.componentWillUnmount(); + (_instance7.props = current.memoizedProps), + (_instance7.state = current.memoizedState), + _instance7.componentWillUnmount(); } catch (unmountError) { captureError(current, unmountError); } @@ -4403,6 +4403,7 @@ function ReactFiberCommitWork( commitContainer(finishedWork); }, commitLifeCycles: commitLifeCycles, + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, commitErrorLogging: commitErrorLogging, commitAttachRef: commitAttachRef, commitDetachRef: commitDetachRef @@ -4412,7 +4413,7 @@ function ReactFiberCommitWork( invariant(!1, "Mutating reconciler is disabled."); } var NO_CONTEXT = {}; -function ReactFiberHostContext(config) { +function ReactFiberHostContext(config, stack) { function requiredContext(c) { invariant( c !== NO_CONTEXT, @@ -4421,10 +4422,13 @@ function ReactFiberHostContext(config) { return c; } var getChildHostContext = config.getChildHostContext, - getRootHostContext = config.getRootHostContext, - contextStackCursor = { current: NO_CONTEXT }, - contextFiberStackCursor = { current: NO_CONTEXT }, - rootInstanceStackCursor = { current: NO_CONTEXT }; + getRootHostContext = config.getRootHostContext; + config = stack.createCursor; + var push = stack.push, + pop = stack.pop, + contextStackCursor = config(NO_CONTEXT), + contextFiberStackCursor = config(NO_CONTEXT), + rootInstanceStackCursor = config(NO_CONTEXT); return { getHostContext: function() { return requiredContext(contextStackCursor.current); @@ -4443,8 +4447,10 @@ function ReactFiberHostContext(config) { }, pushHostContainer: function(fiber, nextRootInstance) { push(rootInstanceStackCursor, nextRootInstance, fiber); - nextRootInstance = getRootHostContext(nextRootInstance); push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, NO_CONTEXT, fiber); + nextRootInstance = getRootHostContext(nextRootInstance); + pop(contextStackCursor, fiber); push(contextStackCursor, nextRootInstance, fiber); }, pushHostContext: function(fiber) { @@ -4454,10 +4460,6 @@ function ReactFiberHostContext(config) { context !== rootInstance && (push(contextFiberStackCursor, fiber, fiber), push(contextStackCursor, rootInstance, fiber)); - }, - resetHostContainer: function() { - contextStackCursor.current = NO_CONTEXT; - rootInstanceStackCursor.current = NO_CONTEXT; } }; } @@ -4617,22 +4619,198 @@ function ReactFiberHydrationContext(config) { } }; } -function ReactFiberScheduler(config) { - function resetContextStack() { - for (; -1 < index; ) (valueStack[index] = null), index--; +function ReactFiberLegacyContext(stack) { + function cacheContext(workInProgress, unmaskedContext, maskedContext) { + workInProgress = workInProgress.stateNode; + workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + workInProgress.__reactInternalMemoizedMaskedChildContext = maskedContext; + } + function isContextProvider(fiber) { + return 2 === fiber.tag && null != fiber.type.childContextTypes; + } + function processChildContext(fiber, parentContext) { + var instance = fiber.stateNode, + childContextTypes = fiber.type.childContextTypes; + if ("function" !== typeof instance.getChildContext) return parentContext; + instance = instance.getChildContext(); + for (var contextKey in instance) + invariant( + contextKey in childContextTypes, + '%s.getChildContext(): key "%s" is not defined in childContextTypes.', + getComponentName(fiber) || "Unknown", + contextKey + ); + return Object.assign({}, parentContext, instance); + } + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop, + contextStackCursor = createCursor(emptyObject), + didPerformWorkStackCursor = createCursor(!1), previousContext = emptyObject; - contextStackCursor.current = emptyObject; - didPerformWorkStackCursor.current = !1; - resetHostContainer(); - for (var i = index$1; -1 < i; i--) { - var context = stack[i].type.context; - context._currentValue = context._defaultValue; - context._changedBits = 0; - changedBitsStack[i] = null; - currentValueStack[i] = null; - stack[i] = null; + return { + getUnmaskedContext: function(workInProgress) { + return isContextProvider(workInProgress) + ? previousContext + : contextStackCursor.current; + }, + cacheContext: cacheContext, + getMaskedContext: function(workInProgress, unmaskedContext) { + var contextTypes = workInProgress.type.contextTypes; + if (!contextTypes) return emptyObject; + var instance = workInProgress.stateNode; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) + return instance.__reactInternalMemoizedMaskedChildContext; + var context = {}, + key; + for (key in contextTypes) context[key] = unmaskedContext[key]; + instance && cacheContext(workInProgress, unmaskedContext, context); + return context; + }, + hasContextChanged: function() { + return didPerformWorkStackCursor.current; + }, + isContextConsumer: function(fiber) { + return 2 === fiber.tag && null != fiber.type.contextTypes; + }, + isContextProvider: isContextProvider, + popContextProvider: function(fiber) { + isContextProvider(fiber) && + (pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber)); + }, + popTopLevelContextObject: function(fiber) { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + }, + pushTopLevelContextObject: function(fiber, context, didChange) { + invariant( + null == contextStackCursor.cursor, + "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." + ); + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); + }, + processChildContext: processChildContext, + pushContextProvider: function(workInProgress) { + if (!isContextProvider(workInProgress)) return !1; + var instance = workInProgress.stateNode; + instance = + (instance && instance.__reactInternalMemoizedMergedChildContext) || + emptyObject; + previousContext = contextStackCursor.current; + push(contextStackCursor, instance, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); + return !0; + }, + invalidateContextProvider: function(workInProgress, didChange) { + var instance = workInProgress.stateNode; + invariant( + instance, + "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." + ); + if (didChange) { + var mergedContext = processChildContext( + workInProgress, + previousContext + ); + instance.__reactInternalMemoizedMergedChildContext = mergedContext; + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); + push(contextStackCursor, mergedContext, workInProgress); + } else pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + }, + findCurrentUnmaskedContext: function(fiber) { + for ( + invariant( + 2 === isFiberMountedImpl(fiber) && 2 === fiber.tag, + "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." + ); + 3 !== fiber.tag; + + ) { + if (isContextProvider(fiber)) + return fiber.stateNode.__reactInternalMemoizedMergedChildContext; + fiber = fiber["return"]; + invariant( + fiber, + "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." + ); + } + return fiber.stateNode.context; + } + }; +} +function ReactFiberNewContext(stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop, + providerCursor = createCursor(null), + valueCursor = createCursor(null), + changedBitsCursor = createCursor(0); + return { + pushProvider: function(providerFiber) { + var context = providerFiber.type._context; + push(changedBitsCursor, context._changedBits, providerFiber); + push(valueCursor, context._currentValue, providerFiber); + push(providerCursor, providerFiber, providerFiber); + context._currentValue = providerFiber.pendingProps.value; + context._changedBits = providerFiber.stateNode; + }, + popProvider: function(providerFiber) { + var changedBits = changedBitsCursor.current, + currentValue = valueCursor.current; + pop(providerCursor, providerFiber); + pop(valueCursor, providerFiber); + pop(changedBitsCursor, providerFiber); + providerFiber = providerFiber.type._context; + providerFiber._currentValue = currentValue; + providerFiber._changedBits = changedBits; } - index$1 = -1; + }; +} +function ReactFiberStack() { + var valueStack = [], + index = -1; + return { + createCursor: function(defaultValue) { + return { current: defaultValue }; + }, + isEmpty: function() { + return -1 === index; + }, + pop: function(cursor) { + 0 > index || + ((cursor.current = valueStack[index]), + (valueStack[index] = null), + index--); + }, + push: function(cursor, value) { + index++; + valueStack[index] = cursor.current; + cursor.current = value; + }, + checkThatStackIsEmpty: function() {}, + resetStackAfterFatalErrorInDev: function() {} + }; +} +function ReactFiberScheduler(config) { + function resetStack() { + if (null !== nextUnitOfWork) + for ( + var interruptedWork = nextUnitOfWork["return"]; + null !== interruptedWork; + + ) + unwindInterruptedWork(interruptedWork), + (interruptedWork = interruptedWork["return"]); nextRoot = null; nextRenderExpirationTime = 0; nextUnitOfWork = null; @@ -4705,7 +4883,7 @@ function ReactFiberScheduler(config) { workInProgress$jscomp$0 = unwindWork(workInProgress$jscomp$0); if (null !== workInProgress$jscomp$0) return ( - (workInProgress$jscomp$0.effectTag &= 511), workInProgress$jscomp$0 + (workInProgress$jscomp$0.effectTag &= 2559), workInProgress$jscomp$0 ); null !== returnFiber && ((returnFiber.firstEffect = returnFiber.lastEffect = null), @@ -4738,7 +4916,7 @@ function ReactFiberScheduler(config) { root !== nextRoot || null === nextUnitOfWork ) - resetContextStack(), + resetStack(), (nextRoot = root), (nextRenderExpirationTime = expirationTime), (nextUnitOfWork = createWorkInProgress( @@ -4868,8 +5046,8 @@ function ReactFiberScheduler(config) { !isWorking && 0 !== nextRenderExpirationTime && expirationTime < nextRenderExpirationTime && - resetContextStack(); - (nextRoot === root && isWorking) || + resetStack(); + (isWorking && !isCommitting && nextRoot === root) || requestWork(root, expirationTime); nestedUpdateCount > NESTED_UPDATE_LIMIT && invariant( @@ -4933,7 +5111,7 @@ function ReactFiberScheduler(config) { (nextFlushedExpirationTime = 1), performWorkOnRoot(root, 1, !1)) : 1 === expirationTime - ? performWork(1, !1, null) + ? performSyncWork() : scheduleCallbackWithExpiration(expirationTime)); } function findHighestPriorityRoot() { @@ -4993,6 +5171,9 @@ function ReactFiberScheduler(config) { function performAsyncWork(dl) { performWork(0, !0, dl); } + function performSyncWork() { + performWork(1, !1, null); + } function performWork(minExpirationTime, isAsync, dl) { deadline = dl; findHighestPriorityRoot(); @@ -5115,6 +5296,25 @@ function ReactFiberScheduler(config) { for (nextEffect = firstEffect; null !== nextEffect; ) { var didError = !1, error = void 0; + try { + for (; null !== nextEffect; ) + nextEffect.effectTag & 2048 && + commitBeforeMutationLifeCycles(nextEffect.alternate, nextEffect), + (nextEffect = nextEffect.nextEffect); + } catch (e) { + (didError = !0), (error = e); + } + didError && + (invariant( + null !== nextEffect, + "Should have next effect. This error is likely caused by a bug in React. Please file an issue." + ), + onCommitPhaseError(nextEffect, error), + null !== nextEffect && (nextEffect = nextEffect.nextEffect)); + } + for (nextEffect = firstEffect; null !== nextEffect; ) { + didError = !1; + error = void 0; try { for (; null !== nextEffect; ) { var effectTag = nextEffect.effectTag; @@ -5212,25 +5412,37 @@ function ReactFiberScheduler(config) { nextFlushedRoot.remainingExpirationTime = 0; hasUnhandledError || ((hasUnhandledError = !0), (unhandledError = error)); } - var hostContext = ReactFiberHostContext(config), - hydrationContext = ReactFiberHydrationContext(config), - resetHostContainer = hostContext.resetHostContainer, + var stack = ReactFiberStack(), + hostContext = ReactFiberHostContext(config, stack), + legacyContext = ReactFiberLegacyContext(stack); + stack = ReactFiberNewContext(stack); + var hydrationContext = ReactFiberHydrationContext(config), beginWork = ReactFiberBeginWork( config, hostContext, + legacyContext, + stack, hydrationContext, scheduleWork, computeExpirationForFiber ).beginWork, - completeWork = ReactFiberCompleteWork(config, hostContext, hydrationContext) - .completeWork; + completeWork = ReactFiberCompleteWork( + config, + hostContext, + legacyContext, + stack, + hydrationContext + ).completeWork; hostContext = ReactFiberUnwindWork( hostContext, + legacyContext, + stack, scheduleWork, isAlreadyFailedLegacyErrorBoundary ); var throwException = hostContext.throwException, - unwindWork = hostContext.unwindWork; + unwindWork = hostContext.unwindWork, + unwindInterruptedWork = hostContext.unwindInterruptedWork; hostContext = ReactFiberCommitWork( config, onCommitPhaseError, @@ -5243,7 +5455,9 @@ function ReactFiberScheduler(config) { }, recalculateCurrentTime ); - var commitResetTextContent = hostContext.commitResetTextContent, + var commitBeforeMutationLifeCycles = + hostContext.commitBeforeMutationLifeCycles, + commitResetTextContent = hostContext.commitResetTextContent, commitPlacement = hostContext.commitPlacement, commitDeletion = hostContext.commitDeletion, commitWork = hostContext.commitWork, @@ -5298,7 +5512,10 @@ function ReactFiberScheduler(config) { !isRendering, "work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method." ); + nextFlushedRoot = root; + nextFlushedExpirationTime = expirationTime; performWorkOnRoot(root, expirationTime, !1); + performSyncWork(); finishRendering(); }, batchedUpdates: function(fn, a) { @@ -5309,7 +5526,7 @@ function ReactFiberScheduler(config) { } finally { (isBatchingUpdates = previousIsBatchingUpdates) || isRendering || - performWork(1, !1, null); + performSyncWork(); } }, unbatchedUpdates: function(fn, a) { @@ -5333,8 +5550,7 @@ function ReactFiberScheduler(config) { try { return syncUpdates(fn, a); } finally { - (isBatchingUpdates = previousIsBatchingUpdates), - performWork(1, !1, null); + (isBatchingUpdates = previousIsBatchingUpdates), performSyncWork(); } }, flushControlled: function(fn) { @@ -5375,7 +5591,7 @@ function ReactFiberScheduler(config) { (isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates), (isBatchingUpdates = previousIsBatchingUpdates) || isRendering || - performWork(1, !1, null); + performSyncWork(); } }, flushInteractiveUpdates: function() { @@ -5389,7 +5605,8 @@ function ReactFiberScheduler(config) { result <= lastUniqueAsyncExpiration && (result = lastUniqueAsyncExpiration + 1); return (lastUniqueAsyncExpiration = result); - } + }, + legacyContext: legacyContext }; } function ReactFiberReconciler$1(config) { @@ -5404,27 +5621,7 @@ function ReactFiberReconciler$1(config) { currentTime = container.current; if (parentComponent) { parentComponent = parentComponent._reactInternalFiber; - var parentContext; - b: { - invariant( - 2 === isFiberMountedImpl(parentComponent) && - 2 === parentComponent.tag, - "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." - ); - for (parentContext = parentComponent; 3 !== parentContext.tag; ) { - if (isContextProvider(parentContext)) { - parentContext = - parentContext.stateNode.__reactInternalMemoizedMergedChildContext; - break b; - } - parentContext = parentContext["return"]; - invariant( - parentContext, - "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." - ); - } - parentContext = parentContext.stateNode.context; - } + var parentContext = findCurrentUnmaskedContext(parentComponent); parentComponent = isContextProvider(parentComponent) ? processChildContext(parentComponent, parentContext) : parentContext; @@ -5453,7 +5650,11 @@ function ReactFiberReconciler$1(config) { config = ReactFiberScheduler(config); var recalculateCurrentTime = config.recalculateCurrentTime, computeExpirationForFiber = config.computeExpirationForFiber, - scheduleWork = config.scheduleWork; + scheduleWork = config.scheduleWork, + legacyContext = config.legacyContext, + findCurrentUnmaskedContext = legacyContext.findCurrentUnmaskedContext, + isContextProvider = legacyContext.isContextProvider, + processChildContext = legacyContext.processChildContext; return { createContainer: function(containerInfo, isAsync, hydrate) { isAsync = new FiberNode(3, null, null, isAsync ? 3 : 0); @@ -5891,7 +6092,7 @@ ReactFabricRenderer.injectIntoDevTools({ findFiberByHostInstance: getInstanceFromTag, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.3.0-alpha.1", + version: "16.3.1", rendererPackageName: "react-native-renderer" }); var ReactFabric$2 = Object.freeze({ default: ReactFabric }), diff --git a/Libraries/Renderer/ReactNativeRenderer-dev.js b/Libraries/Renderer/ReactNativeRenderer-dev.js index 400472d29a3875..7fd62f11ca6ae4 100644 --- a/Libraries/Renderer/ReactNativeRenderer-dev.js +++ b/Libraries/Renderer/ReactNativeRenderer-dev.js @@ -26,9 +26,9 @@ var deepDiffer = require("deepDiffer"); var flattenStyle = require("flattenStyle"); var React = require("react"); var emptyObject = require("fbjs/lib/emptyObject"); -var checkPropTypes = require("prop-types/checkPropTypes"); var shallowEqual = require("fbjs/lib/shallowEqual"); var ExceptionsManager = require("ExceptionsManager"); +var checkPropTypes = require("prop-types/checkPropTypes"); var deepFreezeAndThrowOnMutationInDev = require("deepFreezeAndThrowOnMutationInDev"); var invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) { @@ -510,11 +510,13 @@ var injection$1 = { getNodeFromInstance = Injected.getNodeFromInstance; { - warning( - getNodeFromInstance && getInstanceFromNode, - "EventPluginUtils.injection.injectComponentTree(...): Injected " + - "module is missing getNodeFromInstance or getInstanceFromNode." - ); + !(getNodeFromInstance && getInstanceFromNode) + ? warning( + false, + "EventPluginUtils.injection.injectComponentTree(...): Injected " + + "module is missing getNodeFromInstance or getInstanceFromNode." + ) + : void 0; } } }; @@ -550,10 +552,9 @@ var validateEventDispatches = void 0; ? dispatchInstances.length : dispatchInstances ? 1 : 0; - warning( - instancesIsArr === listenersIsArr && instancesLen === listenersLen, - "EventPluginUtils: Invalid `event`." - ); + !(instancesIsArr === listenersIsArr && instancesLen === listenersLen) + ? warning(false, "EventPluginUtils: Invalid `event`.") + : void 0; }; } @@ -965,6 +966,7 @@ var Fragment = 10; var Mode = 11; var ContextConsumer = 12; var ContextProvider = 13; +var ForwardRef = 14; function getParent(inst) { do { @@ -1093,7 +1095,7 @@ function listenerAtPhase(inst, event, propagationPhase) { */ function accumulateDirectionalDispatches(inst, phase, event) { { - warning(inst, "Dispatching inst must not be null"); + !inst ? warning(false, "Dispatching inst must not be null") : void 0; } var listener = listenerAtPhase(inst, event, phase); if (listener) { @@ -1412,13 +1414,15 @@ SyntheticEvent.extend = function(Interface) { !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1 ) { - warning( - didWarnForAddedNewProperty || target.isPersistent(), - "This synthetic event is reused for performance reasons. If you're " + - "seeing this, you're adding a new property in the synthetic event object. " + - "The property is never released. See " + - "https://fb.me/react-event-pooling for more information." - ); + !(didWarnForAddedNewProperty || target.isPersistent()) + ? warning( + false, + "This synthetic event is reused for performance reasons. If you're " + + "seeing this, you're adding a new property in the synthetic event object. " + + "The property is never released. See " + + "https://fb.me/react-event-pooling for more information." + ) + : void 0; didWarnForAddedNewProperty = true; } target[prop] = value; @@ -1465,16 +1469,18 @@ function getPooledWarningPropertyDefinition(propName, getVal) { function warn(action, result) { var warningCondition = false; - warning( - warningCondition, - "This synthetic event is reused for performance reasons. If you're seeing this, " + - "you're %s `%s` on a released/nullified synthetic event. %s. " + - "If you must keep the original synthetic event around, use event.persist(). " + - "See https://fb.me/react-event-pooling for more information.", - action, - propName, - result - ); + !warningCondition + ? warning( + false, + "This synthetic event is reused for performance reasons. If you're seeing this, " + + "you're %s `%s` on a released/nullified synthetic event. %s. " + + "If you must keep the original synthetic event around, use event.persist(). " + + "See https://fb.me/react-event-pooling for more information.", + action, + propName, + result + ) + : void 0; } } @@ -1592,13 +1598,15 @@ function getTouchIdentifier(_ref) { invariant(identifier != null, "Touch object is missing identifier."); { - warning( - identifier <= MAX_TOUCH_BANK, - "Touch identifier %s is greater than maximum supported %s which causes " + - "performance issues backfilling array locations for all of the indices.", - identifier, - MAX_TOUCH_BANK - ); + !(identifier <= MAX_TOUCH_BANK) + ? warning( + false, + "Touch identifier %s is greater than maximum supported %s which causes " + + "performance issues backfilling array locations for all of the indices.", + identifier, + MAX_TOUCH_BANK + ) + : void 0; } return identifier; } @@ -1697,10 +1705,9 @@ var ResponderTouchHistoryStore = { } { var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch]; - warning( - activeRecord != null && activeRecord.touchActive, - "Cannot find single active touch." - ); + !(activeRecord != null && activeRecord.touchActive) + ? warning(false, "Cannot find single active touch.") + : void 0; } } } @@ -2802,6 +2809,9 @@ var REACT_CONTEXT_TYPE = hasSymbol ? Symbol["for"]("react.context") : 0xeace; var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol["for"]("react.async_mode") : 0xeacf; +var REACT_FORWARD_REF_TYPE = hasSymbol + ? Symbol["for"]("react.forward_ref") + : 0xead0; var MAYBE_ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = "@@iterator"; @@ -2983,7 +2993,7 @@ var TouchHistoryMath = { // TODO: this is special because it gets imported during build. -var ReactVersion = "16.3.0-alpha.1"; +var ReactVersion = "16.3.1"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -3653,15 +3663,17 @@ function findNodeHandle(componentOrHandle) { { var owner = ReactCurrentOwner.current; if (owner !== null && owner.stateNode !== null) { - warning( - owner.stateNode._warnedAboutRefsInRender, - "%s is accessing findNodeHandle inside its render(). " + - "render() should be a pure function of props and state. It should " + - "never access something that requires stale data from the previous " + - "render, such as refs. Move this logic to componentDidMount and " + - "componentDidUpdate instead.", - getComponentName(owner) || "A component" - ); + !owner.stateNode._warnedAboutRefsInRender + ? warning( + false, + "%s is accessing findNodeHandle inside its render(). " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentName(owner) || "A component" + ) + : void 0; owner.stateNode._warnedAboutRefsInRender = true; } @@ -4116,9 +4128,10 @@ var Callback = /* */ 32; var DidCapture = /* */ 64; var Ref = /* */ 128; var ErrLog = /* */ 256; +var Snapshot = /* */ 2048; // Union of all host effects -var HostEffectMask = /* */ 511; +var HostEffectMask = /* */ 2559; var Incomplete = /* */ 512; var ShouldCapture = /* */ 1024; @@ -4166,15 +4179,17 @@ function isMounted(component) { if (owner !== null && owner.tag === ClassComponent) { var ownerFiber = owner; var instance = ownerFiber.stateNode; - warning( - instance._warnedAboutRefsInRender, - "%s is accessing isMounted inside its render() function. " + - "render() should be a pure function of props and state. It should " + - "never access something that requires stale data from the previous " + - "render, such as refs. Move this logic to componentDidMount and " + - "componentDidUpdate instead.", - getComponentName(ownerFiber) || "A component" - ); + !instance._warnedAboutRefsInRender + ? warning( + false, + "%s is accessing isMounted inside its render() function. " + + "render() should be a pure function of props and state. It should " + + "never access something that requires stale data from the previous " + + "render, such as refs. Move this logic to componentDidMount and " + + "componentDidUpdate instead.", + getComponentName(ownerFiber) || "A component" + ) + : void 0; instance._warnedAboutRefsInRender = true; } } @@ -4385,1721 +4400,1469 @@ function findCurrentHostFiberWithNoPortals(parent) { return null; } -var valueStack = []; +// Max 31 bit integer. The max integer size in V8 for 32-bit systems. +// Math.pow(2, 30) - 1 +// 0b111111111111111111111111111111 +var MAX_SIGNED_31_BIT_INT = 1073741823; -var fiberStack = void 0; +// TODO: Use an opaque type once ESLint et al support the syntax -{ - fiberStack = []; -} +var NoWork = 0; +var Sync = 1; +var Never = MAX_SIGNED_31_BIT_INT; -var index = -1; +var UNIT_SIZE = 10; +var MAGIC_NUMBER_OFFSET = 2; -function createCursor(defaultValue) { - return { - current: defaultValue - }; +// 1 unit of expiration time represents 10ms. +function msToExpirationTime(ms) { + // Always add an offset so that we don't clash with the magic number for NoWork. + return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET; } -function pop(cursor, fiber) { - if (index < 0) { - { - warning(false, "Unexpected pop."); - } - return; - } +function expirationTimeToMs(expirationTime) { + return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE; +} - { - if (fiber !== fiberStack[index]) { - warning(false, "Unexpected Fiber popped."); - } - } +function ceiling(num, precision) { + return (((num / precision) | 0) + 1) * precision; +} - cursor.current = valueStack[index]; +function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { + return ceiling( + currentTime + expirationInMs / UNIT_SIZE, + bucketSizeMs / UNIT_SIZE + ); +} + +var NoContext = 0; +var AsyncMode = 1; +var StrictMode = 2; - valueStack[index] = null; +var hasBadMapPolyfill = void 0; - { - fiberStack[index] = null; +{ + hasBadMapPolyfill = false; + try { + var nonExtensibleObject = Object.preventExtensions({}); + var testMap = new Map([[nonExtensibleObject, null]]); + var testSet = new Set([nonExtensibleObject]); + // This is necessary for Rollup to not consider these unused. + // https://github.com/rollup/rollup/issues/1771 + // TODO: we can remove these if Rollup fixes the bug. + testMap.set(0, 0); + testSet.add(0); + } catch (e) { + // TODO: Consider warning about bad polyfills + hasBadMapPolyfill = true; } +} + +// A Fiber is work on a Component that needs to be done or was done. There can +// be more than one per component. + +var debugCounter = void 0; - index--; +{ + debugCounter = 1; } -function push(cursor, value, fiber) { - index++; +function FiberNode(tag, pendingProps, key, mode) { + // Instance + this.tag = tag; + this.key = key; + this.type = null; + this.stateNode = null; + + // Fiber + this["return"] = null; + this.child = null; + this.sibling = null; + this.index = 0; + + this.ref = null; + + this.pendingProps = pendingProps; + this.memoizedProps = null; + this.updateQueue = null; + this.memoizedState = null; + + this.mode = mode; + + // Effects + this.effectTag = NoEffect; + this.nextEffect = null; + + this.firstEffect = null; + this.lastEffect = null; + + this.expirationTime = NoWork; - valueStack[index] = cursor.current; + this.alternate = null; { - fiberStack[index] = fiber; + this._debugID = debugCounter++; + this._debugSource = null; + this._debugOwner = null; + this._debugIsCurrentlyTiming = false; + if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") { + Object.preventExtensions(this); + } } +} + +// This is a constructor function, rather than a POJO constructor, still +// please ensure we do the following: +// 1) Nobody should add any instance methods on this. Instance methods can be +// more difficult to predict when they get optimized and they are almost +// never inlined properly in static compilers. +// 2) Nobody should rely on `instanceof Fiber` for type testing. We should +// always know when it is a fiber. +// 3) We might want to experiment with using numeric keys since they are easier +// to optimize in a non-JIT environment. +// 4) We can easily go from a constructor to a createFiber object literal if that +// is faster. +// 5) It should be easy to port this to a C struct and keep a C implementation +// compatible. +var createFiber = function(tag, pendingProps, key, mode) { + // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, pendingProps, key, mode); +}; - cursor.current = value; +function shouldConstruct(Component) { + return !!(Component.prototype && Component.prototype.isReactComponent); } -function reset() { - while (index > -1) { - valueStack[index] = null; +// This is used to create an alternate fiber to do work on. +function createWorkInProgress(current, pendingProps, expirationTime) { + var workInProgress = current.alternate; + if (workInProgress === null) { + // We use a double buffering pooling technique because we know that we'll + // only ever need at most two versions of a tree. We pool the "other" unused + // node that we're free to reuse. This is lazily created to avoid allocating + // extra objects for things that are never updated. It also allow us to + // reclaim the extra memory if needed. + workInProgress = createFiber( + current.tag, + pendingProps, + current.key, + current.mode + ); + workInProgress.type = current.type; + workInProgress.stateNode = current.stateNode; { - fiberStack[index] = null; + // DEV-only fields + workInProgress._debugID = current._debugID; + workInProgress._debugSource = current._debugSource; + workInProgress._debugOwner = current._debugOwner; } - index--; - } -} + workInProgress.alternate = current; + current.alternate = workInProgress; + } else { + workInProgress.pendingProps = pendingProps; -var describeComponentFrame = function(name, source, ownerName) { - return ( - "\n in " + - (name || "Unknown") + - (source - ? " (at " + - source.fileName.replace(/^.*[\\\/]/, "") + - ":" + - source.lineNumber + - ")" - : ownerName ? " (created by " + ownerName + ")" : "") - ); -}; + // We already have an alternate. + // Reset the effect tag. + workInProgress.effectTag = NoEffect; -function describeFiber(fiber) { - switch (fiber.tag) { - case IndeterminateComponent: - case FunctionalComponent: - case ClassComponent: - case HostComponent: - var owner = fiber._debugOwner; - var source = fiber._debugSource; - var name = getComponentName(fiber); - var ownerName = null; - if (owner) { - ownerName = getComponentName(owner); - } - return describeComponentFrame(name, source, ownerName); - default: - return ""; + // The effect list is no longer valid. + workInProgress.nextEffect = null; + workInProgress.firstEffect = null; + workInProgress.lastEffect = null; } + + workInProgress.expirationTime = expirationTime; + + workInProgress.child = current.child; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; + + // These will be overridden during the parent's reconciliation + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + + return workInProgress; } -// This function can only be called with a work-in-progress fiber and -// only during begin or complete phase. Do not call it under any other -// circumstances. -function getStackAddendumByWorkInProgressFiber(workInProgress) { - var info = ""; - var node = workInProgress; - do { - info += describeFiber(node); - // Otherwise this return pointer might point to the wrong tree: - node = node["return"]; - } while (node); - return info; +function createHostRootFiber(isAsync) { + var mode = isAsync ? AsyncMode | StrictMode : NoContext; + return createFiber(HostRoot, null, null, mode); } -function getCurrentFiberOwnerName() { +function createFiberFromElement(element, mode, expirationTime) { + var owner = null; { - var fiber = ReactDebugCurrentFiber.current; - if (fiber === null) { - return null; - } - var owner = fiber._debugOwner; - if (owner !== null && typeof owner !== "undefined") { - return getComponentName(owner); - } + owner = element._owner; } - return null; + + var fiber = void 0; + var type = element.type; + var key = element.key; + var pendingProps = element.props; + + var fiberTag = void 0; + if (typeof type === "function") { + fiberTag = shouldConstruct(type) ? ClassComponent : IndeterminateComponent; + } else if (typeof type === "string") { + fiberTag = HostComponent; + } else { + switch (type) { + case REACT_FRAGMENT_TYPE: + return createFiberFromFragment( + pendingProps.children, + mode, + expirationTime, + key + ); + case REACT_ASYNC_MODE_TYPE: + fiberTag = Mode; + mode |= AsyncMode | StrictMode; + break; + case REACT_STRICT_MODE_TYPE: + fiberTag = Mode; + mode |= StrictMode; + break; + case REACT_CALL_TYPE: + fiberTag = CallComponent; + break; + case REACT_RETURN_TYPE: + fiberTag = ReturnComponent; + break; + default: { + if (typeof type === "object" && type !== null) { + switch (type.$$typeof) { + case REACT_PROVIDER_TYPE: + fiberTag = ContextProvider; + break; + case REACT_CONTEXT_TYPE: + // This is a consumer + fiberTag = ContextConsumer; + break; + case REACT_FORWARD_REF_TYPE: + fiberTag = ForwardRef; + break; + default: + if (typeof type.tag === "number") { + // Currently assumed to be a continuation and therefore is a + // fiber already. + // TODO: The yield system is currently broken for updates in + // some cases. The reified yield stores a fiber, but we don't + // know which fiber that is; the current or a workInProgress? + // When the continuation gets rendered here we don't know if we + // can reuse that fiber or if we need to clone it. There is + // probably a clever way to restructure this. + fiber = type; + fiber.pendingProps = pendingProps; + fiber.expirationTime = expirationTime; + return fiber; + } else { + throwOnInvalidElementType(type, owner); + } + break; + } + } else { + throwOnInvalidElementType(type, owner); + } + } + } + } + + fiber = createFiber(fiberTag, pendingProps, key, mode); + fiber.type = type; + fiber.expirationTime = expirationTime; + + { + fiber._debugSource = element._source; + fiber._debugOwner = element._owner; + } + + return fiber; } -function getCurrentFiberStackAddendum() { +function throwOnInvalidElementType(type, owner) { + var info = ""; { - var fiber = ReactDebugCurrentFiber.current; - if (fiber === null) { - return null; + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + info += + " You likely forgot to export your component from the file " + + "it's defined in, or you might have mixed up default and " + + "named imports."; + } + var ownerName = owner ? getComponentName(owner) : null; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; } - // Safe because if current fiber exists, we are reconciling, - // and it is guaranteed to be the work-in-progress version. - return getStackAddendumByWorkInProgressFiber(fiber); } - return null; + invariant( + false, + "Element type is invalid: expected a string (for built-in " + + "components) or a class/function (for composite components) " + + "but got: %s.%s", + type == null ? type : typeof type, + info + ); } -function resetCurrentFiber() { - ReactDebugCurrentFrame.getCurrentStack = null; - ReactDebugCurrentFiber.current = null; - ReactDebugCurrentFiber.phase = null; +function createFiberFromFragment(elements, mode, expirationTime, key) { + var fiber = createFiber(Fragment, elements, key, mode); + fiber.expirationTime = expirationTime; + return fiber; } -function setCurrentFiber(fiber) { - ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; - ReactDebugCurrentFiber.current = fiber; - ReactDebugCurrentFiber.phase = null; +function createFiberFromText(content, mode, expirationTime) { + var fiber = createFiber(HostText, content, null, mode); + fiber.expirationTime = expirationTime; + return fiber; } -function setCurrentPhase(phase) { - ReactDebugCurrentFiber.phase = phase; +function createFiberFromHostInstanceForDeletion() { + var fiber = createFiber(HostComponent, null, null, NoContext); + fiber.type = "DELETED"; + return fiber; } -var ReactDebugCurrentFiber = { - current: null, - phase: null, - resetCurrentFiber: resetCurrentFiber, - setCurrentFiber: setCurrentFiber, - setCurrentPhase: setCurrentPhase, - getCurrentFiberOwnerName: getCurrentFiberOwnerName, - getCurrentFiberStackAddendum: getCurrentFiberStackAddendum -}; - -// Re-export dynamic flags from the fbsource version. -var _require = require("ReactFeatureFlags"); - -var enableGetDerivedStateFromCatch = _require.enableGetDerivedStateFromCatch; -var debugRenderPhaseSideEffects = _require.debugRenderPhaseSideEffects; -var debugRenderPhaseSideEffectsForStrictMode = - _require.debugRenderPhaseSideEffectsForStrictMode; -var warnAboutDeprecatedLifecycles = _require.warnAboutDeprecatedLifecycles; -var replayFailedUnitOfWorkWithInvokeGuardedCallback = - _require.replayFailedUnitOfWorkWithInvokeGuardedCallback; - -var enableUserTimingAPI = true; -var enableMutatingReconciler = true; -var enableNoopReconciler = false; -var enablePersistentReconciler = false; - -// Only used in www builds. +function createFiberFromPortal(portal, mode, expirationTime) { + var pendingProps = portal.children !== null ? portal.children : []; + var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); + fiber.expirationTime = expirationTime; + fiber.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, // Used by persistent updates + implementation: portal.implementation + }; + return fiber; +} -// Prefix measurements so that it's possible to filter them. -// Longer prefixes are hard to read in DevTools. -var reactEmoji = "\u269B"; -var warningEmoji = "\u26D4"; -var supportsUserTiming = - typeof performance !== "undefined" && - typeof performance.mark === "function" && - typeof performance.clearMarks === "function" && - typeof performance.measure === "function" && - typeof performance.clearMeasures === "function"; +// Used for stashing WIP properties to replay failed work in DEV. +function assignFiberPropertiesInDEV(target, source) { + if (target === null) { + // This Fiber's initial properties will always be overwritten. + // We only use a Fiber to ensure the same hidden class so DEV isn't slow. + target = createFiber(IndeterminateComponent, null, null, NoContext); + } + + // This is intentionally written as a list of all properties. + // We tried to use Object.assign() instead but this is called in + // the hottest path, and Object.assign() was too slow: + // https://github.com/facebook/react/issues/12502 + // This code is DEV-only so size is not a concern. + + target.tag = source.tag; + target.key = source.key; + 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.mode = source.mode; + target.effectTag = source.effectTag; + target.nextEffect = source.nextEffect; + target.firstEffect = source.firstEffect; + target.lastEffect = source.lastEffect; + target.expirationTime = source.expirationTime; + target.alternate = source.alternate; + target._debugID = source._debugID; + target._debugSource = source._debugSource; + target._debugOwner = source._debugOwner; + target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming; + return target; +} -// Keep track of current fiber so that we know the path to unwind on pause. -// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? -var currentFiber = null; -// If we're in the middle of user code, which fiber and method is it? -// Reusing `currentFiber` would be confusing for this because user code fiber -// can change during commit phase too, but we don't need to unwind it (since -// lifecycles in the commit phase don't resemble a tree). -var currentPhase = null; -var currentPhaseFiber = null; -// Did lifecycle hook schedule an update? This is often a performance problem, -// so we will keep track of it, and include it in the report. -// Track commits caused by cascading updates. -var isCommitting = false; -var hasScheduledUpdateInCurrentCommit = false; -var hasScheduledUpdateInCurrentPhase = false; -var commitCountInCurrentWorkLoop = 0; -var effectCountInCurrentCommit = 0; -var isWaitingForCallback = false; -// During commits, we only show a measurement once per method name -// to avoid stretch the commit phase with measurement overhead. -var labelsInCurrentCommit = new Set(); +// TODO: This should be lifted into the renderer. -var formatMarkName = function(markName) { - return reactEmoji + " " + markName; -}; +function createFiberRoot(containerInfo, isAsync, hydrate) { + // Cyclic construction. This cheats the type system right now because + // stateNode is any. + var uninitializedFiber = createHostRootFiber(isAsync); + var root = { + current: uninitializedFiber, + containerInfo: containerInfo, + pendingChildren: null, + pendingCommitExpirationTime: NoWork, + finishedWork: null, + context: null, + pendingContext: null, + hydrate: hydrate, + remainingExpirationTime: NoWork, + firstBatch: null, + nextScheduledRoot: null + }; + uninitializedFiber.stateNode = root; + return root; +} -var formatLabel = function(label, warning$$1) { - var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; - var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; - return "" + prefix + label + suffix; -}; +var onCommitFiberRoot = null; +var onCommitFiberUnmount = null; +var hasLoggedError = false; -var beginMark = function(markName) { - performance.mark(formatMarkName(markName)); -}; +function catchErrors(fn) { + return function(arg) { + try { + return fn(arg); + } catch (err) { + if (true && !hasLoggedError) { + hasLoggedError = true; + warning(false, "React DevTools encountered an error: %s", err); + } + } + }; +} -var clearMark = function(markName) { - performance.clearMarks(formatMarkName(markName)); -}; - -var endMark = function(label, markName, warning$$1) { - var formattedMarkName = formatMarkName(markName); - var formattedLabel = formatLabel(label, warning$$1); - try { - performance.measure(formattedLabel, formattedMarkName); - } catch (err) {} - // If previous mark was missing for some reason, this will throw. - // This could only happen if React crashed in an unexpected place earlier. - // Don't pile on with more errors. - - // Clear marks immediately to avoid growing buffer. - performance.clearMarks(formattedMarkName); - performance.clearMeasures(formattedLabel); -}; - -var getFiberMarkName = function(label, debugID) { - return label + " (#" + debugID + ")"; -}; - -var getFiberLabel = function(componentName, isMounted, phase) { - if (phase === null) { - // These are composite component total time measurements. - return componentName + " [" + (isMounted ? "update" : "mount") + "]"; - } else { - // Composite component methods. - return componentName + "." + phase; - } -}; - -var beginFiberMark = function(fiber, phase) { - var componentName = getComponentName(fiber) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - - if (isCommitting && labelsInCurrentCommit.has(label)) { - // During the commit phase, we don't show duplicate labels because - // there is a fixed overhead for every measurement, and we don't - // want to stretch the commit phase beyond necessary. +function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { + // No DevTools return false; } - labelsInCurrentCommit.add(label); - - var markName = getFiberMarkName(label, debugID); - beginMark(markName); - return true; -}; - -var clearFiberMark = function(fiber, phase) { - var componentName = getComponentName(fiber) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - clearMark(markName); -}; - -var endFiberMark = function(fiber, phase, warning$$1) { - var componentName = getComponentName(fiber) || "Unknown"; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - endMark(label, markName, warning$$1); -}; - -var shouldIgnoreFiber = function(fiber) { - // Host components should be skipped in the timeline. - // We could check typeof fiber.type, but does this work with RN? - switch (fiber.tag) { - case HostRoot: - case HostComponent: - case HostText: - case HostPortal: - case CallComponent: - case ReturnComponent: - case Fragment: - case ContextProvider: - case ContextConsumer: - return true; - default: - return false; - } -}; - -var clearPendingPhaseMeasurement = function() { - if (currentPhase !== null && currentPhaseFiber !== null) { - clearFiberMark(currentPhaseFiber, currentPhase); + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (hook.isDisabled) { + // This isn't a real property on the hook, but it can be set to opt out + // of DevTools integration and associated warnings and logs. + // https://github.com/facebook/react/issues/3877 + return true; } - currentPhaseFiber = null; - currentPhase = null; - hasScheduledUpdateInCurrentPhase = false; -}; - -var pauseTimers = function() { - // Stops all currently active measurements so that they can be resumed - // if we continue in a later deferred loop from the same unit of work. - var fiber = currentFiber; - while (fiber) { - if (fiber._debugIsCurrentlyTiming) { - endFiberMark(fiber, null, null); + if (!hook.supportsFiber) { + { + warning( + false, + "The installed version of React DevTools is too old and will not work " + + "with the current version of React. Please update React DevTools. " + + "https://fb.me/react-devtools" + ); } - fiber = fiber["return"]; - } -}; - -var resumeTimersRecursively = function(fiber) { - if (fiber["return"] !== null) { - resumeTimersRecursively(fiber["return"]); - } - if (fiber._debugIsCurrentlyTiming) { - beginFiberMark(fiber, null); - } -}; - -var resumeTimers = function() { - // Resumes all measurements that were active during the last deferred loop. - if (currentFiber !== null) { - resumeTimersRecursively(currentFiber); - } -}; - -function recordEffect() { - if (enableUserTimingAPI) { - effectCountInCurrentCommit++; + // DevTools exists, even though it doesn't support Fiber. + return true; } -} - -function recordScheduleUpdate() { - if (enableUserTimingAPI) { - if (isCommitting) { - hasScheduledUpdateInCurrentCommit = true; - } - if ( - currentPhase !== null && - currentPhase !== "componentWillMount" && - currentPhase !== "componentWillReceiveProps" - ) { - hasScheduledUpdateInCurrentPhase = true; + try { + var rendererID = hook.inject(internals); + // We have successfully injected, so now it is safe to set up hooks. + onCommitFiberRoot = catchErrors(function(root) { + return hook.onCommitFiberRoot(rendererID, root); + }); + onCommitFiberUnmount = catchErrors(function(fiber) { + return hook.onCommitFiberUnmount(rendererID, fiber); + }); + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + warning(false, "React DevTools encountered an error: %s.", err); } } + // DevTools exists + return true; } -function startRequestCallbackTimer() { - if (enableUserTimingAPI) { - if (supportsUserTiming && !isWaitingForCallback) { - isWaitingForCallback = true; - beginMark("(Waiting for async callback...)"); - } +function onCommitRoot(root) { + if (typeof onCommitFiberRoot === "function") { + onCommitFiberRoot(root); } } -function stopRequestCallbackTimer(didExpire) { - if (enableUserTimingAPI) { - if (supportsUserTiming) { - isWaitingForCallback = false; - var warning$$1 = didExpire ? "React was blocked by main thread" : null; - endMark( - "(Waiting for async callback...)", - "(Waiting for async callback...)", - warning$$1 - ); - } +function onCommitUnmount(fiber) { + if (typeof onCommitFiberUnmount === "function") { + onCommitFiberUnmount(fiber); } } -function startWorkTimer(fiber) { - if (enableUserTimingAPI) { - 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; +var describeComponentFrame = function(name, source, ownerName) { + return ( + "\n in " + + (name || "Unknown") + + (source + ? " (at " + + source.fileName.replace(/^.*[\\\/]/, "") + + ":" + + source.lineNumber + + ")" + : ownerName ? " (created by " + ownerName + ")" : "") + ); +}; + +function describeFiber(fiber) { + switch (fiber.tag) { + case IndeterminateComponent: + case FunctionalComponent: + case ClassComponent: + case HostComponent: + var owner = fiber._debugOwner; + var source = fiber._debugSource; + var name = getComponentName(fiber); + var ownerName = null; + if (owner) { + ownerName = getComponentName(owner); + } + return describeComponentFrame(name, source, ownerName); + default: + return ""; } } -function cancelWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // Remember we shouldn't complete measurement for this fiber. - // Otherwise flamechart will be deep even for small updates. - fiber._debugIsCurrentlyTiming = false; - clearFiberMark(fiber, null); - } +// This function can only be called with a work-in-progress fiber and +// only during begin or complete phase. Do not call it under any other +// circumstances. +function getStackAddendumByWorkInProgressFiber(workInProgress) { + var info = ""; + var node = workInProgress; + do { + info += describeFiber(node); + // Otherwise this return pointer might point to the wrong tree: + node = node["return"]; + } while (node); + return info; } -function stopWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber["return"]; - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - endFiberMark(fiber, null, null); - } -} - -function stopFailedWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber["return"]; - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - var warning$$1 = "An error was thrown inside this error boundary"; - endFiberMark(fiber, null, warning$$1); - } -} +/** + * Forked from fbjs/warning: + * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js + * + * Only change is we use console.warn instead of console.error, + * and do nothing when 'console' is not supported. + * This really simplifies the code. + * --- + * Similar to invariant but only logs a warning if the condition is not met. + * This can be used to log issues in development environments in critical + * paths. Removing the logging code for production environments will keep the + * same logic and follow the same code paths. + */ -function startPhaseTimer(fiber, phase) { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - clearPendingPhaseMeasurement(); - if (!beginFiberMark(fiber, phase)) { - return; - } - currentPhaseFiber = fiber; - currentPhase = phase; - } -} +var lowPriorityWarning = function() {}; -function stopPhaseTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - if (currentPhase !== null && currentPhaseFiber !== null) { - var warning$$1 = hasScheduledUpdateInCurrentPhase - ? "Scheduled a cascading update" - : null; - endFiberMark(currentPhaseFiber, currentPhase, warning$$1); +{ + var printWarning = function(format) { + for ( + var _len = arguments.length, + args = Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key]; } - currentPhase = null; - currentPhaseFiber = null; - } -} -function startWorkLoopTimer(nextUnitOfWork) { - if (enableUserTimingAPI) { - currentFiber = nextUnitOfWork; - if (!supportsUserTiming) { - return; + var argIndex = 0; + var message = + "Warning: " + + format.replace(/%s/g, function() { + return args[argIndex++]; + }); + if (typeof console !== "undefined") { + console.warn(message); } - commitCountInCurrentWorkLoop = 0; - // This is top level call. - // Any other measurements are performed within. - beginMark("(React Tree Reconciliation)"); - // Resume any measurements that were in progress during the last loop. - resumeTimers(); - } -} + try { + // --- Welcome to debugging React --- + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch (x) {} + }; -function stopWorkLoopTimer(interruptedBy) { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; + lowPriorityWarning = function(condition, format) { + if (format === undefined) { + throw new Error( + "`warning(condition, format, ...args)` requires a warning " + + "message argument" + ); } - var warning$$1 = null; - if (interruptedBy !== null) { - if (interruptedBy.tag === HostRoot) { - warning$$1 = "A top-level update interrupted the previous render"; - } else { - var componentName = getComponentName(interruptedBy) || "Unknown"; - warning$$1 = - "An update to " + componentName + " interrupted the previous render"; + if (!condition) { + for ( + var _len2 = arguments.length, + args = Array(_len2 > 2 ? _len2 - 2 : 0), + _key2 = 2; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 2] = arguments[_key2]; } - } else if (commitCountInCurrentWorkLoop > 1) { - warning$$1 = "There were cascading updates"; - } - commitCountInCurrentWorkLoop = 0; - // Pause any measurements until the next loop. - pauseTimers(); - endMark( - "(React Tree Reconciliation)", - "(React Tree Reconciliation)", - warning$$1 - ); - } -} - -function startCommitTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - isCommitting = true; - hasScheduledUpdateInCurrentCommit = false; - labelsInCurrentCommit.clear(); - beginMark("(Committing Changes)"); - } -} - -function stopCommitTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - - var warning$$1 = null; - if (hasScheduledUpdateInCurrentCommit) { - warning$$1 = "Lifecycle hook scheduled a cascading update"; - } else if (commitCountInCurrentWorkLoop > 0) { - warning$$1 = "Caused by a cascading update in earlier commit"; - } - hasScheduledUpdateInCurrentCommit = false; - commitCountInCurrentWorkLoop++; - isCommitting = false; - labelsInCurrentCommit.clear(); - - endMark("(Committing Changes)", "(Committing Changes)", warning$$1); - } -} - -function startCommitHostEffectsTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - effectCountInCurrentCommit = 0; - beginMark("(Committing Host Effects)"); - } -} - -function stopCommitHostEffectsTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Committing Host Effects: " + count + " Total)", - "(Committing Host Effects)", - null - ); - } -} -function startCommitLifeCyclesTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; + printWarning.apply(undefined, [format].concat(args)); } - effectCountInCurrentCommit = 0; - beginMark("(Calling Lifecycle Methods)"); - } + }; } -function stopCommitLifeCyclesTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - "(Calling Lifecycle Methods: " + count + " Total)", - "(Calling Lifecycle Methods)", - null - ); - } -} +var lowPriorityWarning$1 = lowPriorityWarning; -var warnedAboutMissingGetChildContext = void 0; +var ReactStrictModeWarnings = { + discardPendingWarnings: function() {}, + flushPendingDeprecationWarnings: function() {}, + flushPendingUnsafeLifecycleWarnings: function() {}, + recordDeprecationWarnings: function(fiber, instance) {}, + recordUnsafeLifecycleWarnings: function(fiber, instance) {} +}; { - warnedAboutMissingGetChildContext = {}; -} + var LIFECYCLE_SUGGESTIONS = { + UNSAFE_componentWillMount: "componentDidMount", + UNSAFE_componentWillReceiveProps: "static getDerivedStateFromProps", + UNSAFE_componentWillUpdate: "componentDidUpdate" + }; -// A cursor to the current merged context object on the stack. -var contextStackCursor = createCursor(emptyObject); -// A cursor to a boolean indicating whether the context has changed. -var didPerformWorkStackCursor = createCursor(false); -// Keep track of the previous context object that was on the stack. -// We use this to get access to the parent context after we have already -// pushed the next context provider, and now need to merge their contexts. -var previousContext = emptyObject; + var pendingComponentWillMountWarnings = []; + var pendingComponentWillReceivePropsWarnings = []; + var pendingComponentWillUpdateWarnings = []; + var pendingUnsafeLifecycleWarnings = new Map(); -function getUnmaskedContext(workInProgress) { - var hasOwnContext = isContextProvider(workInProgress); - if (hasOwnContext) { - // If the fiber is a context provider itself, when we read its context - // we have already pushed its own child context on the stack. A context - // provider should not "see" its own child context. Therefore we read the - // previous (parent) context instead for a context provider. - return previousContext; - } - return contextStackCursor.current; -} + // Tracks components we have already warned about. + var didWarnAboutDeprecatedLifecycles = new Set(); + var didWarnAboutUnsafeLifecycles = new Set(); -function cacheContext(workInProgress, unmaskedContext, maskedContext) { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; - instance.__reactInternalMemoizedMaskedChildContext = maskedContext; -} + ReactStrictModeWarnings.discardPendingWarnings = function() { + pendingComponentWillMountWarnings = []; + pendingComponentWillReceivePropsWarnings = []; + pendingComponentWillUpdateWarnings = []; + pendingUnsafeLifecycleWarnings = new Map(); + }; -function getMaskedContext(workInProgress, unmaskedContext) { - var type = workInProgress.type; - var contextTypes = type.contextTypes; - if (!contextTypes) { - return emptyObject; - } - - // Avoid recreating masked context unless unmasked context has changed. - // Failing to do this will result in unnecessary calls to componentWillReceiveProps. - // This may trigger infinite loops if componentWillReceiveProps calls setState. - var instance = workInProgress.stateNode; - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) { - return instance.__reactInternalMemoizedMaskedChildContext; - } - - var context = {}; - for (var key in contextTypes) { - context[key] = unmaskedContext[key]; - } + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { + pendingUnsafeLifecycleWarnings.forEach(function( + lifecycleWarningsMap, + strictRoot + ) { + var lifecyclesWarningMesages = []; - { - var name = getComponentName(workInProgress) || "Unknown"; - checkPropTypes( - contextTypes, - context, - "context", - name, - ReactDebugCurrentFiber.getCurrentFiberStackAddendum - ); - } + Object.keys(lifecycleWarningsMap).forEach(function(lifecycle) { + var lifecycleWarnings = lifecycleWarningsMap[lifecycle]; + if (lifecycleWarnings.length > 0) { + var componentNames = new Set(); + lifecycleWarnings.forEach(function(fiber) { + componentNames.add(getComponentName(fiber) || "Component"); + didWarnAboutUnsafeLifecycles.add(fiber.type); + }); - // Cache unmasked context so we can avoid recreating masked context unless necessary. - // Context is created before the class component is instantiated so check for instance. - if (instance) { - cacheContext(workInProgress, unmaskedContext, context); - } + var formatted = lifecycle.replace("UNSAFE_", ""); + var suggestion = LIFECYCLE_SUGGESTIONS[lifecycle]; + var sortedComponentNames = Array.from(componentNames) + .sort() + .join(", "); - return context; -} + lifecyclesWarningMesages.push( + formatted + + ": Please update the following components to use " + + (suggestion + " instead: " + sortedComponentNames) + ); + } + }); -function hasContextChanged() { - return didPerformWorkStackCursor.current; -} + if (lifecyclesWarningMesages.length > 0) { + var strictRootComponentStack = getStackAddendumByWorkInProgressFiber( + strictRoot + ); -function isContextConsumer(fiber) { - return fiber.tag === ClassComponent && fiber.type.contextTypes != null; -} + warning( + false, + "Unsafe lifecycle methods were found within a strict-mode tree:%s" + + "\n\n%s" + + "\n\nLearn more about this warning here:" + + "\nhttps://fb.me/react-strict-mode-warnings", + strictRootComponentStack, + lifecyclesWarningMesages.join("\n\n") + ); + } + }); -function isContextProvider(fiber) { - return fiber.tag === ClassComponent && fiber.type.childContextTypes != null; -} + pendingUnsafeLifecycleWarnings = new Map(); + }; -function popContextProvider(fiber) { - if (!isContextProvider(fiber)) { - return; - } + var getStrictRoot = function(fiber) { + var maybeStrictRoot = null; - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor, fiber); -} + while (fiber !== null) { + if (fiber.mode & StrictMode) { + maybeStrictRoot = fiber; + } -function popTopLevelContextObject(fiber) { - pop(didPerformWorkStackCursor, fiber); - pop(contextStackCursor, fiber); -} + fiber = fiber["return"]; + } -function pushTopLevelContextObject(fiber, context, didChange) { - invariant( - contextStackCursor.cursor == null, - "Unexpected context found on stack. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + return maybeStrictRoot; + }; - push(contextStackCursor, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); -} + ReactStrictModeWarnings.flushPendingDeprecationWarnings = function() { + if (pendingComponentWillMountWarnings.length > 0) { + var uniqueNames = new Set(); + pendingComponentWillMountWarnings.forEach(function(fiber) { + uniqueNames.add(getComponentName(fiber) || "Component"); + didWarnAboutDeprecatedLifecycles.add(fiber.type); + }); -function processChildContext(fiber, parentContext) { - var instance = fiber.stateNode; - var childContextTypes = fiber.type.childContextTypes; + var sortedNames = Array.from(uniqueNames) + .sort() + .join(", "); - // TODO (bvaughn) Replace this behavior with an invariant() in the future. - // It has only been added in Fiber to match the (unintentional) behavior in Stack. - if (typeof instance.getChildContext !== "function") { - { - var componentName = getComponentName(fiber) || "Unknown"; + lowPriorityWarning$1( + false, + "componentWillMount is deprecated and will be removed in the next major version. " + + "Use componentDidMount instead. As a temporary workaround, " + + "you can rename to UNSAFE_componentWillMount." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here:" + + "\nhttps://fb.me/react-async-component-lifecycle-hooks", + sortedNames + ); - if (!warnedAboutMissingGetChildContext[componentName]) { - warnedAboutMissingGetChildContext[componentName] = true; - warning( - false, - "%s.childContextTypes is specified but there is no getChildContext() method " + - "on the instance. You can either define getChildContext() on %s or remove " + - "childContextTypes from it.", - componentName, - componentName - ); - } + pendingComponentWillMountWarnings = []; } - return parentContext; - } - - var childContext = void 0; - { - ReactDebugCurrentFiber.setCurrentPhase("getChildContext"); - } - startPhaseTimer(fiber, "getChildContext"); - childContext = instance.getChildContext(); - stopPhaseTimer(); - { - ReactDebugCurrentFiber.setCurrentPhase(null); - } - for (var contextKey in childContext) { - invariant( - contextKey in childContextTypes, - '%s.getChildContext(): key "%s" is not defined in childContextTypes.', - getComponentName(fiber) || "Unknown", - contextKey - ); - } - { - var name = getComponentName(fiber) || "Unknown"; - checkPropTypes( - childContextTypes, - childContext, - "child context", - name, - // In practice, there is one case in which we won't get a stack. It's when - // somebody calls unstable_renderSubtreeIntoContainer() and we process - // context from the parent component instance. The stack will be missing - // because it's outside of the reconciliation, and so the pointer has not - // been set. This is rare and doesn't matter. We'll also remove that API. - ReactDebugCurrentFiber.getCurrentFiberStackAddendum - ); - } - return Object.assign({}, parentContext, childContext); -} + if (pendingComponentWillReceivePropsWarnings.length > 0) { + var _uniqueNames = new Set(); + pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { + _uniqueNames.add(getComponentName(fiber) || "Component"); + didWarnAboutDeprecatedLifecycles.add(fiber.type); + }); -function pushContextProvider(workInProgress) { - if (!isContextProvider(workInProgress)) { - return false; - } + var _sortedNames = Array.from(_uniqueNames) + .sort() + .join(", "); - var instance = workInProgress.stateNode; - // We push the context as early as possible to ensure stack integrity. - // If the instance does not exist yet, we will push null at first, - // and replace it on the stack later when invalidating the context. - var memoizedMergedChildContext = - (instance && instance.__reactInternalMemoizedMergedChildContext) || - emptyObject; - - // Remember the parent context so we can merge with it later. - // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. - previousContext = contextStackCursor.current; - push(contextStackCursor, memoizedMergedChildContext, workInProgress); - push( - didPerformWorkStackCursor, - didPerformWorkStackCursor.current, - workInProgress - ); + lowPriorityWarning$1( + false, + "componentWillReceiveProps is deprecated and will be removed in the next major version. " + + "Use static getDerivedStateFromProps instead." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here:" + + "\nhttps://fb.me/react-async-component-lifecycle-hooks", + _sortedNames + ); - return true; -} + pendingComponentWillReceivePropsWarnings = []; + } -function invalidateContextProvider(workInProgress, didChange) { - var instance = workInProgress.stateNode; - invariant( - instance, - "Expected to have an instance by this point. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + if (pendingComponentWillUpdateWarnings.length > 0) { + var _uniqueNames2 = new Set(); + pendingComponentWillUpdateWarnings.forEach(function(fiber) { + _uniqueNames2.add(getComponentName(fiber) || "Component"); + didWarnAboutDeprecatedLifecycles.add(fiber.type); + }); - if (didChange) { - // Merge parent and own context. - // Skip this if we're not updating due to sCU. - // This avoids unnecessarily recomputing memoized values. - var mergedContext = processChildContext(workInProgress, previousContext); - instance.__reactInternalMemoizedMergedChildContext = mergedContext; - - // Replace the old (or empty) context with the new one. - // It is important to unwind the context in the reverse order. - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor, workInProgress); - // Now push the new context and mark that it has changed. - push(contextStackCursor, mergedContext, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } else { - pop(didPerformWorkStackCursor, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); - } -} + var _sortedNames2 = Array.from(_uniqueNames2) + .sort() + .join(", "); -function resetContext() { - previousContext = emptyObject; - contextStackCursor.current = emptyObject; - didPerformWorkStackCursor.current = false; -} + lowPriorityWarning$1( + false, + "componentWillUpdate is deprecated and will be removed in the next major version. " + + "Use componentDidUpdate instead. As a temporary workaround, " + + "you can rename to UNSAFE_componentWillUpdate." + + "\n\nPlease update the following components: %s" + + "\n\nLearn more about this warning here:" + + "\nhttps://fb.me/react-async-component-lifecycle-hooks", + _sortedNames2 + ); -function findCurrentUnmaskedContext(fiber) { - // Currently this is only used with renderSubtreeIntoContainer; not sure if it - // makes sense elsewhere - invariant( - isFiberMounted(fiber) && fiber.tag === ClassComponent, - "Expected subtree parent to be a mounted class component. " + - "This error is likely caused by a bug in React. Please file an issue." - ); + pendingComponentWillUpdateWarnings = []; + } + }; - var node = fiber; - while (node.tag !== HostRoot) { - if (isContextProvider(node)) { - return node.stateNode.__reactInternalMemoizedMergedChildContext; + ReactStrictModeWarnings.recordDeprecationWarnings = function( + fiber, + instance + ) { + // Dedup strategy: Warn once per component. + if (didWarnAboutDeprecatedLifecycles.has(fiber.type)) { + return; } - var parent = node["return"]; - invariant( - parent, - "Found unexpected detached subtree parent. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - node = parent; - } - return node.stateNode.context; -} -// Max 31 bit integer. The max integer size in V8 for 32-bit systems. -// Math.pow(2, 30) - 1 -// 0b111111111111111111111111111111 -var MAX_SIGNED_31_BIT_INT = 1073741823; + // Don't warn about react-lifecycles-compat polyfilled components. + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber); + } + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber); + } + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber); + } + }; -// TODO: Use an opaque type once ESLint et al support the syntax + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( + fiber, + instance + ) { + var strictRoot = getStrictRoot(fiber); -var NoWork = 0; -var Sync = 1; -var Never = MAX_SIGNED_31_BIT_INT; + // Dedup strategy: Warn once per component. + // This is difficult to track any other way since component names + // are often vague and are likely to collide between 3rd party libraries. + // An expand property is probably okay to use here since it's DEV-only, + // and will only be set in the event of serious warnings. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return; + } -var UNIT_SIZE = 10; -var MAGIC_NUMBER_OFFSET = 2; + // Don't warn about react-lifecycles-compat polyfilled components. + // Note that it is sufficient to check for the presence of a + // single lifecycle, componentWillMount, with the polyfill flag. + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning === true + ) { + return; + } -// 1 unit of expiration time represents 10ms. -function msToExpirationTime(ms) { - // Always add an offset so that we don't clash with the magic number for NoWork. - return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET; -} + var warningsForRoot = void 0; + if (!pendingUnsafeLifecycleWarnings.has(strictRoot)) { + warningsForRoot = { + UNSAFE_componentWillMount: [], + UNSAFE_componentWillReceiveProps: [], + UNSAFE_componentWillUpdate: [] + }; -function expirationTimeToMs(expirationTime) { - return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE; -} + pendingUnsafeLifecycleWarnings.set(strictRoot, warningsForRoot); + } else { + warningsForRoot = pendingUnsafeLifecycleWarnings.get(strictRoot); + } -function ceiling(num, precision) { - return (((num / precision) | 0) + 1) * precision; -} + var unsafeLifecycles = []; + if ( + typeof instance.componentWillMount === "function" || + typeof instance.UNSAFE_componentWillMount === "function" + ) { + unsafeLifecycles.push("UNSAFE_componentWillMount"); + } + if ( + typeof instance.componentWillReceiveProps === "function" || + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + unsafeLifecycles.push("UNSAFE_componentWillReceiveProps"); + } + if ( + typeof instance.componentWillUpdate === "function" || + typeof instance.UNSAFE_componentWillUpdate === "function" + ) { + unsafeLifecycles.push("UNSAFE_componentWillUpdate"); + } -function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { - return ceiling( - currentTime + expirationInMs / UNIT_SIZE, - bucketSizeMs / UNIT_SIZE - ); + if (unsafeLifecycles.length > 0) { + unsafeLifecycles.forEach(function(lifecycle) { + warningsForRoot[lifecycle].push(fiber); + }); + } + }; } -var NoContext = 0; -var AsyncMode = 1; -var StrictMode = 2; +// Re-export dynamic flags from the fbsource version. +var _require = require("ReactFeatureFlags"); -var hasBadMapPolyfill = void 0; +var enableGetDerivedStateFromCatch = _require.enableGetDerivedStateFromCatch; +var debugRenderPhaseSideEffects = _require.debugRenderPhaseSideEffects; +var debugRenderPhaseSideEffectsForStrictMode = + _require.debugRenderPhaseSideEffectsForStrictMode; +var warnAboutDeprecatedLifecycles = _require.warnAboutDeprecatedLifecycles; +var replayFailedUnitOfWorkWithInvokeGuardedCallback = + _require.replayFailedUnitOfWorkWithInvokeGuardedCallback; -{ - hasBadMapPolyfill = false; - try { - var nonExtensibleObject = Object.preventExtensions({}); - var testMap = new Map([[nonExtensibleObject, null]]); - var testSet = new Set([nonExtensibleObject]); - // This is necessary for Rollup to not consider these unused. - // https://github.com/rollup/rollup/issues/1771 - // TODO: we can remove these if Rollup fixes the bug. - testMap.set(0, 0); - testSet.add(0); - } catch (e) { - // TODO: Consider warning about bad polyfills - hasBadMapPolyfill = true; +var enableUserTimingAPI = true; +var enableMutatingReconciler = true; +var enableNoopReconciler = false; +var enablePersistentReconciler = false; + +// Only used in www builds. + +function getCurrentFiberOwnerName() { + { + var fiber = ReactDebugCurrentFiber.current; + if (fiber === null) { + return null; + } + var owner = fiber._debugOwner; + if (owner !== null && typeof owner !== "undefined") { + return getComponentName(owner); + } } + return null; } -// A Fiber is work on a Component that needs to be done or was done. There can -// be more than one per component. - -var debugCounter = void 0; +function getCurrentFiberStackAddendum() { + { + var fiber = ReactDebugCurrentFiber.current; + if (fiber === null) { + return null; + } + // Safe because if current fiber exists, we are reconciling, + // and it is guaranteed to be the work-in-progress version. + return getStackAddendumByWorkInProgressFiber(fiber); + } + return null; +} -{ - debugCounter = 1; +function resetCurrentFiber() { + ReactDebugCurrentFrame.getCurrentStack = null; + ReactDebugCurrentFiber.current = null; + ReactDebugCurrentFiber.phase = null; } -function FiberNode(tag, pendingProps, key, mode) { - // Instance - this.tag = tag; - this.key = key; - this.type = null; - this.stateNode = null; +function setCurrentFiber(fiber) { + ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; + ReactDebugCurrentFiber.current = fiber; + ReactDebugCurrentFiber.phase = null; +} - // Fiber - this["return"] = null; - this.child = null; - this.sibling = null; - this.index = 0; +function setCurrentPhase(phase) { + ReactDebugCurrentFiber.phase = phase; +} - this.ref = null; +var ReactDebugCurrentFiber = { + current: null, + phase: null, + resetCurrentFiber: resetCurrentFiber, + setCurrentFiber: setCurrentFiber, + setCurrentPhase: setCurrentPhase, + getCurrentFiberOwnerName: getCurrentFiberOwnerName, + getCurrentFiberStackAddendum: getCurrentFiberStackAddendum +}; - this.pendingProps = pendingProps; - this.memoizedProps = null; - this.updateQueue = null; - this.memoizedState = null; +// Prefix measurements so that it's possible to filter them. +// Longer prefixes are hard to read in DevTools. +var reactEmoji = "\u269B"; +var warningEmoji = "\u26D4"; +var supportsUserTiming = + typeof performance !== "undefined" && + typeof performance.mark === "function" && + typeof performance.clearMarks === "function" && + typeof performance.measure === "function" && + typeof performance.clearMeasures === "function"; - this.mode = mode; +// Keep track of current fiber so that we know the path to unwind on pause. +// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? +var currentFiber = null; +// If we're in the middle of user code, which fiber and method is it? +// Reusing `currentFiber` would be confusing for this because user code fiber +// can change during commit phase too, but we don't need to unwind it (since +// lifecycles in the commit phase don't resemble a tree). +var currentPhase = null; +var currentPhaseFiber = null; +// Did lifecycle hook schedule an update? This is often a performance problem, +// so we will keep track of it, and include it in the report. +// Track commits caused by cascading updates. +var isCommitting = false; +var hasScheduledUpdateInCurrentCommit = false; +var hasScheduledUpdateInCurrentPhase = false; +var commitCountInCurrentWorkLoop = 0; +var effectCountInCurrentCommit = 0; +var isWaitingForCallback = false; +// During commits, we only show a measurement once per method name +// to avoid stretch the commit phase with measurement overhead. +var labelsInCurrentCommit = new Set(); - // Effects - this.effectTag = NoEffect; - this.nextEffect = null; +var formatMarkName = function(markName) { + return reactEmoji + " " + markName; +}; - this.firstEffect = null; - this.lastEffect = null; +var formatLabel = function(label, warning$$1) { + var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; + var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; + return "" + prefix + label + suffix; +}; - this.expirationTime = NoWork; +var beginMark = function(markName) { + performance.mark(formatMarkName(markName)); +}; - this.alternate = null; +var clearMark = function(markName) { + performance.clearMarks(formatMarkName(markName)); +}; - { - this._debugID = debugCounter++; - this._debugSource = null; - this._debugOwner = null; - this._debugIsCurrentlyTiming = false; - if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") { - Object.preventExtensions(this); - } - } -} +var endMark = function(label, markName, warning$$1) { + var formattedMarkName = formatMarkName(markName); + var formattedLabel = formatLabel(label, warning$$1); + try { + performance.measure(formattedLabel, formattedMarkName); + } catch (err) {} + // If previous mark was missing for some reason, this will throw. + // This could only happen if React crashed in an unexpected place earlier. + // Don't pile on with more errors. -// This is a constructor function, rather than a POJO constructor, still -// please ensure we do the following: -// 1) Nobody should add any instance methods on this. Instance methods can be -// more difficult to predict when they get optimized and they are almost -// never inlined properly in static compilers. -// 2) Nobody should rely on `instanceof Fiber` for type testing. We should -// always know when it is a fiber. -// 3) We might want to experiment with using numeric keys since they are easier -// to optimize in a non-JIT environment. -// 4) We can easily go from a constructor to a createFiber object literal if that -// is faster. -// 5) It should be easy to port this to a C struct and keep a C implementation -// compatible. -var createFiber = function(tag, pendingProps, key, mode) { - // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors - return new FiberNode(tag, pendingProps, key, mode); + // Clear marks immediately to avoid growing buffer. + performance.clearMarks(formattedMarkName); + performance.clearMeasures(formattedLabel); }; -function shouldConstruct(Component) { - return !!(Component.prototype && Component.prototype.isReactComponent); -} +var getFiberMarkName = function(label, debugID) { + return label + " (#" + debugID + ")"; +}; -// This is used to create an alternate fiber to do work on. -function createWorkInProgress(current, pendingProps, expirationTime) { - var workInProgress = current.alternate; - if (workInProgress === null) { - // We use a double buffering pooling technique because we know that we'll - // only ever need at most two versions of a tree. We pool the "other" unused - // node that we're free to reuse. This is lazily created to avoid allocating - // extra objects for things that are never updated. It also allow us to - // reclaim the extra memory if needed. - workInProgress = createFiber( - current.tag, - pendingProps, - current.key, - current.mode - ); - workInProgress.type = current.type; - workInProgress.stateNode = current.stateNode; +var getFiberLabel = function(componentName, isMounted, phase) { + if (phase === null) { + // These are composite component total time measurements. + return componentName + " [" + (isMounted ? "update" : "mount") + "]"; + } else { + // Composite component methods. + return componentName + "." + phase; + } +}; - { - // DEV-only fields - workInProgress._debugID = current._debugID; - workInProgress._debugSource = current._debugSource; - workInProgress._debugOwner = current._debugOwner; - } - - workInProgress.alternate = current; - current.alternate = workInProgress; - } else { - workInProgress.pendingProps = pendingProps; - - // We already have an alternate. - // Reset the effect tag. - workInProgress.effectTag = NoEffect; +var beginFiberMark = function(fiber, phase) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); - // The effect list is no longer valid. - workInProgress.nextEffect = null; - workInProgress.firstEffect = null; - workInProgress.lastEffect = null; + if (isCommitting && labelsInCurrentCommit.has(label)) { + // During the commit phase, we don't show duplicate labels because + // there is a fixed overhead for every measurement, and we don't + // want to stretch the commit phase beyond necessary. + return false; } + labelsInCurrentCommit.add(label); - workInProgress.expirationTime = expirationTime; - - workInProgress.child = current.child; - workInProgress.memoizedProps = current.memoizedProps; - workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; - - // These will be overridden during the parent's reconciliation - workInProgress.sibling = current.sibling; - workInProgress.index = current.index; - workInProgress.ref = current.ref; + var markName = getFiberMarkName(label, debugID); + beginMark(markName); + return true; +}; - return workInProgress; -} +var clearFiberMark = function(fiber, phase) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + var markName = getFiberMarkName(label, debugID); + clearMark(markName); +}; -function createHostRootFiber(isAsync) { - var mode = isAsync ? AsyncMode | StrictMode : NoContext; - return createFiber(HostRoot, null, null, mode); -} +var endFiberMark = function(fiber, phase, warning$$1) { + var componentName = getComponentName(fiber) || "Unknown"; + var debugID = fiber._debugID; + var isMounted = fiber.alternate !== null; + var label = getFiberLabel(componentName, isMounted, phase); + var markName = getFiberMarkName(label, debugID); + endMark(label, markName, warning$$1); +}; -function createFiberFromElement(element, mode, expirationTime) { - var owner = null; - { - owner = element._owner; +var shouldIgnoreFiber = function(fiber) { + // Host components should be skipped in the timeline. + // We could check typeof fiber.type, but does this work with RN? + switch (fiber.tag) { + case HostRoot: + case HostComponent: + case HostText: + case HostPortal: + case CallComponent: + case ReturnComponent: + case Fragment: + case ContextProvider: + case ContextConsumer: + return true; + default: + return false; } +}; - var fiber = void 0; - var type = element.type; - var key = element.key; - var pendingProps = element.props; +var clearPendingPhaseMeasurement = function() { + if (currentPhase !== null && currentPhaseFiber !== null) { + clearFiberMark(currentPhaseFiber, currentPhase); + } + currentPhaseFiber = null; + currentPhase = null; + hasScheduledUpdateInCurrentPhase = false; +}; - var fiberTag = void 0; - if (typeof type === "function") { - fiberTag = shouldConstruct(type) ? ClassComponent : IndeterminateComponent; - } else if (typeof type === "string") { - fiberTag = HostComponent; - } else { - switch (type) { - case REACT_FRAGMENT_TYPE: - return createFiberFromFragment( - pendingProps.children, - mode, - expirationTime, - key - ); - case REACT_ASYNC_MODE_TYPE: - fiberTag = Mode; - mode |= AsyncMode | StrictMode; - break; - case REACT_STRICT_MODE_TYPE: - fiberTag = Mode; - mode |= StrictMode; - break; - case REACT_CALL_TYPE: - fiberTag = CallComponent; - break; - case REACT_RETURN_TYPE: - fiberTag = ReturnComponent; - break; - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break; - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break; - default: - if (typeof type.tag === "number") { - // Currently assumed to be a continuation and therefore is a - // fiber already. - // TODO: The yield system is currently broken for updates in - // some cases. The reified yield stores a fiber, but we don't - // know which fiber that is; the current or a workInProgress? - // When the continuation gets rendered here we don't know if we - // can reuse that fiber or if we need to clone it. There is - // probably a clever way to restructure this. - fiber = type; - fiber.pendingProps = pendingProps; - fiber.expirationTime = expirationTime; - return fiber; - } else { - throwOnInvalidElementType(type, owner); - } - break; - } - } else { - throwOnInvalidElementType(type, owner); - } - } +var pauseTimers = function() { + // Stops all currently active measurements so that they can be resumed + // if we continue in a later deferred loop from the same unit of work. + var fiber = currentFiber; + while (fiber) { + if (fiber._debugIsCurrentlyTiming) { + endFiberMark(fiber, null, null); } + fiber = fiber["return"]; } +}; - fiber = createFiber(fiberTag, pendingProps, key, mode); - fiber.type = type; - fiber.expirationTime = expirationTime; +var resumeTimersRecursively = function(fiber) { + if (fiber["return"] !== null) { + resumeTimersRecursively(fiber["return"]); + } + if (fiber._debugIsCurrentlyTiming) { + beginFiberMark(fiber, null); + } +}; - { - fiber._debugSource = element._source; - fiber._debugOwner = element._owner; +var resumeTimers = function() { + // Resumes all measurements that were active during the last deferred loop. + if (currentFiber !== null) { + resumeTimersRecursively(currentFiber); } +}; - return fiber; +function recordEffect() { + if (enableUserTimingAPI) { + effectCountInCurrentCommit++; + } } -function throwOnInvalidElementType(type, owner) { - var info = ""; - { +function recordScheduleUpdate() { + if (enableUserTimingAPI) { + if (isCommitting) { + hasScheduledUpdateInCurrentCommit = true; + } if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) + currentPhase !== null && + currentPhase !== "componentWillMount" && + currentPhase !== "componentWillReceiveProps" ) { - info += - " You likely forgot to export your component from the file " + - "it's defined in, or you might have mixed up default and " + - "named imports."; - } - var ownerName = owner ? getComponentName(owner) : null; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; + hasScheduledUpdateInCurrentPhase = true; } } - invariant( - false, - "Element type is invalid: expected a string (for built-in " + - "components) or a class/function (for composite components) " + - "but got: %s.%s", - type == null ? type : typeof type, - info - ); } -function createFiberFromFragment(elements, mode, expirationTime, key) { - var fiber = createFiber(Fragment, elements, key, mode); - fiber.expirationTime = expirationTime; - return fiber; +function startRequestCallbackTimer() { + if (enableUserTimingAPI) { + if (supportsUserTiming && !isWaitingForCallback) { + isWaitingForCallback = true; + beginMark("(Waiting for async callback...)"); + } + } } -function createFiberFromText(content, mode, expirationTime) { - var fiber = createFiber(HostText, content, null, mode); - fiber.expirationTime = expirationTime; - return fiber; +function stopRequestCallbackTimer(didExpire, expirationTime) { + if (enableUserTimingAPI) { + if (supportsUserTiming) { + isWaitingForCallback = false; + var warning$$1 = didExpire ? "React was blocked by main thread" : null; + endMark( + "(Waiting for async callback... will force flush in " + + expirationTime + + " ms)", + "(Waiting for async callback...)", + warning$$1 + ); + } + } } -function createFiberFromHostInstanceForDeletion() { - var fiber = createFiber(HostComponent, null, null, NoContext); - fiber.type = "DELETED"; - return fiber; -} - -function createFiberFromPortal(portal, mode, expirationTime) { - var pendingProps = portal.children !== null ? portal.children : []; - var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); - fiber.expirationTime = expirationTime; - fiber.stateNode = { - containerInfo: portal.containerInfo, - pendingChildren: null, // Used by persistent updates - implementation: portal.implementation - }; - return fiber; -} - -// TODO: This should be lifted into the renderer. - -function createFiberRoot(containerInfo, isAsync, hydrate) { - // Cyclic construction. This cheats the type system right now because - // stateNode is any. - var uninitializedFiber = createHostRootFiber(isAsync); - var root = { - current: uninitializedFiber, - containerInfo: containerInfo, - pendingChildren: null, - pendingCommitExpirationTime: NoWork, - finishedWork: null, - context: null, - pendingContext: null, - hydrate: hydrate, - remainingExpirationTime: NoWork, - firstBatch: null, - nextScheduledRoot: null - }; - uninitializedFiber.stateNode = root; - return root; +function startWorkTimer(fiber) { + if (enableUserTimingAPI) { + 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; + } } -var onCommitFiberRoot = null; -var onCommitFiberUnmount = null; -var hasLoggedError = false; - -function catchErrors(fn) { - return function(arg) { - try { - return fn(arg); - } catch (err) { - if (true && !hasLoggedError) { - hasLoggedError = true; - warning(false, "React DevTools encountered an error: %s", err); - } +function cancelWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; } - }; + // Remember we shouldn't complete measurement for this fiber. + // Otherwise flamechart will be deep even for small updates. + fiber._debugIsCurrentlyTiming = false; + clearFiberMark(fiber, null); + } } -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { - // No DevTools - return false; - } - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - if (hook.isDisabled) { - // This isn't a real property on the hook, but it can be set to opt out - // of DevTools integration and associated warnings and logs. - // https://github.com/facebook/react/issues/3877 - return true; - } - if (!hook.supportsFiber) { - { - warning( - false, - "The installed version of React DevTools is too old and will not work " + - "with the current version of React. Please update React DevTools. " + - "https://fb.me/react-devtools" - ); +function stopWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; } - // DevTools exists, even though it doesn't support Fiber. - return true; - } - try { - var rendererID = hook.inject(internals); - // We have successfully injected, so now it is safe to set up hooks. - onCommitFiberRoot = catchErrors(function(root) { - return hook.onCommitFiberRoot(rendererID, root); - }); - onCommitFiberUnmount = catchErrors(function(fiber) { - return hook.onCommitFiberUnmount(rendererID, fiber); - }); - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - warning(false, "React DevTools encountered an error: %s.", err); + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber["return"]; + if (!fiber._debugIsCurrentlyTiming) { + return; } + fiber._debugIsCurrentlyTiming = false; + endFiberMark(fiber, null, null); } - // DevTools exists - return true; } -function onCommitRoot(root) { - if (typeof onCommitFiberRoot === "function") { - onCommitFiberRoot(root); +function stopFailedWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return; + } + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber["return"]; + if (!fiber._debugIsCurrentlyTiming) { + return; + } + fiber._debugIsCurrentlyTiming = false; + var warning$$1 = "An error was thrown inside this error boundary"; + endFiberMark(fiber, null, warning$$1); } } -function onCommitUnmount(fiber) { - if (typeof onCommitFiberUnmount === "function") { - onCommitFiberUnmount(fiber); +function startPhaseTimer(fiber, phase) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + clearPendingPhaseMeasurement(); + if (!beginFiberMark(fiber, phase)) { + return; + } + currentPhaseFiber = fiber; + currentPhase = phase; } } -/** - * Forked from fbjs/warning: - * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js - * - * Only change is we use console.warn instead of console.error, - * and do nothing when 'console' is not supported. - * This really simplifies the code. - * --- - * Similar to invariant but only logs a warning if the condition is not met. - * This can be used to log issues in development environments in critical - * paths. Removing the logging code for production environments will keep the - * same logic and follow the same code paths. - */ - -var lowPriorityWarning = function() {}; - -{ - var printWarning = function(format) { - for ( - var _len = arguments.length, - args = Array(_len > 1 ? _len - 1 : 0), - _key = 1; - _key < _len; - _key++ - ) { - args[_key - 1] = arguments[_key]; +function stopPhaseTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + if (currentPhase !== null && currentPhaseFiber !== null) { + var warning$$1 = hasScheduledUpdateInCurrentPhase + ? "Scheduled a cascading update" + : null; + endFiberMark(currentPhaseFiber, currentPhase, warning$$1); } + currentPhase = null; + currentPhaseFiber = null; + } +} - var argIndex = 0; - var message = - "Warning: " + - format.replace(/%s/g, function() { - return args[argIndex++]; - }); - if (typeof console !== "undefined") { - console.warn(message); +function startWorkLoopTimer(nextUnitOfWork) { + if (enableUserTimingAPI) { + currentFiber = nextUnitOfWork; + if (!supportsUserTiming) { + return; } - try { - // --- Welcome to debugging React --- - // This error was thrown as a convenience so that you can use this stack - // to find the callsite that caused this warning to fire. - throw new Error(message); - } catch (x) {} - }; + commitCountInCurrentWorkLoop = 0; + // This is top level call. + // Any other measurements are performed within. + beginMark("(React Tree Reconciliation)"); + // Resume any measurements that were in progress during the last loop. + resumeTimers(); + } +} - lowPriorityWarning = function(condition, format) { - if (format === undefined) { - throw new Error( - "`warning(condition, format, ...args)` requires a warning " + - "message argument" - ); +function stopWorkLoopTimer(interruptedBy, didCompleteRoot) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; } - if (!condition) { - for ( - var _len2 = arguments.length, - args = Array(_len2 > 2 ? _len2 - 2 : 0), - _key2 = 2; - _key2 < _len2; - _key2++ - ) { - args[_key2 - 2] = arguments[_key2]; + var warning$$1 = null; + if (interruptedBy !== null) { + if (interruptedBy.tag === HostRoot) { + warning$$1 = "A top-level update interrupted the previous render"; + } else { + var componentName = getComponentName(interruptedBy) || "Unknown"; + warning$$1 = + "An update to " + componentName + " interrupted the previous render"; } - - printWarning.apply(undefined, [format].concat(args)); + } else if (commitCountInCurrentWorkLoop > 1) { + warning$$1 = "There were cascading updates"; } - }; + commitCountInCurrentWorkLoop = 0; + var label = didCompleteRoot + ? "(React Tree Reconciliation: Completed Root)" + : "(React Tree Reconciliation: Yielded)"; + // Pause any measurements until the next loop. + pauseTimers(); + endMark(label, "(React Tree Reconciliation)", warning$$1); + } } -var lowPriorityWarning$1 = lowPriorityWarning; - -var ReactStrictModeWarnings = { - discardPendingWarnings: function() {}, - flushPendingDeprecationWarnings: function() {}, - flushPendingUnsafeLifecycleWarnings: function() {}, - recordDeprecationWarnings: function(fiber, instance) {}, - recordUnsafeLifecycleWarnings: function(fiber, instance) {} -}; - -{ - var LIFECYCLE_SUGGESTIONS = { - UNSAFE_componentWillMount: "componentDidMount", - UNSAFE_componentWillReceiveProps: "static getDerivedStateFromProps", - UNSAFE_componentWillUpdate: "componentDidUpdate" - }; +function startCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + isCommitting = true; + hasScheduledUpdateInCurrentCommit = false; + labelsInCurrentCommit.clear(); + beginMark("(Committing Changes)"); + } +} - var pendingComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUnsafeLifecycleWarnings = new Map(); +function stopCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } - // Tracks components we have already warned about. - var didWarnAboutDeprecatedLifecycles = new Set(); - var didWarnAboutUnsafeLifecycles = new Set(); + var warning$$1 = null; + if (hasScheduledUpdateInCurrentCommit) { + warning$$1 = "Lifecycle hook scheduled a cascading update"; + } else if (commitCountInCurrentWorkLoop > 0) { + warning$$1 = "Caused by a cascading update in earlier commit"; + } + hasScheduledUpdateInCurrentCommit = false; + commitCountInCurrentWorkLoop++; + isCommitting = false; + labelsInCurrentCommit.clear(); - ReactStrictModeWarnings.discardPendingWarnings = function() { - pendingComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUnsafeLifecycleWarnings = new Map(); - }; + endMark("(Committing Changes)", "(Committing Changes)", warning$$1); + } +} - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() { - pendingUnsafeLifecycleWarnings.forEach(function( - lifecycleWarningsMap, - strictRoot - ) { - var lifecyclesWarningMesages = []; +function startCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Committing Snapshot Effects)"); + } +} - Object.keys(lifecycleWarningsMap).forEach(function(lifecycle) { - var lifecycleWarnings = lifecycleWarningsMap[lifecycle]; - if (lifecycleWarnings.length > 0) { - var componentNames = new Set(); - lifecycleWarnings.forEach(function(fiber) { - componentNames.add(getComponentName(fiber) || "Component"); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); +function stopCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Committing Snapshot Effects: " + count + " Total)", + "(Committing Snapshot Effects)", + null + ); + } +} - var formatted = lifecycle.replace("UNSAFE_", ""); - var suggestion = LIFECYCLE_SUGGESTIONS[lifecycle]; - var sortedComponentNames = Array.from(componentNames) - .sort() - .join(", "); +function startCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Committing Host Effects)"); + } +} - lifecyclesWarningMesages.push( - formatted + - ": Please update the following components to use " + - (suggestion + " instead: " + sortedComponentNames) - ); - } - }); +function stopCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Committing Host Effects: " + count + " Total)", + "(Committing Host Effects)", + null + ); + } +} - if (lifecyclesWarningMesages.length > 0) { - var strictRootComponentStack = getStackAddendumByWorkInProgressFiber( - strictRoot - ); +function startCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Calling Lifecycle Methods)"); + } +} - warning( - false, - "Unsafe lifecycle methods were found within a strict-mode tree:%s" + - "\n\n%s" + - "\n\nLearn more about this warning here:" + - "\nhttps://fb.me/react-strict-mode-warnings", - strictRootComponentStack, - lifecyclesWarningMesages.join("\n\n") - ); - } - }); +function stopCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Calling Lifecycle Methods: " + count + " Total)", + "(Calling Lifecycle Methods)", + null + ); + } +} - pendingUnsafeLifecycleWarnings = new Map(); - }; +var didWarnUpdateInsideUpdate = void 0; - var getStrictRoot = function(fiber) { - var maybeStrictRoot = null; +{ + didWarnUpdateInsideUpdate = false; +} - while (fiber !== null) { - if (fiber.mode & StrictMode) { - maybeStrictRoot = fiber; - } +// Callbacks are not validated until invocation - fiber = fiber["return"]; - } +// Singly linked-list of updates. When an update is scheduled, it is added to +// the queue of the current fiber and the work-in-progress fiber. The two queues +// are separate but they share a persistent structure. +// +// During reconciliation, updates are removed from the work-in-progress fiber, +// but they remain on the current fiber. That ensures that if a work-in-progress +// is aborted, the aborted updates are recovered by cloning from current. +// +// The work-in-progress queue is always a subset of the current queue. +// +// When the tree is committed, the work-in-progress becomes the current. - return maybeStrictRoot; +function createUpdateQueue(baseState) { + var queue = { + baseState: baseState, + expirationTime: NoWork, + first: null, + last: null, + callbackList: null, + hasForceUpdate: false, + isInitialized: false, + capturedValues: null }; + { + queue.isProcessing = false; + } + return queue; +} - ReactStrictModeWarnings.flushPendingDeprecationWarnings = function() { - if (pendingComponentWillMountWarnings.length > 0) { - var uniqueNames = new Set(); - pendingComponentWillMountWarnings.forEach(function(fiber) { - uniqueNames.add(getComponentName(fiber) || "Component"); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); - - var sortedNames = Array.from(uniqueNames) - .sort() - .join(", "); +function insertUpdateIntoQueue(queue, update) { + // Append the update to the end of the list. + if (queue.last === null) { + // Queue is empty + queue.first = queue.last = update; + } else { + queue.last.next = update; + queue.last = update; + } + if ( + queue.expirationTime === NoWork || + queue.expirationTime > update.expirationTime + ) { + queue.expirationTime = update.expirationTime; + } +} - lowPriorityWarning$1( - false, - "componentWillMount is deprecated and will be removed in the next major version. " + - "Use componentDidMount instead. As a temporary workaround, " + - "you can rename to UNSAFE_componentWillMount." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here:" + - "\nhttps://fb.me/react-async-component-lifecycle-hooks", - sortedNames - ); +var q1 = void 0; +var q2 = void 0; +function ensureUpdateQueues(fiber) { + q1 = q2 = null; + // We'll have at least one and at most two distinct update queues. + var alternateFiber = fiber.alternate; + var queue1 = fiber.updateQueue; + if (queue1 === null) { + // TODO: We don't know what the base state will be until we begin work. + // It depends on which fiber is the next current. Initialize with an empty + // base state, then set to the memoizedState when rendering. Not super + // happy with this approach. + queue1 = fiber.updateQueue = createUpdateQueue(null); + } - pendingComponentWillMountWarnings = []; - } - - if (pendingComponentWillReceivePropsWarnings.length > 0) { - var _uniqueNames = new Set(); - pendingComponentWillReceivePropsWarnings.forEach(function(fiber) { - _uniqueNames.add(getComponentName(fiber) || "Component"); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); - - var _sortedNames = Array.from(_uniqueNames) - .sort() - .join(", "); - - lowPriorityWarning$1( - false, - "componentWillReceiveProps is deprecated and will be removed in the next major version. " + - "Use static getDerivedStateFromProps instead." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here:" + - "\nhttps://fb.me/react-async-component-lifecycle-hooks", - _sortedNames - ); - - pendingComponentWillReceivePropsWarnings = []; - } - - if (pendingComponentWillUpdateWarnings.length > 0) { - var _uniqueNames2 = new Set(); - pendingComponentWillUpdateWarnings.forEach(function(fiber) { - _uniqueNames2.add(getComponentName(fiber) || "Component"); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); - - var _sortedNames2 = Array.from(_uniqueNames2) - .sort() - .join(", "); - - lowPriorityWarning$1( - false, - "componentWillUpdate is deprecated and will be removed in the next major version. " + - "Use componentDidUpdate instead. As a temporary workaround, " + - "you can rename to UNSAFE_componentWillUpdate." + - "\n\nPlease update the following components: %s" + - "\n\nLearn more about this warning here:" + - "\nhttps://fb.me/react-async-component-lifecycle-hooks", - _sortedNames2 - ); - - pendingComponentWillUpdateWarnings = []; - } - }; - - ReactStrictModeWarnings.recordDeprecationWarnings = function( - fiber, - instance - ) { - // Dedup strategy: Warn once per component. - if (didWarnAboutDeprecatedLifecycles.has(fiber.type)) { - return; - } - - // Don't warn about react-lifecycles-compat polyfilled components. - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning !== true - ) { - pendingComponentWillMountWarnings.push(fiber); - } - if ( - typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== true - ) { - pendingComponentWillReceivePropsWarnings.push(fiber); - } - if (typeof instance.componentWillUpdate === "function") { - pendingComponentWillUpdateWarnings.push(fiber); - } - }; - - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function( - fiber, - instance - ) { - var strictRoot = getStrictRoot(fiber); - - // Dedup strategy: Warn once per component. - // This is difficult to track any other way since component names - // are often vague and are likely to collide between 3rd party libraries. - // An expand property is probably okay to use here since it's DEV-only, - // and will only be set in the event of serious warnings. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } - - // Don't warn about react-lifecycles-compat polyfilled components. - // Note that it is sufficient to check for the presence of a - // single lifecycle, componentWillMount, with the polyfill flag. - if ( - typeof instance.componentWillMount === "function" && - instance.componentWillMount.__suppressDeprecationWarning === true - ) { - return; - } - - var warningsForRoot = void 0; - if (!pendingUnsafeLifecycleWarnings.has(strictRoot)) { - warningsForRoot = { - UNSAFE_componentWillMount: [], - UNSAFE_componentWillReceiveProps: [], - UNSAFE_componentWillUpdate: [] - }; - - pendingUnsafeLifecycleWarnings.set(strictRoot, warningsForRoot); - } else { - warningsForRoot = pendingUnsafeLifecycleWarnings.get(strictRoot); - } - - var unsafeLifecycles = []; - if ( - typeof instance.componentWillMount === "function" || - typeof instance.UNSAFE_componentWillMount === "function" - ) { - unsafeLifecycles.push("UNSAFE_componentWillMount"); - } - if ( - typeof instance.componentWillReceiveProps === "function" || - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - unsafeLifecycles.push("UNSAFE_componentWillReceiveProps"); - } - if ( - typeof instance.componentWillUpdate === "function" || - typeof instance.UNSAFE_componentWillUpdate === "function" - ) { - unsafeLifecycles.push("UNSAFE_componentWillUpdate"); - } - - if (unsafeLifecycles.length > 0) { - unsafeLifecycles.forEach(function(lifecycle) { - warningsForRoot[lifecycle].push(fiber); - }); - } - }; -} - -var didWarnUpdateInsideUpdate = void 0; - -{ - didWarnUpdateInsideUpdate = false; -} - -// Callbacks are not validated until invocation - -// Singly linked-list of updates. When an update is scheduled, it is added to -// the queue of the current fiber and the work-in-progress fiber. The two queues -// are separate but they share a persistent structure. -// -// During reconciliation, updates are removed from the work-in-progress fiber, -// but they remain on the current fiber. That ensures that if a work-in-progress -// is aborted, the aborted updates are recovered by cloning from current. -// -// The work-in-progress queue is always a subset of the current queue. -// -// When the tree is committed, the work-in-progress becomes the current. - -function createUpdateQueue(baseState) { - var queue = { - baseState: baseState, - expirationTime: NoWork, - first: null, - last: null, - callbackList: null, - hasForceUpdate: false, - isInitialized: false, - capturedValues: null - }; - { - queue.isProcessing = false; - } - return queue; -} - -function insertUpdateIntoQueue(queue, update) { - // Append the update to the end of the list. - if (queue.last === null) { - // Queue is empty - queue.first = queue.last = update; - } else { - queue.last.next = update; - queue.last = update; - } - if ( - queue.expirationTime === NoWork || - queue.expirationTime > update.expirationTime - ) { - queue.expirationTime = update.expirationTime; - } -} - -var q1 = void 0; -var q2 = void 0; -function ensureUpdateQueues(fiber) { - q1 = q2 = null; - // We'll have at least one and at most two distinct update queues. - var alternateFiber = fiber.alternate; - var queue1 = fiber.updateQueue; - if (queue1 === null) { - // TODO: We don't know what the base state will be until we begin work. - // It depends on which fiber is the next current. Initialize with an empty - // base state, then set to the memoizedState when rendering. Not super - // happy with this approach. - queue1 = fiber.updateQueue = createUpdateQueue(null); - } - - var queue2 = void 0; - if (alternateFiber !== null) { - queue2 = alternateFiber.updateQueue; - if (queue2 === null) { - queue2 = alternateFiber.updateQueue = createUpdateQueue(null); + var queue2 = void 0; + if (alternateFiber !== null) { + queue2 = alternateFiber.updateQueue; + if (queue2 === null) { + queue2 = alternateFiber.updateQueue = createUpdateQueue(null); } } else { queue2 = null; @@ -6360,23 +6123,26 @@ var isArray = Array.isArray; var didWarnAboutStateAssignmentForComponent = void 0; var didWarnAboutUndefinedDerivedState = void 0; var didWarnAboutUninitializedState = void 0; -var didWarnAboutWillReceivePropsAndDerivedState = void 0; +var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = void 0; +var didWarnAboutLegacyLifecyclesAndDerivedState = void 0; var warnOnInvalidCallback = void 0; { - didWarnAboutStateAssignmentForComponent = {}; - didWarnAboutUndefinedDerivedState = {}; - didWarnAboutUninitializedState = {}; - didWarnAboutWillReceivePropsAndDerivedState = {}; + didWarnAboutStateAssignmentForComponent = new Set(); + didWarnAboutUndefinedDerivedState = new Set(); + didWarnAboutUninitializedState = new Set(); + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); + didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); - var didWarnOnInvalidCallback = {}; + var didWarnOnInvalidCallback = new Set(); warnOnInvalidCallback = function(callback, callerName) { if (callback === null || typeof callback === "function") { return; } var key = callerName + "_" + callback; - if (!didWarnOnInvalidCallback[key]) { + if (!didWarnOnInvalidCallback.has(key)) { + didWarnOnInvalidCallback.add(key); warning( false, "%s(...): Expected the last optional `callback` argument to be a " + @@ -6384,7 +6150,6 @@ var warnOnInvalidCallback = void 0; callerName, callback ); - didWarnOnInvalidCallback[key] = true; } }; @@ -6423,12 +6188,20 @@ function callGetDerivedStateFromCatch(ctor, capturedValues) { } var ReactFiberClassComponent = function( + legacyContext, scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState ) { + var cacheContext = legacyContext.cacheContext, + getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + isContextConsumer = legacyContext.isContextConsumer, + hasContextChanged = legacyContext.hasContextChanged; + // Class component state updater + var updater = { isMounted: isMounted, enqueueSetState: function(instance, partialState, callback) { @@ -6519,12 +6292,14 @@ var ReactFiberClassComponent = function( stopPhaseTimer(); { - warning( - shouldUpdate !== undefined, - "%s.shouldComponentUpdate(): Returned undefined instead of a " + - "boolean value. Make sure to return true or false.", - getComponentName(workInProgress) || "Unknown" - ); + !(shouldUpdate !== undefined) + ? warning( + false, + "%s.shouldComponentUpdate(): Returned undefined instead of a " + + "boolean value. Make sure to return true or false.", + getComponentName(workInProgress) || "Component" + ) + : void 0; } return shouldUpdate; @@ -6543,7 +6318,7 @@ var ReactFiberClassComponent = function( var instance = workInProgress.stateNode; var type = workInProgress.type; { - var name = getComponentName(workInProgress); + var name = getComponentName(workInProgress) || "Component"; var renderPresent = instance.render; if (!renderPresent) { @@ -6568,47 +6343,57 @@ var ReactFiberClassComponent = function( !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state; - warning( - noGetInitialStateOnES6, - "getInitialState was defined on %s, a plain JavaScript class. " + - "This is only supported for classes created using React.createClass. " + - "Did you mean to define a state property instead?", - name - ); + !noGetInitialStateOnES6 + ? warning( + false, + "getInitialState was defined on %s, a plain JavaScript class. " + + "This is only supported for classes created using React.createClass. " + + "Did you mean to define a state property instead?", + name + ) + : void 0; var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved; - warning( - noGetDefaultPropsOnES6, - "getDefaultProps was defined on %s, a plain JavaScript class. " + - "This is only supported for classes created using React.createClass. " + - "Use a static property to define defaultProps instead.", - name - ); + !noGetDefaultPropsOnES6 + ? warning( + false, + "getDefaultProps was defined on %s, a plain JavaScript class. " + + "This is only supported for classes created using React.createClass. " + + "Use a static property to define defaultProps instead.", + name + ) + : void 0; var noInstancePropTypes = !instance.propTypes; - warning( - noInstancePropTypes, - "propTypes was defined as an instance property on %s. Use a static " + - "property to define propTypes instead.", - name - ); + !noInstancePropTypes + ? warning( + false, + "propTypes was defined as an instance property on %s. Use a static " + + "property to define propTypes instead.", + name + ) + : void 0; var noInstanceContextTypes = !instance.contextTypes; - warning( - noInstanceContextTypes, - "contextTypes was defined as an instance property on %s. Use a static " + - "property to define contextTypes instead.", - name - ); + !noInstanceContextTypes + ? warning( + false, + "contextTypes was defined as an instance property on %s. Use a static " + + "property to define contextTypes instead.", + name + ) + : void 0; var noComponentShouldUpdate = typeof instance.componentShouldUpdate !== "function"; - warning( - noComponentShouldUpdate, - "%s has a method called " + - "componentShouldUpdate(). Did you mean shouldComponentUpdate()? " + - "The name is phrased as a question because the function is " + - "expected to return a value.", - name - ); + !noComponentShouldUpdate + ? warning( + false, + "%s has a method called " + + "componentShouldUpdate(). Did you mean shouldComponentUpdate()? " + + "The name is phrased as a question because the function is " + + "expected to return a value.", + name + ) + : void 0; if ( type.prototype && type.prototype.isPureReactComponent && @@ -6624,73 +6409,128 @@ var ReactFiberClassComponent = function( } var noComponentDidUnmount = typeof instance.componentDidUnmount !== "function"; - warning( - noComponentDidUnmount, - "%s has a method called " + - "componentDidUnmount(). But there is no such lifecycle method. " + - "Did you mean componentWillUnmount()?", - name - ); + !noComponentDidUnmount + ? warning( + false, + "%s has a method called " + + "componentDidUnmount(). But there is no such lifecycle method. " + + "Did you mean componentWillUnmount()?", + name + ) + : void 0; var noComponentDidReceiveProps = typeof instance.componentDidReceiveProps !== "function"; - warning( - noComponentDidReceiveProps, - "%s has a method called " + - "componentDidReceiveProps(). But there is no such lifecycle method. " + - "If you meant to update the state in response to changing props, " + - "use componentWillReceiveProps(). If you meant to fetch data or " + - "run side-effects or mutations after React has updated the UI, use componentDidUpdate().", - name - ); + !noComponentDidReceiveProps + ? warning( + false, + "%s has a method called " + + "componentDidReceiveProps(). But there is no such lifecycle method. " + + "If you meant to update the state in response to changing props, " + + "use componentWillReceiveProps(). If you meant to fetch data or " + + "run side-effects or mutations after React has updated the UI, use componentDidUpdate().", + name + ) + : void 0; var noComponentWillRecieveProps = typeof instance.componentWillRecieveProps !== "function"; - warning( - noComponentWillRecieveProps, - "%s has a method called " + - "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", - name - ); + !noComponentWillRecieveProps + ? warning( + false, + "%s has a method called " + + "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?", + name + ) + : void 0; var noUnsafeComponentWillRecieveProps = typeof instance.UNSAFE_componentWillRecieveProps !== "function"; - warning( - noUnsafeComponentWillRecieveProps, - "%s has a method called " + - "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", - name - ); + !noUnsafeComponentWillRecieveProps + ? warning( + false, + "%s has a method called " + + "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?", + name + ) + : void 0; var hasMutatedProps = instance.props !== workInProgress.pendingProps; - warning( - instance.props === undefined || !hasMutatedProps, - "%s(...): When calling super() in `%s`, make sure to pass " + - "up the same props that your component's constructor was passed.", - name, - name - ); + !(instance.props === undefined || !hasMutatedProps) + ? warning( + false, + "%s(...): When calling super() in `%s`, make sure to pass " + + "up the same props that your component's constructor was passed.", + name, + name + ) + : void 0; var noInstanceDefaultProps = !instance.defaultProps; - warning( - noInstanceDefaultProps, - "Setting defaultProps as an instance property on %s is not supported and will be ignored." + - " Instead, define defaultProps as a static property on %s.", - name, - name - ); - } + !noInstanceDefaultProps + ? warning( + false, + "Setting defaultProps as an instance property on %s is not supported and will be ignored." + + " Instead, define defaultProps as a static property on %s.", + name, + name + ) + : void 0; - var state = instance.state; - if (state && (typeof state !== "object" || isArray(state))) { - warning( - false, - "%s.state: must be set to an object or null", - getComponentName(workInProgress) - ); - } - if (typeof instance.getChildContext === "function") { - warning( - typeof type.childContextTypes === "object", - "%s.getChildContext(): childContextTypes must be defined in order to " + - "use getChildContext().", - getComponentName(workInProgress) - ); + if ( + typeof instance.getSnapshotBeforeUpdate === "function" && + typeof instance.componentDidUpdate !== "function" && + typeof instance.componentDidUpdate !== "function" && + !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(type) + ) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(type); + warning( + false, + "%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). " + + "This component defines getSnapshotBeforeUpdate() only.", + getComponentName(workInProgress) + ); + } + + var noInstanceGetDerivedStateFromProps = + typeof instance.getDerivedStateFromProps !== "function"; + !noInstanceGetDerivedStateFromProps + ? warning( + false, + "%s: getDerivedStateFromProps() is defined as an instance method " + + "and will be ignored. Instead, declare it as a static method.", + name + ) + : void 0; + var noInstanceGetDerivedStateFromCatch = + typeof instance.getDerivedStateFromCatch !== "function"; + !noInstanceGetDerivedStateFromCatch + ? warning( + false, + "%s: getDerivedStateFromCatch() is defined as an instance method " + + "and will be ignored. Instead, declare it as a static method.", + name + ) + : void 0; + var noStaticGetSnapshotBeforeUpdate = + typeof type.getSnapshotBeforeUpdate !== "function"; + !noStaticGetSnapshotBeforeUpdate + ? warning( + false, + "%s: getSnapshotBeforeUpdate() is defined as a static method " + + "and will be ignored. Instead, declare it as an instance method.", + name + ) + : void 0; + var _state = instance.state; + if (_state && (typeof _state !== "object" || isArray(_state))) { + warning(false, "%s.state: must be set to an object or null", name); + } + if (typeof instance.getChildContext === "function") { + !(typeof type.childContextTypes === "object") + ? warning( + false, + "%s.getChildContext(): childContextTypes must be defined in order to " + + "use getChildContext().", + name + ) + : void 0; + } } } @@ -6738,8 +6578,9 @@ var ReactFiberClassComponent = function( typeof ctor.getDerivedStateFromProps === "function" && state === null ) { - var componentName = getComponentName(workInProgress) || "Unknown"; - if (!didWarnAboutUninitializedState[componentName]) { + var componentName = getComponentName(workInProgress) || "Component"; + if (!didWarnAboutUninitializedState.has(componentName)) { + didWarnAboutUninitializedState.add(componentName); warning( false, "%s: Did not properly initialize state during construction. " + @@ -6747,7 +6588,75 @@ var ReactFiberClassComponent = function( componentName, instance.state === null ? "null" : "undefined" ); - didWarnAboutUninitializedState[componentName] = true; + } + } + + // If new component APIs are defined, "unsafe" lifecycles won't be called. + // Warn about these lifecycles if they are present. + // Don't warn about react-lifecycles-compat polyfilled methods though. + if ( + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function" + ) { + var foundWillMountName = null; + var foundWillReceivePropsName = null; + var foundWillUpdateName = null; + if ( + typeof instance.componentWillMount === "function" && + instance.componentWillMount.__suppressDeprecationWarning !== true + ) { + foundWillMountName = "componentWillMount"; + } else if (typeof instance.UNSAFE_componentWillMount === "function") { + foundWillMountName = "UNSAFE_componentWillMount"; + } + if ( + typeof instance.componentWillReceiveProps === "function" && + instance.componentWillReceiveProps.__suppressDeprecationWarning !== + true + ) { + foundWillReceivePropsName = "componentWillReceiveProps"; + } else if ( + typeof instance.UNSAFE_componentWillReceiveProps === "function" + ) { + foundWillReceivePropsName = "UNSAFE_componentWillReceiveProps"; + } + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { + foundWillUpdateName = "componentWillUpdate"; + } else if (typeof instance.UNSAFE_componentWillUpdate === "function") { + foundWillUpdateName = "UNSAFE_componentWillUpdate"; + } + if ( + foundWillMountName !== null || + foundWillReceivePropsName !== null || + foundWillUpdateName !== null + ) { + var _componentName = getComponentName(workInProgress) || "Component"; + var newApiName = + typeof ctor.getDerivedStateFromProps === "function" + ? "getDerivedStateFromProps()" + : "getSnapshotBeforeUpdate()"; + if ( + !didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName) + ) { + didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); + warning( + false, + "Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n" + + "%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n" + + "The above lifecycles should be removed. Learn more about this warning here:\n" + + "https://fb.me/react-async-component-lifecycle-hooks", + _componentName, + newApiName, + foundWillMountName !== null ? "\n " + foundWillMountName : "", + foundWillReceivePropsName !== null + ? "\n " + foundWillReceivePropsName + : "", + foundWillUpdateName !== null ? "\n " + foundWillUpdateName : "" + ); + } } } } @@ -6757,7 +6666,8 @@ var ReactFiberClassComponent = function( var partialState = callGetDerivedStateFromProps( workInProgress, instance, - props + props, + state ); if (partialState !== null && partialState !== undefined) { @@ -6800,7 +6710,7 @@ var ReactFiberClassComponent = function( "%s.componentWillMount(): Assigning directly to this.state is " + "deprecated (except inside a component's " + "constructor). Use setState instead.", - getComponentName(workInProgress) + getComponentName(workInProgress) || "Component" ); } updater.enqueueReplaceState(instance, instance.state, null); @@ -6826,7 +6736,8 @@ var ReactFiberClassComponent = function( if (instance.state !== oldState) { { var componentName = getComponentName(workInProgress) || "Component"; - if (!didWarnAboutStateAssignmentForComponent[componentName]) { + if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { + didWarnAboutStateAssignmentForComponent.add(componentName); warning( false, "%s.componentWillReceiveProps(): Assigning directly to " + @@ -6834,69 +6745,47 @@ var ReactFiberClassComponent = function( "constructor). Use setState instead.", componentName ); - didWarnAboutStateAssignmentForComponent[componentName] = true; } } updater.enqueueReplaceState(instance, instance.state, null); } } - function callGetDerivedStateFromProps(workInProgress, instance, props) { + function callGetDerivedStateFromProps( + workInProgress, + instance, + nextProps, + prevState + ) { var type = workInProgress.type; if (typeof type.getDerivedStateFromProps === "function") { - { - // Don't warn about react-lifecycles-compat polyfilled components - if ( - (typeof instance.componentWillReceiveProps === "function" && - instance.componentWillReceiveProps.__suppressDeprecationWarning !== - true) || - typeof instance.UNSAFE_componentWillReceiveProps === "function" - ) { - var componentName = getComponentName(workInProgress) || "Unknown"; - if (!didWarnAboutWillReceivePropsAndDerivedState[componentName]) { - warning( - false, - "%s: Defines both componentWillReceiveProps() and static " + - "getDerivedStateFromProps() methods. We recommend using " + - "only getDerivedStateFromProps().", - componentName - ); - didWarnAboutWillReceivePropsAndDerivedState[componentName] = true; - } - } - } - if ( debugRenderPhaseSideEffects || (debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictMode) ) { // Invoke method an extra time to help detect side-effects. - type.getDerivedStateFromProps.call( - null, - props, - workInProgress.memoizedState - ); + type.getDerivedStateFromProps.call(null, nextProps, prevState); } var partialState = type.getDerivedStateFromProps.call( null, - props, - workInProgress.memoizedState + nextProps, + prevState ); { if (partialState === undefined) { - var _componentName = getComponentName(workInProgress) || "Unknown"; - if (!didWarnAboutUndefinedDerivedState[_componentName]) { + var componentName = getComponentName(workInProgress) || "Component"; + if (!didWarnAboutUndefinedDerivedState.has(componentName)) { + didWarnAboutUndefinedDerivedState.add(componentName); warning( false, "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " + "You have returned undefined.", - _componentName + componentName ); - didWarnAboutUndefinedDerivedState[_componentName] = _componentName; } } } @@ -6940,11 +6829,12 @@ var ReactFiberClassComponent = function( } // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( + typeof ctor.getDerivedStateFromProps !== "function" && + typeof instance.getSnapshotBeforeUpdate !== "function" && (typeof instance.UNSAFE_componentWillMount === "function" || - typeof instance.componentWillMount === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + typeof instance.componentWillMount === "function") ) { callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's @@ -6977,16 +6867,20 @@ var ReactFiberClassComponent = function( var newUnmaskedContext = getUnmaskedContext(workInProgress); var newContext = getMaskedContext(workInProgress, newUnmaskedContext); + var hasNewLifecycles = + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function"; + // Note: During these life-cycles, instance.props/instance.state are what // ever the previously attempted to render - not the "current". However, // during componentDidUpdate we pass the "current" props. // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( + !hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + typeof instance.componentWillReceiveProps === "function") ) { if (oldProps !== newProps || oldContext !== newContext) { callComponentWillReceiveProps( @@ -6998,15 +6892,6 @@ var ReactFiberClassComponent = function( } } - var derivedStateFromProps = void 0; - if (oldProps !== newProps) { - derivedStateFromProps = callGetDerivedStateFromProps( - workInProgress, - instance, - newProps - ); - } - // Compute the next state using the memoized state and the update queue. var oldState = workInProgress.memoizedState; // TODO: Previous state can be null. @@ -7043,6 +6928,18 @@ var ReactFiberClassComponent = function( newState = oldState; } + var derivedStateFromProps = void 0; + if (oldProps !== newProps) { + // The prevState parameter should be the partially updated state. + // Otherwise, spreading state in return values could override updates. + derivedStateFromProps = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + newState + ); + } + if (derivedStateFromProps !== null && derivedStateFromProps !== undefined) { // Render-phase updates (like this) should not be added to the update queue, // So that multiple render passes do not enqueue multiple updates. @@ -7051,6 +6948,17 @@ var ReactFiberClassComponent = function( newState === null || newState === undefined ? derivedStateFromProps : Object.assign({}, newState, derivedStateFromProps); + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue = workInProgress.updateQueue; + if (_updateQueue !== null) { + _updateQueue.baseState = Object.assign( + {}, + _updateQueue.baseState, + derivedStateFromProps + ); + } } if (derivedStateFromCatch !== null && derivedStateFromCatch !== undefined) { // Render-phase updates (like this) should not be added to the update queue, @@ -7060,6 +6968,17 @@ var ReactFiberClassComponent = function( newState === null || newState === undefined ? derivedStateFromCatch : Object.assign({}, newState, derivedStateFromCatch); + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue2 = workInProgress.updateQueue; + if (_updateQueue2 !== null) { + _updateQueue2.baseState = Object.assign( + {}, + _updateQueue2.baseState, + derivedStateFromCatch + ); + } } if ( @@ -7090,22 +7009,22 @@ var ReactFiberClassComponent = function( if (shouldUpdate) { // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( - (typeof instance.UNSAFE_componentWillUpdate === "function" || - typeof instance.componentWillUpdate === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillMount === "function" || + typeof instance.componentWillMount === "function") ) { - startPhaseTimer(workInProgress, "componentWillUpdate"); - if (typeof instance.componentWillUpdate === "function") { - instance.componentWillUpdate(newProps, newState, newContext); + startPhaseTimer(workInProgress, "componentWillMount"); + if (typeof instance.componentWillMount === "function") { + instance.componentWillMount(); } - if (typeof instance.UNSAFE_componentWillUpdate === "function") { - instance.UNSAFE_componentWillUpdate(newProps, newState, newContext); + if (typeof instance.UNSAFE_componentWillMount === "function") { + instance.UNSAFE_componentWillMount(); } stopPhaseTimer(); } - if (typeof instance.componentDidUpdate === "function") { + if (typeof instance.componentDidMount === "function") { workInProgress.effectTag |= Update; } } else { @@ -7142,16 +7061,20 @@ var ReactFiberClassComponent = function( var newUnmaskedContext = getUnmaskedContext(workInProgress); var newContext = getMaskedContext(workInProgress, newUnmaskedContext); + var hasNewLifecycles = + typeof ctor.getDerivedStateFromProps === "function" || + typeof instance.getSnapshotBeforeUpdate === "function"; + // Note: During these life-cycles, instance.props/instance.state are what // ever the previously attempted to render - not the "current". However, // during componentDidUpdate we pass the "current" props. // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( + !hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === "function" || - typeof instance.componentWillReceiveProps === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + typeof instance.componentWillReceiveProps === "function") ) { if (oldProps !== newProps || oldContext !== newContext) { callComponentWillReceiveProps( @@ -7163,20 +7086,12 @@ var ReactFiberClassComponent = function( } } - var derivedStateFromProps = void 0; - if (oldProps !== newProps) { - derivedStateFromProps = callGetDerivedStateFromProps( - workInProgress, - instance, - newProps - ); - } - // Compute the next state using the memoized state and the update queue. var oldState = workInProgress.memoizedState; // TODO: Previous state can be null. var newState = void 0; var derivedStateFromCatch = void 0; + if (workInProgress.updateQueue !== null) { newState = processUpdateQueue( current, @@ -7208,6 +7123,18 @@ var ReactFiberClassComponent = function( newState = oldState; } + var derivedStateFromProps = void 0; + if (oldProps !== newProps) { + // The prevState parameter should be the partially updated state. + // Otherwise, spreading state in return values could override updates. + derivedStateFromProps = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + newState + ); + } + if (derivedStateFromProps !== null && derivedStateFromProps !== undefined) { // Render-phase updates (like this) should not be added to the update queue, // So that multiple render passes do not enqueue multiple updates. @@ -7216,6 +7143,17 @@ var ReactFiberClassComponent = function( newState === null || newState === undefined ? derivedStateFromProps : Object.assign({}, newState, derivedStateFromProps); + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue3 = workInProgress.updateQueue; + if (_updateQueue3 !== null) { + _updateQueue3.baseState = Object.assign( + {}, + _updateQueue3.baseState, + derivedStateFromProps + ); + } } if (derivedStateFromCatch !== null && derivedStateFromCatch !== undefined) { // Render-phase updates (like this) should not be added to the update queue, @@ -7225,6 +7163,17 @@ var ReactFiberClassComponent = function( newState === null || newState === undefined ? derivedStateFromCatch : Object.assign({}, newState, derivedStateFromCatch); + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue4 = workInProgress.updateQueue; + if (_updateQueue4 !== null) { + _updateQueue4.baseState = Object.assign( + {}, + _updateQueue4.baseState, + derivedStateFromCatch + ); + } } if ( @@ -7246,6 +7195,14 @@ var ReactFiberClassComponent = function( workInProgress.effectTag |= Update; } } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Snapshot; + } + } return false; } @@ -7260,11 +7217,11 @@ var ReactFiberClassComponent = function( if (shouldUpdate) { // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( + !hasNewLifecycles && (typeof instance.UNSAFE_componentWillUpdate === "function" || - typeof instance.componentWillUpdate === "function") && - typeof ctor.getDerivedStateFromProps !== "function" + typeof instance.componentWillUpdate === "function") ) { startPhaseTimer(workInProgress, "componentWillUpdate"); if (typeof instance.componentWillUpdate === "function") { @@ -7278,6 +7235,9 @@ var ReactFiberClassComponent = function( if (typeof instance.componentDidUpdate === "function") { workInProgress.effectTag |= Update; } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + workInProgress.effectTag |= Snapshot; + } } else { // If an update was already in progress, we should schedule an Update // effect even though we're bailing out, so that cWU/cDU are called. @@ -7289,6 +7249,14 @@ var ReactFiberClassComponent = function( workInProgress.effectTag |= Update; } } + if (typeof instance.getSnapshotBeforeUpdate === "function") { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Snapshot; + } + } // If shouldComponentUpdate returned false, we should still update the // memoized props/state to indicate that this work can be reused. @@ -8128,13 +8096,15 @@ function ChildReconciler(shouldTrackSideEffects) { if (typeof newChildrenIterable.entries === "function") { var possibleMap = newChildrenIterable; if (possibleMap.entries === iteratorFn) { - warning( - didWarnAboutMaps, - "Using Maps as children is unsupported and will likely yield " + - "unexpected results. Convert it to a sequence/iterable of keyed " + - "ReactElements instead.%s", - getCurrentFiberStackAddendum$1() - ); + !didWarnAboutMaps + ? warning( + false, + "Using Maps as children is unsupported and will likely yield " + + "unexpected results. Convert it to a sequence/iterable of keyed " + + "ReactElements instead.%s", + getCurrentFiberStackAddendum$1() + ) + : void 0; didWarnAboutMaps = true; } } @@ -8576,71 +8546,6 @@ function cloneChildFibers(current, workInProgress) { newChild.sibling = null; } -var changedBitsStack = []; -var currentValueStack = []; -var stack = []; -var index$1 = -1; - -var rendererSigil = void 0; -{ - // Use this to detect multiple renderers using the same context - rendererSigil = {}; -} - -function pushProvider(providerFiber) { - var context = providerFiber.type.context; - index$1 += 1; - changedBitsStack[index$1] = context._changedBits; - currentValueStack[index$1] = context._currentValue; - stack[index$1] = providerFiber; - context._currentValue = providerFiber.pendingProps.value; - context._changedBits = providerFiber.stateNode; - - { - warning( - context._currentRenderer === null || - context._currentRenderer === rendererSigil, - "Detected multiple renderers concurrently rendering the " + - "same context provider. This is currently unsupported." - ); - context._currentRenderer = rendererSigil; - } -} - -function popProvider(providerFiber) { - { - warning( - index$1 > -1 && providerFiber === stack[index$1], - "Unexpected pop." - ); - } - var changedBits = changedBitsStack[index$1]; - var currentValue = currentValueStack[index$1]; - changedBitsStack[index$1] = null; - currentValueStack[index$1] = null; - stack[index$1] = null; - index$1 -= 1; - var context = providerFiber.type.context; - context._currentValue = currentValue; - context._changedBits = changedBits; -} - -function resetProviderStack() { - for (var i = index$1; i > -1; i--) { - var providerFiber = stack[i]; - var context = providerFiber.type.context; - context._currentValue = context._defaultValue; - context._changedBits = 0; - changedBitsStack[i] = null; - currentValueStack[i] = null; - stack[i] = null; - { - context._currentRenderer = null; - } - } - index$1 = -1; -} - var didWarnAboutBadClass = void 0; var didWarnAboutGetDerivedStateOnFunctionalComponent = void 0; var didWarnAboutStatelessRefs = void 0; @@ -8654,6 +8559,8 @@ var didWarnAboutStatelessRefs = void 0; var ReactFiberBeginWork = function( config, hostContext, + legacyContext, + newContext, hydrationContext, scheduleWork, computeExpirationForFiber @@ -8662,12 +8569,20 @@ var ReactFiberBeginWork = function( shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree; var pushHostContext = hostContext.pushHostContext, pushHostContainer = hostContext.pushHostContainer; + var pushProvider = newContext.pushProvider; + var getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + hasLegacyContextChanged = legacyContext.hasContextChanged, + pushLegacyContextProvider = legacyContext.pushContextProvider, + pushTopLevelContextObject = legacyContext.pushTopLevelContextObject, + invalidateContextProvider = legacyContext.invalidateContextProvider; var enterHydrationState = hydrationContext.enterHydrationState, resetHydrationState = hydrationContext.resetHydrationState, tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance; var _ReactFiberClassCompo = ReactFiberClassComponent( + legacyContext, scheduleWork, computeExpirationForFiber, memoizeProps, @@ -8725,9 +8640,17 @@ var ReactFiberBeginWork = function( } } + function updateForwardRef(current, workInProgress) { + var render = workInProgress.type.render; + var nextChildren = render(workInProgress.pendingProps, workInProgress.ref); + reconcileChildren(current, workInProgress, nextChildren); + memoizeProps(workInProgress, nextChildren); + return workInProgress.child; + } + function updateFragment(current, workInProgress) { var nextChildren = workInProgress.pendingProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (workInProgress.memoizedProps === nextChildren) { @@ -8740,7 +8663,7 @@ var ReactFiberBeginWork = function( function updateMode(current, workInProgress) { var nextChildren = workInProgress.pendingProps.children; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if ( @@ -8769,7 +8692,7 @@ var ReactFiberBeginWork = function( var fn = workInProgress.type; var nextProps = workInProgress.pendingProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else { @@ -8802,7 +8725,7 @@ var ReactFiberBeginWork = function( // Push context providers early to prevent context stack mismatches. // During mounting we don't know the child context yet as the instance doesn't exist. // We will invalidate the child context in finishClassComponent() right after rendering. - var hasContext = pushContextProvider(workInProgress); + var hasContext = pushLegacyContextProvider(workInProgress); var shouldUpdate = void 0; if (current === null) { if (workInProgress.stateNode === null) { @@ -9027,7 +8950,7 @@ var ReactFiberBeginWork = function( var nextProps = workInProgress.pendingProps; var prevProps = current !== null ? current.memoizedProps : null; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (memoizedProps === nextProps) { @@ -9147,7 +9070,8 @@ var ReactFiberBeginWork = function( var partialState = callGetDerivedStateFromProps( workInProgress, value, - props + props, + workInProgress.memoizedState ); if (partialState !== null && partialState !== undefined) { @@ -9162,7 +9086,7 @@ var ReactFiberBeginWork = function( // Push context providers early to prevent context stack mismatches. // During mounting we don't know the child context yet as the instance doesn't exist. // We will invalidate the child context in finishClassComponent() right after rendering. - var hasContext = pushContextProvider(workInProgress); + var hasContext = pushLegacyContextProvider(workInProgress); adoptClassInstance(workInProgress, value); mountClassInstance(workInProgress, renderExpirationTime); return finishClassComponent( @@ -9180,11 +9104,13 @@ var ReactFiberBeginWork = function( var _Component = workInProgress.type; if (_Component) { - warning( - !_Component.childContextTypes, - "%s(...): childContextTypes cannot be defined on a functional component.", - _Component.displayName || _Component.name || "Component" - ); + !!_Component.childContextTypes + ? warning( + false, + "%s(...): childContextTypes cannot be defined on a functional component.", + _Component.displayName || _Component.name || "Component" + ) + : void 0; } if (workInProgress.ref !== null) { var info = ""; @@ -9235,7 +9161,7 @@ var ReactFiberBeginWork = function( function updateCallComponent(current, workInProgress, renderExpirationTime) { var nextProps = workInProgress.pendingProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (workInProgress.memoizedProps === nextProps) { @@ -9278,7 +9204,7 @@ var ReactFiberBeginWork = function( ) { pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); var nextChildren = workInProgress.pendingProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (workInProgress.memoizedProps === nextChildren) { @@ -9312,6 +9238,10 @@ var ReactFiberBeginWork = function( renderExpirationTime ) { var fiber = workInProgress.child; + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber["return"] = workInProgress; + } while (fiber !== null) { var nextFiber = void 0; // Visit this fiber. @@ -9399,12 +9329,12 @@ var ReactFiberBeginWork = function( renderExpirationTime ) { var providerType = workInProgress.type; - var context = providerType.context; + var context = providerType._context; var newProps = workInProgress.pendingProps; var oldProps = workInProgress.memoizedProps; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (oldProps === newProps) { @@ -9452,12 +9382,14 @@ var ReactFiberBeginWork = function( ? context._calculateChangedBits(oldValue, newValue) : MAX_SIGNED_31_BIT_INT; { - warning( - (changedBits & MAX_SIGNED_31_BIT_INT) === changedBits, - "calculateChangedBits: Expected the return value to be a " + - "31-bit integer. Instead received: %s", - changedBits - ); + !((changedBits & MAX_SIGNED_31_BIT_INT) === changedBits) + ? warning( + false, + "calculateChangedBits: Expected the return value to be a " + + "31-bit integer. Instead received: %s", + changedBits + ) + : void 0; } changedBits |= 0; @@ -9500,7 +9432,7 @@ var ReactFiberBeginWork = function( var newValue = context._currentValue; var changedBits = context._changedBits; - if (hasContextChanged()) { + if (hasLegacyContextChanged()) { // Normally we can bail out on props equality but if context has changed // we don't do the bailout and we have to reuse existing props instead. } else if (changedBits === 0 && oldProps === newProps) { @@ -9525,21 +9457,23 @@ var ReactFiberBeginWork = function( changedBits, renderExpirationTime ); - } else if (oldProps !== null && oldProps.children === newProps.children) { - // No change. Bailout early if children are the same. - return bailoutOnAlreadyFinishedWork(current, workInProgress); } + // There is no bailout on `children` equality because we expect people + // to often pass a bound method as a child, but it may reference + // `this.state` or `this.props` (and thus needs to re-render on `setState`). var render = newProps.children; { - warning( - typeof render === "function", - "A context consumer was rendered with multiple children, or a child " + - "that isn't a function. A context consumer expects a single child " + - "that is a function. If you did pass a function, make sure there " + - "is no trailing or leading whitespace around it." - ); + !(typeof render === "function") + ? warning( + false, + "A context consumer was rendered with multiple children, or a child " + + "that isn't a function. A context consumer expects a single child " + + "that is a function. If you did pass a function, make sure there " + + "is no trailing or leading whitespace around it." + ) + : void 0; } var newChildren = render(newValue); @@ -9597,7 +9531,7 @@ var ReactFiberBeginWork = function( pushHostRootContext(workInProgress); break; case ClassComponent: - pushContextProvider(workInProgress); + pushLegacyContextProvider(workInProgress); break; case HostPortal: pushHostContainer( @@ -9678,6 +9612,8 @@ var ReactFiberBeginWork = function( workInProgress, renderExpirationTime ); + case ForwardRef: + return updateForwardRef(current, workInProgress); case Fragment: return updateFragment(current, workInProgress); case Mode: @@ -9708,7 +9644,13 @@ var ReactFiberBeginWork = function( }; }; -var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { +var ReactFiberCompleteWork = function( + config, + hostContext, + legacyContext, + newContext, + hydrationContext +) { var createInstance = config.createInstance, createTextInstance = config.createTextInstance, appendInitialChild = config.appendInitialChild, @@ -9720,6 +9662,9 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { popHostContext = hostContext.popHostContext, getHostContext = hostContext.getHostContext, popHostContainer = hostContext.popHostContainer; + var popLegacyContextProvider = legacyContext.popContextProvider, + popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject; + var popProvider = newContext.popProvider; var prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance, prepareToHydrateHostTextInstance = @@ -10035,7 +9980,7 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { return null; case ClassComponent: { // We are leaving this subtree, so pop context if any. - popContextProvider(workInProgress); + popLegacyContextProvider(workInProgress); // If this component caught an error, schedule an error log effect. var instance = workInProgress.stateNode; @@ -10054,7 +9999,7 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { } case HostRoot: { popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); + popTopLevelLegacyContextObject(workInProgress); var fiberRoot = workInProgress.stateNode; if (fiberRoot.pendingContext) { fiberRoot.context = fiberRoot.pendingContext; @@ -10230,6 +10175,8 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { case ReturnComponent: // Does nothing. return null; + case ForwardRef: + return null; case Fragment: return null; case Mode: @@ -10279,11 +10226,16 @@ function createCapturedValue(value, source) { var ReactFiberUnwindWork = function( hostContext, + legacyContext, + newContext, scheduleWork, isAlreadyFailedLegacyErrorBoundary ) { var popHostContainer = hostContext.popHostContainer, popHostContext = hostContext.popHostContext; + var popLegacyContextProvider = legacyContext.popContextProvider, + popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject; + var popProvider = newContext.popProvider; function throwException(returnFiber, sourceFiber, rawValue) { // The source fiber did not complete. @@ -10339,7 +10291,7 @@ var ReactFiberUnwindWork = function( function unwindWork(workInProgress) { switch (workInProgress.tag) { case ClassComponent: { - popContextProvider(workInProgress); + popLegacyContextProvider(workInProgress); var effectTag = workInProgress.effectTag; if (effectTag & ShouldCapture) { workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture; @@ -10349,7 +10301,7 @@ var ReactFiberUnwindWork = function( } case HostRoot: { popHostContainer(workInProgress); - popTopLevelContextObject(workInProgress); + popTopLevelLegacyContextObject(workInProgress); var _effectTag = workInProgress.effectTag; if (_effectTag & ShouldCapture) { workInProgress.effectTag = (_effectTag & ~ShouldCapture) | DidCapture; @@ -10371,9 +10323,37 @@ var ReactFiberUnwindWork = function( return null; } } + + function unwindInterruptedWork(interruptedWork) { + switch (interruptedWork.tag) { + case ClassComponent: { + popLegacyContextProvider(interruptedWork); + break; + } + case HostRoot: { + popHostContainer(interruptedWork); + popTopLevelLegacyContextObject(interruptedWork); + break; + } + case HostComponent: { + popHostContext(interruptedWork); + break; + } + case HostPortal: + popHostContainer(interruptedWork); + break; + case ContextProvider: + popProvider(interruptedWork); + break; + default: + break; + } + } + return { throwException: throwException, - unwindWork: unwindWork + unwindWork: unwindWork, + unwindInterruptedWork: unwindInterruptedWork }; }; @@ -10482,6 +10462,11 @@ var invokeGuardedCallback$3 = ReactErrorUtils.invokeGuardedCallback; var hasCaughtError$1 = ReactErrorUtils.hasCaughtError; var clearCaughtError$1 = ReactErrorUtils.clearCaughtError; +var didWarnAboutUndefinedSnapshotBeforeUpdate = null; +{ + didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); +} + function logError(boundary, errorInfo) { var source = errorInfo.source; var stack = errorInfo.stack; @@ -10491,21 +10476,19 @@ function logError(boundary, errorInfo) { var capturedError = { componentName: source !== null ? getComponentName(source) : null, - error: errorInfo.value, - errorBoundary: boundary, componentStack: stack !== null ? stack : "", + error: errorInfo.value, + errorBoundary: null, errorBoundaryName: null, errorBoundaryFound: false, willRetry: false }; - if (boundary !== null) { + if (boundary !== null && boundary.tag === ClassComponent) { + capturedError.errorBoundary = boundary.stateNode; capturedError.errorBoundaryName = getComponentName(boundary); - capturedError.errorBoundaryFound = capturedError.willRetry = - boundary.tag === ClassComponent; - } else { - capturedError.errorBoundaryName = null; - capturedError.errorBoundaryFound = capturedError.willRetry = false; + capturedError.errorBoundaryFound = true; + capturedError.willRetry = true; } try { @@ -10569,64 +10552,120 @@ var ReactFiberCommitWork = function( } } } else { - ref.value = null; + ref.current = null; } } } - function commitLifeCycles( - finishedRoot, - current, - finishedWork, - currentTime, - committedExpirationTime - ) { + function commitBeforeMutationLifeCycles(current, finishedWork) { switch (finishedWork.tag) { case ClassComponent: { - var _instance = finishedWork.stateNode; - if (finishedWork.effectTag & Update) { - if (current === null) { - startPhaseTimer(finishedWork, "componentDidMount"); - _instance.props = finishedWork.memoizedProps; - _instance.state = finishedWork.memoizedState; - _instance.componentDidMount(); - stopPhaseTimer(); - } else { + if (finishedWork.effectTag & Snapshot) { + if (current !== null) { var prevProps = current.memoizedProps; var prevState = current.memoizedState; - startPhaseTimer(finishedWork, "componentDidUpdate"); + startPhaseTimer(finishedWork, "getSnapshotBeforeUpdate"); + var _instance = finishedWork.stateNode; _instance.props = finishedWork.memoizedProps; _instance.state = finishedWork.memoizedState; - _instance.componentDidUpdate(prevProps, prevState); + var snapshot = _instance.getSnapshotBeforeUpdate( + prevProps, + prevState + ); + { + var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; + if ( + snapshot === undefined && + !didWarnSet.has(finishedWork.type) + ) { + didWarnSet.add(finishedWork.type); + warning( + false, + "%s.getSnapshotBeforeUpdate(): A snapshot value (or null) " + + "must be returned. You have returned undefined.", + getComponentName(finishedWork) + ); + } + } + _instance.__reactInternalSnapshotBeforeUpdate = snapshot; stopPhaseTimer(); } } - var updateQueue = finishedWork.updateQueue; - if (updateQueue !== null) { - commitCallbacks(updateQueue, _instance); - } return; } - case HostRoot: { - var _updateQueue = finishedWork.updateQueue; - if (_updateQueue !== null) { - var _instance2 = null; - if (finishedWork.child !== null) { + case HostRoot: + case HostComponent: + case HostText: + case HostPortal: + // Nothing to do for these component types + return; + default: { + invariant( + false, + "This unit of work tag should not have side-effects. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } + } + + function commitLifeCycles( + finishedRoot, + current, + finishedWork, + currentTime, + committedExpirationTime + ) { + switch (finishedWork.tag) { + case ClassComponent: { + var _instance2 = finishedWork.stateNode; + if (finishedWork.effectTag & Update) { + if (current === null) { + startPhaseTimer(finishedWork, "componentDidMount"); + _instance2.props = finishedWork.memoizedProps; + _instance2.state = finishedWork.memoizedState; + _instance2.componentDidMount(); + stopPhaseTimer(); + } else { + var prevProps = current.memoizedProps; + var prevState = current.memoizedState; + startPhaseTimer(finishedWork, "componentDidUpdate"); + _instance2.props = finishedWork.memoizedProps; + _instance2.state = finishedWork.memoizedState; + _instance2.componentDidUpdate( + prevProps, + prevState, + _instance2.__reactInternalSnapshotBeforeUpdate + ); + stopPhaseTimer(); + } + } + var updateQueue = finishedWork.updateQueue; + if (updateQueue !== null) { + commitCallbacks(updateQueue, _instance2); + } + return; + } + case HostRoot: { + var _updateQueue = finishedWork.updateQueue; + if (_updateQueue !== null) { + var _instance3 = null; + if (finishedWork.child !== null) { switch (finishedWork.child.tag) { case HostComponent: - _instance2 = getPublicInstance(finishedWork.child.stateNode); + _instance3 = getPublicInstance(finishedWork.child.stateNode); break; case ClassComponent: - _instance2 = finishedWork.child.stateNode; + _instance3 = finishedWork.child.stateNode; break; } } - commitCallbacks(_updateQueue, _instance2); + commitCallbacks(_updateQueue, _instance3); } return; } case HostComponent: { - var _instance3 = finishedWork.stateNode; + var _instance4 = finishedWork.stateNode; // Renderers may schedule work to be done after host components are mounted // (eg DOM renderer may schedule auto-focus for inputs and form controls). @@ -10635,7 +10674,7 @@ var ReactFiberCommitWork = function( if (current === null && finishedWork.effectTag & Update) { var type = finishedWork.type; var props = finishedWork.memoizedProps; - commitMount(_instance3, type, props, finishedWork); + commitMount(_instance4, type, props, finishedWork); } return; @@ -10663,7 +10702,7 @@ var ReactFiberCommitWork = function( case ClassComponent: { var ctor = finishedWork.type; - var _instance4 = finishedWork.stateNode; + var _instance5 = finishedWork.stateNode; var updateQueue = finishedWork.updateQueue; invariant( updateQueue !== null && updateQueue.capturedValues !== null, @@ -10680,16 +10719,19 @@ var ReactFiberCommitWork = function( // This gets reset before we yield back to the browser. // TODO: Warn in strict mode if getDerivedStateFromCatch is // not defined. - markLegacyErrorBoundaryAsFailed(_instance4); + markLegacyErrorBoundaryAsFailed(_instance5); } - _instance4.props = finishedWork.memoizedProps; - _instance4.state = finishedWork.memoizedState; + _instance5.props = finishedWork.memoizedProps; + _instance5.state = finishedWork.memoizedState; for (var i = 0; i < capturedErrors.length; i++) { var errorInfo = capturedErrors[i]; var _error = errorInfo.value; + var stack = errorInfo.stack; logError(finishedWork, errorInfo); - _instance4.componentDidCatch(_error); + _instance5.componentDidCatch(_error, { + componentStack: stack !== null ? stack : "" + }); } } break; @@ -10722,19 +10764,31 @@ var ReactFiberCommitWork = function( function commitAttachRef(finishedWork) { var ref = finishedWork.ref; if (ref !== null) { - var _instance5 = finishedWork.stateNode; + var _instance6 = finishedWork.stateNode; var instanceToUse = void 0; switch (finishedWork.tag) { case HostComponent: - instanceToUse = getPublicInstance(_instance5); + instanceToUse = getPublicInstance(_instance6); break; default: - instanceToUse = _instance5; + instanceToUse = _instance6; } if (typeof ref === "function") { ref(instanceToUse); } else { - ref.value = instanceToUse; + { + if (!ref.hasOwnProperty("current")) { + warning( + false, + "Unexpected ref object provided for %s. " + + "Use either a ref-setter function or React.createRef().%s", + getComponentName(finishedWork), + getStackAddendumByWorkInProgressFiber(finishedWork) + ); + } + } + + ref.current = instanceToUse; } } } @@ -10745,7 +10799,7 @@ var ReactFiberCommitWork = function( if (typeof currentRef === "function") { currentRef(null); } else { - currentRef.value = null; + currentRef.current = null; } } } @@ -10761,9 +10815,9 @@ var ReactFiberCommitWork = function( switch (current.tag) { case ClassComponent: { safelyDetachRef(current); - var _instance6 = current.stateNode; - if (typeof _instance6.componentWillUnmount === "function") { - safelyCallComponentWillUnmount(current, _instance6); + var _instance7 = current.stateNode; + if (typeof _instance7.componentWillUnmount === "function") { + safelyCallComponentWillUnmount(current, _instance7); } return; } @@ -10900,6 +10954,7 @@ var ReactFiberCommitWork = function( }, commitLifeCycles: commitLifeCycles, + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, commitErrorLogging: commitErrorLogging, commitAttachRef: commitAttachRef, commitDetachRef: commitDetachRef @@ -11059,635 +11114,1063 @@ var ReactFiberCommitWork = function( } } - function unmountHostComponents(current) { - // We only have the top Fiber that was inserted but we need recurse down its - var node = current; + function unmountHostComponents(current) { + // We only have the top Fiber that was inserted but we need recurse down its + var node = current; + + // Each iteration, currentParent is populated with node's host parent if not + // currentParentIsValid. + var currentParentIsValid = false; + var currentParent = void 0; + var currentParentIsContainer = void 0; + + while (true) { + if (!currentParentIsValid) { + var parent = node["return"]; + findParent: while (true) { + invariant( + parent !== null, + "Expected to find a host parent. This error is likely caused by " + + "a bug in React. Please file an issue." + ); + switch (parent.tag) { + case HostComponent: + currentParent = parent.stateNode; + currentParentIsContainer = false; + break findParent; + case HostRoot: + currentParent = parent.stateNode.containerInfo; + currentParentIsContainer = true; + break findParent; + case HostPortal: + currentParent = parent.stateNode.containerInfo; + currentParentIsContainer = true; + break findParent; + } + parent = parent["return"]; + } + currentParentIsValid = true; + } + + if (node.tag === HostComponent || node.tag === HostText) { + commitNestedUnmounts(node); + // After all the children have unmounted, it is now safe to remove the + // node from the tree. + if (currentParentIsContainer) { + removeChildFromContainer(currentParent, node.stateNode); + } else { + removeChild(currentParent, node.stateNode); + } + // Don't visit children because we already visited them. + } else if (node.tag === HostPortal) { + // When we go into a portal, it becomes the parent to remove from. + // We will reassign it back when we pop the portal on the way up. + currentParent = node.stateNode.containerInfo; + // Visit children because portals might contain host components. + if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + } else { + commitUnmount(node); + // Visit children because we may find more host components below. + if (node.child !== null) { + node.child["return"] = node; + node = node.child; + continue; + } + } + if (node === current) { + return; + } + while (node.sibling === null) { + if (node["return"] === null || node["return"] === current) { + return; + } + node = node["return"]; + if (node.tag === HostPortal) { + // When we go out of the portal, we need to restore the parent. + // Since we don't keep a stack of them, we will search for it. + currentParentIsValid = false; + } + } + node.sibling["return"] = node["return"]; + node = node.sibling; + } + } + + function commitDeletion(current) { + // Recursively delete all host nodes from the parent. + // Detach refs and call componentWillUnmount() on the whole subtree. + unmountHostComponents(current); + detachFiber(current); + } + + function commitWork(current, finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: { + return; + } + case HostComponent: { + var _instance8 = finishedWork.stateNode; + if (_instance8 != null) { + // Commit the work prepared earlier. + var newProps = finishedWork.memoizedProps; + // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + var oldProps = current !== null ? current.memoizedProps : newProps; + var type = finishedWork.type; + // TODO: Type the updateQueue to be specific to host components. + var updatePayload = finishedWork.updateQueue; + finishedWork.updateQueue = null; + if (updatePayload !== null) { + commitUpdate( + _instance8, + updatePayload, + type, + oldProps, + newProps, + finishedWork + ); + } + } + return; + } + case HostText: { + invariant( + finishedWork.stateNode !== null, + "This should have a text node initialized. This error is likely " + + "caused by a bug in React. Please file an issue." + ); + var textInstance = finishedWork.stateNode; + var newText = finishedWork.memoizedProps; + // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + var oldText = current !== null ? current.memoizedProps : newText; + commitTextUpdate(textInstance, oldText, newText); + return; + } + case HostRoot: { + return; + } + default: { + invariant( + false, + "This unit of work tag should not have side-effects. This error is " + + "likely caused by a bug in React. Please file an issue." + ); + } + } + } + + function commitResetTextContent(current) { + resetTextContent(current.stateNode); + } + + if (enableMutatingReconciler) { + return { + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, + commitResetTextContent: commitResetTextContent, + commitPlacement: commitPlacement, + commitDeletion: commitDeletion, + commitWork: commitWork, + commitLifeCycles: commitLifeCycles, + commitErrorLogging: commitErrorLogging, + commitAttachRef: commitAttachRef, + commitDetachRef: commitDetachRef + }; + } else { + invariant(false, "Mutating reconciler is disabled."); + } +}; + +var NO_CONTEXT = {}; + +var ReactFiberHostContext = function(config, stack) { + var getChildHostContext = config.getChildHostContext, + getRootHostContext = config.getRootHostContext; + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop; + + var contextStackCursor = createCursor(NO_CONTEXT); + var contextFiberStackCursor = createCursor(NO_CONTEXT); + var rootInstanceStackCursor = createCursor(NO_CONTEXT); + + function requiredContext(c) { + invariant( + c !== NO_CONTEXT, + "Expected host context to exist. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + return c; + } + + function getRootHostContainer() { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + return rootInstance; + } + + function pushHostContainer(fiber, nextRootInstance) { + // Push current root instance onto the stack; + // This allows us to reset root when portals are popped. + push(rootInstanceStackCursor, nextRootInstance, fiber); + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + + // Finally, we need to push the host context to the stack. + // However, we can't just call getRootHostContext() and push it because + // we'd have a different number of entries on the stack depending on + // whether getRootHostContext() throws somewhere in renderer code or not. + // So we push an empty value first. This lets us safely unwind on errors. + push(contextStackCursor, NO_CONTEXT, fiber); + var nextRootContext = getRootHostContext(nextRootInstance); + // Now that we know this function doesn't throw, replace it. + pop(contextStackCursor, fiber); + push(contextStackCursor, nextRootContext, fiber); + } + + function popHostContainer(fiber) { + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + pop(rootInstanceStackCursor, fiber); + } + + function getHostContext() { + var context = requiredContext(contextStackCursor.current); + return context; + } + + function pushHostContext(fiber) { + var rootInstance = requiredContext(rootInstanceStackCursor.current); + var context = requiredContext(contextStackCursor.current); + var nextContext = getChildHostContext(context, fiber.type, rootInstance); + + // Don't push this Fiber's context unless it's unique. + if (context === nextContext) { + return; + } + + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, nextContext, fiber); + } + + function popHostContext(fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + if (contextFiberStackCursor.current !== fiber) { + return; + } + + pop(contextStackCursor, fiber); + pop(contextFiberStackCursor, fiber); + } + + return { + getHostContext: getHostContext, + getRootHostContainer: getRootHostContainer, + popHostContainer: popHostContainer, + popHostContext: popHostContext, + pushHostContainer: pushHostContainer, + pushHostContext: pushHostContext + }; +}; + +var ReactFiberHydrationContext = function(config) { + var shouldSetTextContent = config.shouldSetTextContent, + hydration = config.hydration; + + // If this doesn't have hydration mode. + + if (!hydration) { + return { + enterHydrationState: function() { + return false; + }, + resetHydrationState: function() {}, + tryToClaimNextHydratableInstance: function() {}, + prepareToHydrateHostInstance: function() { + invariant( + false, + "Expected prepareToHydrateHostInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + }, + prepareToHydrateHostTextInstance: function() { + invariant( + false, + "Expected prepareToHydrateHostTextInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + }, + popHydrationState: function(fiber) { + return false; + } + }; + } + + var canHydrateInstance = hydration.canHydrateInstance, + canHydrateTextInstance = hydration.canHydrateTextInstance, + getNextHydratableSibling = hydration.getNextHydratableSibling, + getFirstHydratableChild = hydration.getFirstHydratableChild, + hydrateInstance = hydration.hydrateInstance, + hydrateTextInstance = hydration.hydrateTextInstance, + didNotMatchHydratedContainerTextInstance = + hydration.didNotMatchHydratedContainerTextInstance, + didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance, + didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance, + didNotHydrateInstance = hydration.didNotHydrateInstance, + didNotFindHydratableContainerInstance = + hydration.didNotFindHydratableContainerInstance, + didNotFindHydratableContainerTextInstance = + hydration.didNotFindHydratableContainerTextInstance, + didNotFindHydratableInstance = hydration.didNotFindHydratableInstance, + didNotFindHydratableTextInstance = + hydration.didNotFindHydratableTextInstance; + + // The deepest Fiber on the stack involved in a hydration context. + // This may have been an insertion or a hydration. + + var hydrationParentFiber = null; + var nextHydratableInstance = null; + var isHydrating = false; + + function enterHydrationState(fiber) { + var parentInstance = fiber.stateNode.containerInfo; + nextHydratableInstance = getFirstHydratableChild(parentInstance); + hydrationParentFiber = fiber; + isHydrating = true; + return true; + } + + function deleteHydratableInstance(returnFiber, instance) { + { + switch (returnFiber.tag) { + case HostRoot: + didNotHydrateContainerInstance( + returnFiber.stateNode.containerInfo, + instance + ); + break; + case HostComponent: + didNotHydrateInstance( + returnFiber.type, + returnFiber.memoizedProps, + returnFiber.stateNode, + instance + ); + break; + } + } + + var childToDelete = createFiberFromHostInstanceForDeletion(); + childToDelete.stateNode = instance; + childToDelete["return"] = returnFiber; + childToDelete.effectTag = Deletion; + + // This might seem like it belongs on progressedFirstDeletion. However, + // these children are not part of the reconciliation list of children. + // Even if we abort and rereconcile the children, that will try to hydrate + // again and the nodes are still in the host tree so these will be + // recreated. + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = childToDelete; + returnFiber.lastEffect = childToDelete; + } else { + returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; + } + } + + function insertNonHydratedInstance(returnFiber, fiber) { + fiber.effectTag |= Placement; + { + switch (returnFiber.tag) { + case HostRoot: { + var parentContainer = returnFiber.stateNode.containerInfo; + switch (fiber.tag) { + case HostComponent: + var type = fiber.type; + var props = fiber.pendingProps; + didNotFindHydratableContainerInstance( + parentContainer, + type, + props + ); + break; + case HostText: + var text = fiber.pendingProps; + didNotFindHydratableContainerTextInstance(parentContainer, text); + break; + } + break; + } + case HostComponent: { + var parentType = returnFiber.type; + var parentProps = returnFiber.memoizedProps; + var parentInstance = returnFiber.stateNode; + switch (fiber.tag) { + case HostComponent: + var _type = fiber.type; + var _props = fiber.pendingProps; + didNotFindHydratableInstance( + parentType, + parentProps, + parentInstance, + _type, + _props + ); + break; + case HostText: + var _text = fiber.pendingProps; + didNotFindHydratableTextInstance( + parentType, + parentProps, + parentInstance, + _text + ); + break; + } + break; + } + default: + return; + } + } + } + + function tryHydrate(fiber, nextInstance) { + switch (fiber.tag) { + case HostComponent: { + var type = fiber.type; + var props = fiber.pendingProps; + var instance = canHydrateInstance(nextInstance, type, props); + if (instance !== null) { + fiber.stateNode = instance; + return true; + } + return false; + } + case HostText: { + var text = fiber.pendingProps; + var textInstance = canHydrateTextInstance(nextInstance, text); + if (textInstance !== null) { + fiber.stateNode = textInstance; + return true; + } + return false; + } + default: + return false; + } + } + + function tryToClaimNextHydratableInstance(fiber) { + if (!isHydrating) { + return; + } + var nextInstance = nextHydratableInstance; + if (!nextInstance) { + // Nothing to hydrate. Make it an insertion. + insertNonHydratedInstance(hydrationParentFiber, fiber); + isHydrating = false; + hydrationParentFiber = fiber; + return; + } + if (!tryHydrate(fiber, nextInstance)) { + // If we can't hydrate this instance let's try the next one. + // We use this as a heuristic. It's based on intuition and not data so it + // might be flawed or unnecessary. + nextInstance = getNextHydratableSibling(nextInstance); + if (!nextInstance || !tryHydrate(fiber, nextInstance)) { + // Nothing to hydrate. Make it an insertion. + insertNonHydratedInstance(hydrationParentFiber, fiber); + isHydrating = false; + hydrationParentFiber = fiber; + return; + } + // We matched the next one, we'll now assume that the first one was + // superfluous and we'll delete it. Since we can't eagerly delete it + // we'll have to schedule a deletion. To do that, this node needs a dummy + // fiber associated with it. + deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance); + } + hydrationParentFiber = fiber; + nextHydratableInstance = getFirstHydratableChild(nextInstance); + } + + function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext + ) { + var instance = fiber.stateNode; + var updatePayload = hydrateInstance( + instance, + fiber.type, + fiber.memoizedProps, + rootContainerInstance, + hostContext, + fiber + ); + // TODO: Type this specific to this type of component. + fiber.updateQueue = updatePayload; + // If the update payload indicates that there is a change or if there + // is a new ref we mark this as an update. + if (updatePayload !== null) { + return true; + } + return false; + } + + function prepareToHydrateHostTextInstance(fiber) { + var textInstance = fiber.stateNode; + var textContent = fiber.memoizedProps; + var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber); + { + if (shouldUpdate) { + // We assume that prepareToHydrateHostTextInstance is called in a context where the + // hydration parent is the parent host component of this host text. + var returnFiber = hydrationParentFiber; + if (returnFiber !== null) { + switch (returnFiber.tag) { + case HostRoot: { + var parentContainer = returnFiber.stateNode.containerInfo; + didNotMatchHydratedContainerTextInstance( + parentContainer, + textInstance, + textContent + ); + break; + } + case HostComponent: { + var parentType = returnFiber.type; + var parentProps = returnFiber.memoizedProps; + var parentInstance = returnFiber.stateNode; + didNotMatchHydratedTextInstance( + parentType, + parentProps, + parentInstance, + textInstance, + textContent + ); + break; + } + } + } + } + } + return shouldUpdate; + } + + function popToNextHostParent(fiber) { + var parent = fiber["return"]; + while ( + parent !== null && + parent.tag !== HostComponent && + parent.tag !== HostRoot + ) { + parent = parent["return"]; + } + hydrationParentFiber = parent; + } + + function popHydrationState(fiber) { + if (fiber !== hydrationParentFiber) { + // We're deeper than the current hydration context, inside an inserted + // tree. + return false; + } + if (!isHydrating) { + // If we're not currently hydrating but we're in a hydration context, then + // we were an insertion and now need to pop up reenter hydration of our + // siblings. + popToNextHostParent(fiber); + isHydrating = true; + return false; + } + + var type = fiber.type; + + // If we have any remaining hydratable nodes, we need to delete them now. + // We only do this deeper than head and body since they tend to have random + // other nodes in them. We also ignore components with pure text content in + // side of them. + // TODO: Better heuristic. + if ( + fiber.tag !== HostComponent || + (type !== "head" && + type !== "body" && + !shouldSetTextContent(type, fiber.memoizedProps)) + ) { + var nextInstance = nextHydratableInstance; + while (nextInstance) { + deleteHydratableInstance(fiber, nextInstance); + nextInstance = getNextHydratableSibling(nextInstance); + } + } + + popToNextHostParent(fiber); + nextHydratableInstance = hydrationParentFiber + ? getNextHydratableSibling(fiber.stateNode) + : null; + return true; + } + + function resetHydrationState() { + hydrationParentFiber = null; + nextHydratableInstance = null; + isHydrating = false; + } - // Each iteration, currentParent is populated with node's host parent if not - // currentParentIsValid. - var currentParentIsValid = false; - var currentParent = void 0; - var currentParentIsContainer = void 0; + return { + enterHydrationState: enterHydrationState, + resetHydrationState: resetHydrationState, + tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance, + prepareToHydrateHostInstance: prepareToHydrateHostInstance, + prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance, + popHydrationState: popHydrationState + }; +}; - while (true) { - if (!currentParentIsValid) { - var parent = node["return"]; - findParent: while (true) { - invariant( - parent !== null, - "Expected to find a host parent. This error is likely caused by " + - "a bug in React. Please file an issue." - ); - switch (parent.tag) { - case HostComponent: - currentParent = parent.stateNode; - currentParentIsContainer = false; - break findParent; - case HostRoot: - currentParent = parent.stateNode.containerInfo; - currentParentIsContainer = true; - break findParent; - case HostPortal: - currentParent = parent.stateNode.containerInfo; - currentParentIsContainer = true; - break findParent; - } - parent = parent["return"]; - } - currentParentIsValid = true; - } +// This lets us hook into Fiber to debug what it's doing. +// See https://github.com/facebook/react/pull/8033. +// This is not part of the public API, not even for React DevTools. +// You may only inject a debugTool if you work on React Fiber itself. +var ReactFiberInstrumentation = { + debugTool: null +}; - if (node.tag === HostComponent || node.tag === HostText) { - commitNestedUnmounts(node); - // After all the children have unmounted, it is now safe to remove the - // node from the tree. - if (currentParentIsContainer) { - removeChildFromContainer(currentParent, node.stateNode); - } else { - removeChild(currentParent, node.stateNode); - } - // Don't visit children because we already visited them. - } else if (node.tag === HostPortal) { - // When we go into a portal, it becomes the parent to remove from. - // We will reassign it back when we pop the portal on the way up. - currentParent = node.stateNode.containerInfo; - // Visit children because portals might contain host components. - if (node.child !== null) { - node.child["return"] = node; - node = node.child; - continue; - } - } else { - commitUnmount(node); - // Visit children because we may find more host components below. - if (node.child !== null) { - node.child["return"] = node; - node = node.child; - continue; - } - } - if (node === current) { - return; - } - while (node.sibling === null) { - if (node["return"] === null || node["return"] === current) { - return; - } - node = node["return"]; - if (node.tag === HostPortal) { - // When we go out of the portal, we need to restore the parent. - // Since we don't keep a stack of them, we will search for it. - currentParentIsValid = false; - } - } - node.sibling["return"] = node["return"]; - node = node.sibling; +var ReactFiberInstrumentation_1 = ReactFiberInstrumentation; + +var warnedAboutMissingGetChildContext = void 0; + +{ + warnedAboutMissingGetChildContext = {}; +} + +var ReactFiberLegacyContext = function(stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop; + + // A cursor to the current merged context object on the stack. + + var contextStackCursor = createCursor(emptyObject); + // A cursor to a boolean indicating whether the context has changed. + var didPerformWorkStackCursor = createCursor(false); + // Keep track of the previous context object that was on the stack. + // We use this to get access to the parent context after we have already + // pushed the next context provider, and now need to merge their contexts. + var previousContext = emptyObject; + + function getUnmaskedContext(workInProgress) { + var hasOwnContext = isContextProvider(workInProgress); + if (hasOwnContext) { + // If the fiber is a context provider itself, when we read its context + // we have already pushed its own child context on the stack. A context + // provider should not "see" its own child context. Therefore we read the + // previous (parent) context instead for a context provider. + return previousContext; } + return contextStackCursor.current; } - function commitDeletion(current) { - // Recursively delete all host nodes from the parent. - // Detach refs and call componentWillUnmount() on the whole subtree. - unmountHostComponents(current); - detachFiber(current); + function cacheContext(workInProgress, unmaskedContext, maskedContext) { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; } - function commitWork(current, finishedWork) { - switch (finishedWork.tag) { - case ClassComponent: { - return; - } - case HostComponent: { - var _instance7 = finishedWork.stateNode; - if (_instance7 != null) { - // Commit the work prepared earlier. - var newProps = finishedWork.memoizedProps; - // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. - var oldProps = current !== null ? current.memoizedProps : newProps; - var type = finishedWork.type; - // TODO: Type the updateQueue to be specific to host components. - var updatePayload = finishedWork.updateQueue; - finishedWork.updateQueue = null; - if (updatePayload !== null) { - commitUpdate( - _instance7, - updatePayload, - type, - oldProps, - newProps, - finishedWork - ); - } - } - return; - } - case HostText: { - invariant( - finishedWork.stateNode !== null, - "This should have a text node initialized. This error is likely " + - "caused by a bug in React. Please file an issue." - ); - var textInstance = finishedWork.stateNode; - var newText = finishedWork.memoizedProps; - // For hydration we reuse the update path but we treat the oldProps - // as the newProps. The updatePayload will contain the real change in - // this case. - var oldText = current !== null ? current.memoizedProps : newText; - commitTextUpdate(textInstance, oldText, newText); - return; - } - case HostRoot: { - return; - } - default: { - invariant( - false, - "This unit of work tag should not have side-effects. This error is " + - "likely caused by a bug in React. Please file an issue." - ); - } + function getMaskedContext(workInProgress, unmaskedContext) { + var type = workInProgress.type; + var contextTypes = type.contextTypes; + if (!contextTypes) { + return emptyObject; + } + + // Avoid recreating masked context unless unmasked context has changed. + // Failing to do this will result in unnecessary calls to componentWillReceiveProps. + // This may trigger infinite loops if componentWillReceiveProps calls setState. + var instance = workInProgress.stateNode; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) { + return instance.__reactInternalMemoizedMaskedChildContext; + } + + var context = {}; + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; + } + + { + var name = getComponentName(workInProgress) || "Unknown"; + checkPropTypes( + contextTypes, + context, + "context", + name, + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + ); + } + + // Cache unmasked context so we can avoid recreating masked context unless necessary. + // Context is created before the class component is instantiated so check for instance. + if (instance) { + cacheContext(workInProgress, unmaskedContext, context); } + + return context; } - function commitResetTextContent(current) { - resetTextContent(current.stateNode); + function hasContextChanged() { + return didPerformWorkStackCursor.current; } - if (enableMutatingReconciler) { - return { - commitResetTextContent: commitResetTextContent, - commitPlacement: commitPlacement, - commitDeletion: commitDeletion, - commitWork: commitWork, - commitLifeCycles: commitLifeCycles, - commitErrorLogging: commitErrorLogging, - commitAttachRef: commitAttachRef, - commitDetachRef: commitDetachRef - }; - } else { - invariant(false, "Mutating reconciler is disabled."); + function isContextConsumer(fiber) { + return fiber.tag === ClassComponent && fiber.type.contextTypes != null; } -}; -var NO_CONTEXT = {}; + function isContextProvider(fiber) { + return fiber.tag === ClassComponent && fiber.type.childContextTypes != null; + } -var ReactFiberHostContext = function(config) { - var getChildHostContext = config.getChildHostContext, - getRootHostContext = config.getRootHostContext; + function popContextProvider(fiber) { + if (!isContextProvider(fiber)) { + return; + } - var contextStackCursor = createCursor(NO_CONTEXT); - var contextFiberStackCursor = createCursor(NO_CONTEXT); - var rootInstanceStackCursor = createCursor(NO_CONTEXT); + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + } - function requiredContext(c) { + function popTopLevelContextObject(fiber) { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + } + + function pushTopLevelContextObject(fiber, context, didChange) { invariant( - c !== NO_CONTEXT, - "Expected host context to exist. This error is likely caused by a bug " + - "in React. Please file an issue." + contextStackCursor.cursor == null, + "Unexpected context found on stack. " + + "This error is likely caused by a bug in React. Please file an issue." ); - return c; - } - function getRootHostContainer() { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - return rootInstance; + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); } - function pushHostContainer(fiber, nextRootInstance) { - // Push current root instance onto the stack; - // This allows us to reset root when portals are popped. - push(rootInstanceStackCursor, nextRootInstance, fiber); + function processChildContext(fiber, parentContext) { + var instance = fiber.stateNode; + var childContextTypes = fiber.type.childContextTypes; - var nextRootContext = getRootHostContext(nextRootInstance); + // TODO (bvaughn) Replace this behavior with an invariant() in the future. + // It has only been added in Fiber to match the (unintentional) behavior in Stack. + if (typeof instance.getChildContext !== "function") { + { + var componentName = getComponentName(fiber) || "Unknown"; - // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor, nextRootContext, fiber); - } + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; + warning( + false, + "%s.childContextTypes is specified but there is no getChildContext() method " + + "on the instance. You can either define getChildContext() on %s or remove " + + "childContextTypes from it.", + componentName, + componentName + ); + } + } + return parentContext; + } - function popHostContainer(fiber) { - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); - pop(rootInstanceStackCursor, fiber); - } + var childContext = void 0; + { + ReactDebugCurrentFiber.setCurrentPhase("getChildContext"); + } + startPhaseTimer(fiber, "getChildContext"); + childContext = instance.getChildContext(); + stopPhaseTimer(); + { + ReactDebugCurrentFiber.setCurrentPhase(null); + } + for (var contextKey in childContext) { + invariant( + contextKey in childContextTypes, + '%s.getChildContext(): key "%s" is not defined in childContextTypes.', + getComponentName(fiber) || "Unknown", + contextKey + ); + } + { + var name = getComponentName(fiber) || "Unknown"; + checkPropTypes( + childContextTypes, + childContext, + "child context", + name, + // In practice, there is one case in which we won't get a stack. It's when + // somebody calls unstable_renderSubtreeIntoContainer() and we process + // context from the parent component instance. The stack will be missing + // because it's outside of the reconciliation, and so the pointer has not + // been set. This is rare and doesn't matter. We'll also remove that API. + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + ); + } - function getHostContext() { - var context = requiredContext(contextStackCursor.current); - return context; + return Object.assign({}, parentContext, childContext); } - function pushHostContext(fiber) { - var rootInstance = requiredContext(rootInstanceStackCursor.current); - var context = requiredContext(contextStackCursor.current); - var nextContext = getChildHostContext(context, fiber.type, rootInstance); - - // Don't push this Fiber's context unless it's unique. - if (context === nextContext) { - return; + function pushContextProvider(workInProgress) { + if (!isContextProvider(workInProgress)) { + return false; } - // Track the context and the Fiber that provided it. - // This enables us to pop only Fibers that provide unique contexts. - push(contextFiberStackCursor, fiber, fiber); - push(contextStackCursor, nextContext, fiber); + var instance = workInProgress.stateNode; + // We push the context as early as possible to ensure stack integrity. + // If the instance does not exist yet, we will push null at first, + // and replace it on the stack later when invalidating the context. + var memoizedMergedChildContext = + (instance && instance.__reactInternalMemoizedMergedChildContext) || + emptyObject; + + // Remember the parent context so we can merge with it later. + // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. + previousContext = contextStackCursor.current; + push(contextStackCursor, memoizedMergedChildContext, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); + + return true; } - function popHostContext(fiber) { - // Do not pop unless this Fiber provided the current context. - // pushHostContext() only pushes Fibers that provide unique contexts. - if (contextFiberStackCursor.current !== fiber) { - return; - } + function invalidateContextProvider(workInProgress, didChange) { + var instance = workInProgress.stateNode; + invariant( + instance, + "Expected to have an instance by this point. " + + "This error is likely caused by a bug in React. Please file an issue." + ); - pop(contextStackCursor, fiber); - pop(contextFiberStackCursor, fiber); + if (didChange) { + // Merge parent and own context. + // Skip this if we're not updating due to sCU. + // This avoids unnecessarily recomputing memoized values. + var mergedContext = processChildContext(workInProgress, previousContext); + instance.__reactInternalMemoizedMergedChildContext = mergedContext; + + // Replace the old (or empty) context with the new one. + // It is important to unwind the context in the reverse order. + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); + // Now push the new context and mark that it has changed. + push(contextStackCursor, mergedContext, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } else { + pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + } } - function resetHostContainer() { - contextStackCursor.current = NO_CONTEXT; - rootInstanceStackCursor.current = NO_CONTEXT; + function findCurrentUnmaskedContext(fiber) { + // Currently this is only used with renderSubtreeIntoContainer; not sure if it + // makes sense elsewhere + invariant( + isFiberMounted(fiber) && fiber.tag === ClassComponent, + "Expected subtree parent to be a mounted class component. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + + var node = fiber; + while (node.tag !== HostRoot) { + if (isContextProvider(node)) { + return node.stateNode.__reactInternalMemoizedMergedChildContext; + } + var parent = node["return"]; + invariant( + parent, + "Found unexpected detached subtree parent. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + node = parent; + } + return node.stateNode.context; } return { - getHostContext: getHostContext, - getRootHostContainer: getRootHostContainer, - popHostContainer: popHostContainer, - popHostContext: popHostContext, - pushHostContainer: pushHostContainer, - pushHostContext: pushHostContext, - resetHostContainer: resetHostContainer + getUnmaskedContext: getUnmaskedContext, + cacheContext: cacheContext, + getMaskedContext: getMaskedContext, + hasContextChanged: hasContextChanged, + isContextConsumer: isContextConsumer, + isContextProvider: isContextProvider, + popContextProvider: popContextProvider, + popTopLevelContextObject: popTopLevelContextObject, + pushTopLevelContextObject: pushTopLevelContextObject, + processChildContext: processChildContext, + pushContextProvider: pushContextProvider, + invalidateContextProvider: invalidateContextProvider, + findCurrentUnmaskedContext: findCurrentUnmaskedContext }; }; -var ReactFiberHydrationContext = function(config) { - var shouldSetTextContent = config.shouldSetTextContent, - hydration = config.hydration; +var ReactFiberNewContext = function(stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop; - // If this doesn't have hydration mode. + var providerCursor = createCursor(null); + var valueCursor = createCursor(null); + var changedBitsCursor = createCursor(0); - if (!hydration) { - return { - enterHydrationState: function() { - return false; - }, - resetHydrationState: function() {}, - tryToClaimNextHydratableInstance: function() {}, - prepareToHydrateHostInstance: function() { - invariant( - false, - "Expected prepareToHydrateHostInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - }, - prepareToHydrateHostTextInstance: function() { - invariant( - false, - "Expected prepareToHydrateHostTextInstance() to never be called. " + - "This error is likely caused by a bug in React. Please file an issue." - ); - }, - popHydrationState: function(fiber) { - return false; - } - }; + var rendererSigil = void 0; + { + // Use this to detect multiple renderers using the same context + rendererSigil = {}; } - var canHydrateInstance = hydration.canHydrateInstance, - canHydrateTextInstance = hydration.canHydrateTextInstance, - getNextHydratableSibling = hydration.getNextHydratableSibling, - getFirstHydratableChild = hydration.getFirstHydratableChild, - hydrateInstance = hydration.hydrateInstance, - hydrateTextInstance = hydration.hydrateTextInstance, - didNotMatchHydratedContainerTextInstance = - hydration.didNotMatchHydratedContainerTextInstance, - didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance, - didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance, - didNotHydrateInstance = hydration.didNotHydrateInstance, - didNotFindHydratableContainerInstance = - hydration.didNotFindHydratableContainerInstance, - didNotFindHydratableContainerTextInstance = - hydration.didNotFindHydratableContainerTextInstance, - didNotFindHydratableInstance = hydration.didNotFindHydratableInstance, - didNotFindHydratableTextInstance = - hydration.didNotFindHydratableTextInstance; - - // The deepest Fiber on the stack involved in a hydration context. - // This may have been an insertion or a hydration. + function pushProvider(providerFiber) { + var context = providerFiber.type._context; - var hydrationParentFiber = null; - var nextHydratableInstance = null; - var isHydrating = false; + push(changedBitsCursor, context._changedBits, providerFiber); + push(valueCursor, context._currentValue, providerFiber); + push(providerCursor, providerFiber, providerFiber); - function enterHydrationState(fiber) { - var parentInstance = fiber.stateNode.containerInfo; - nextHydratableInstance = getFirstHydratableChild(parentInstance); - hydrationParentFiber = fiber; - isHydrating = true; - return true; - } + context._currentValue = providerFiber.pendingProps.value; + context._changedBits = providerFiber.stateNode; - function deleteHydratableInstance(returnFiber, instance) { { - switch (returnFiber.tag) { - case HostRoot: - didNotHydrateContainerInstance( - returnFiber.stateNode.containerInfo, - instance - ); - break; - case HostComponent: - didNotHydrateInstance( - returnFiber.type, - returnFiber.memoizedProps, - returnFiber.stateNode, - instance - ); - break; - } + !( + context._currentRenderer === null || + context._currentRenderer === rendererSigil + ) + ? warning( + false, + "Detected multiple renderers concurrently rendering the " + + "same context provider. This is currently unsupported." + ) + : void 0; + context._currentRenderer = rendererSigil; } + } - var childToDelete = createFiberFromHostInstanceForDeletion(); - childToDelete.stateNode = instance; - childToDelete["return"] = returnFiber; - childToDelete.effectTag = Deletion; + function popProvider(providerFiber) { + var changedBits = changedBitsCursor.current; + var currentValue = valueCursor.current; - // This might seem like it belongs on progressedFirstDeletion. However, - // these children are not part of the reconciliation list of children. - // Even if we abort and rereconcile the children, that will try to hydrate - // again and the nodes are still in the host tree so these will be - // recreated. - if (returnFiber.lastEffect !== null) { - returnFiber.lastEffect.nextEffect = childToDelete; - returnFiber.lastEffect = childToDelete; - } else { - returnFiber.firstEffect = returnFiber.lastEffect = childToDelete; - } + pop(providerCursor, providerFiber); + pop(valueCursor, providerFiber); + pop(changedBitsCursor, providerFiber); + + var context = providerFiber.type._context; + context._currentValue = currentValue; + context._changedBits = changedBits; } - function insertNonHydratedInstance(returnFiber, fiber) { - fiber.effectTag |= Placement; - { - switch (returnFiber.tag) { - case HostRoot: { - var parentContainer = returnFiber.stateNode.containerInfo; - switch (fiber.tag) { - case HostComponent: - var type = fiber.type; - var props = fiber.pendingProps; - didNotFindHydratableContainerInstance( - parentContainer, - type, - props - ); - break; - case HostText: - var text = fiber.pendingProps; - didNotFindHydratableContainerTextInstance(parentContainer, text); - break; - } - break; - } - case HostComponent: { - var parentType = returnFiber.type; - var parentProps = returnFiber.memoizedProps; - var parentInstance = returnFiber.stateNode; - switch (fiber.tag) { - case HostComponent: - var _type = fiber.type; - var _props = fiber.pendingProps; - didNotFindHydratableInstance( - parentType, - parentProps, - parentInstance, - _type, - _props - ); - break; - case HostText: - var _text = fiber.pendingProps; - didNotFindHydratableTextInstance( - parentType, - parentProps, - parentInstance, - _text - ); - break; - } - break; - } - default: - return; - } - } + return { + pushProvider: pushProvider, + popProvider: popProvider + }; +}; + +var ReactFiberStack = function() { + var valueStack = []; + + var fiberStack = void 0; + + { + fiberStack = []; } - function tryHydrate(fiber, nextInstance) { - switch (fiber.tag) { - case HostComponent: { - var type = fiber.type; - var props = fiber.pendingProps; - var instance = canHydrateInstance(nextInstance, type, props); - if (instance !== null) { - fiber.stateNode = instance; - return true; - } - return false; - } - case HostText: { - var text = fiber.pendingProps; - var textInstance = canHydrateTextInstance(nextInstance, text); - if (textInstance !== null) { - fiber.stateNode = textInstance; - return true; - } - return false; - } - default: - return false; - } + var index = -1; + + function createCursor(defaultValue) { + return { + current: defaultValue + }; + } + + function isEmpty() { + return index === -1; } - function tryToClaimNextHydratableInstance(fiber) { - if (!isHydrating) { - return; - } - var nextInstance = nextHydratableInstance; - if (!nextInstance) { - // Nothing to hydrate. Make it an insertion. - insertNonHydratedInstance(hydrationParentFiber, fiber); - isHydrating = false; - hydrationParentFiber = fiber; + function pop(cursor, fiber) { + if (index < 0) { + { + warning(false, "Unexpected pop."); + } return; } - if (!tryHydrate(fiber, nextInstance)) { - // If we can't hydrate this instance let's try the next one. - // We use this as a heuristic. It's based on intuition and not data so it - // might be flawed or unnecessary. - nextInstance = getNextHydratableSibling(nextInstance); - if (!nextInstance || !tryHydrate(fiber, nextInstance)) { - // Nothing to hydrate. Make it an insertion. - insertNonHydratedInstance(hydrationParentFiber, fiber); - isHydrating = false; - hydrationParentFiber = fiber; - return; + + { + if (fiber !== fiberStack[index]) { + warning(false, "Unexpected Fiber popped."); } - // We matched the next one, we'll now assume that the first one was - // superfluous and we'll delete it. Since we can't eagerly delete it - // we'll have to schedule a deletion. To do that, this node needs a dummy - // fiber associated with it. - deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance); } - hydrationParentFiber = fiber; - nextHydratableInstance = getFirstHydratableChild(nextInstance); - } - function prepareToHydrateHostInstance( - fiber, - rootContainerInstance, - hostContext - ) { - var instance = fiber.stateNode; - var updatePayload = hydrateInstance( - instance, - fiber.type, - fiber.memoizedProps, - rootContainerInstance, - hostContext, - fiber - ); - // TODO: Type this specific to this type of component. - fiber.updateQueue = updatePayload; - // If the update payload indicates that there is a change or if there - // is a new ref we mark this as an update. - if (updatePayload !== null) { - return true; - } - return false; - } + cursor.current = valueStack[index]; + + valueStack[index] = null; - function prepareToHydrateHostTextInstance(fiber) { - var textInstance = fiber.stateNode; - var textContent = fiber.memoizedProps; - var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber); { - if (shouldUpdate) { - // We assume that prepareToHydrateHostTextInstance is called in a context where the - // hydration parent is the parent host component of this host text. - var returnFiber = hydrationParentFiber; - if (returnFiber !== null) { - switch (returnFiber.tag) { - case HostRoot: { - var parentContainer = returnFiber.stateNode.containerInfo; - didNotMatchHydratedContainerTextInstance( - parentContainer, - textInstance, - textContent - ); - break; - } - case HostComponent: { - var parentType = returnFiber.type; - var parentProps = returnFiber.memoizedProps; - var parentInstance = returnFiber.stateNode; - didNotMatchHydratedTextInstance( - parentType, - parentProps, - parentInstance, - textInstance, - textContent - ); - break; - } - } - } - } + fiberStack[index] = null; } - return shouldUpdate; - } - function popToNextHostParent(fiber) { - var parent = fiber["return"]; - while ( - parent !== null && - parent.tag !== HostComponent && - parent.tag !== HostRoot - ) { - parent = parent["return"]; - } - hydrationParentFiber = parent; + index--; } - function popHydrationState(fiber) { - if (fiber !== hydrationParentFiber) { - // We're deeper than the current hydration context, inside an inserted - // tree. - return false; - } - if (!isHydrating) { - // If we're not currently hydrating but we're in a hydration context, then - // we were an insertion and now need to pop up reenter hydration of our - // siblings. - popToNextHostParent(fiber); - isHydrating = true; - return false; + function push(cursor, value, fiber) { + index++; + + valueStack[index] = cursor.current; + + { + fiberStack[index] = fiber; } - var type = fiber.type; + cursor.current = value; + } - // If we have any remaining hydratable nodes, we need to delete them now. - // We only do this deeper than head and body since they tend to have random - // other nodes in them. We also ignore components with pure text content in - // side of them. - // TODO: Better heuristic. - if ( - fiber.tag !== HostComponent || - (type !== "head" && - type !== "body" && - !shouldSetTextContent(type, fiber.memoizedProps)) - ) { - var nextInstance = nextHydratableInstance; - while (nextInstance) { - deleteHydratableInstance(fiber, nextInstance); - nextInstance = getNextHydratableSibling(nextInstance); + function checkThatStackIsEmpty() { + { + if (index !== -1) { + warning( + false, + "Expected an empty stack. Something was not reset properly." + ); } } - - popToNextHostParent(fiber); - nextHydratableInstance = hydrationParentFiber - ? getNextHydratableSibling(fiber.stateNode) - : null; - return true; } - function resetHydrationState() { - hydrationParentFiber = null; - nextHydratableInstance = null; - isHydrating = false; + function resetStackAfterFatalErrorInDev() { + { + index = -1; + valueStack.length = 0; + fiberStack.length = 0; + } } return { - enterHydrationState: enterHydrationState, - resetHydrationState: resetHydrationState, - tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance, - prepareToHydrateHostInstance: prepareToHydrateHostInstance, - prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance, - popHydrationState: popHydrationState + createCursor: createCursor, + isEmpty: isEmpty, + pop: pop, + push: push, + checkThatStackIsEmpty: checkThatStackIsEmpty, + resetStackAfterFatalErrorInDev: resetStackAfterFatalErrorInDev }; }; -// This lets us hook into Fiber to debug what it's doing. -// See https://github.com/facebook/react/pull/8033. -// This is not part of the public API, not even for React DevTools. -// You may only inject a debugTool if you work on React Fiber itself. -var ReactFiberInstrumentation = { - debugTool: null -}; - -var ReactFiberInstrumentation_1 = ReactFiberInstrumentation; - var invokeGuardedCallback$2 = ReactErrorUtils.invokeGuardedCallback; var hasCaughtError = ReactErrorUtils.hasCaughtError; var clearCaughtError = ReactErrorUtils.clearCaughtError; @@ -11703,17 +12186,19 @@ var warnAboutInvalidUpdates = void 0; var didWarnStateUpdateForUnmountedComponent = {}; warnAboutUpdateOnUnmounted = function(fiber) { + // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. var componentName = getComponentName(fiber) || "ReactClass"; if (didWarnStateUpdateForUnmountedComponent[componentName]) { return; } warning( false, - "Can only update a mounted or mounting " + - "component. This usually means you called setState, replaceState, " + - "or forceUpdate on an unmounted component. This is a no-op.\n\nPlease " + - "check the code for the %s component.", - componentName + "Can't call setState (or forceUpdate) on an unmounted component. This " + + "is a no-op, but it indicates a memory leak in your application. To " + + "fix, cancel all subscriptions and asynchronous tasks in the " + + "componentWillUnmount method.%s", + getStackAddendumByWorkInProgressFiber(fiber) ); didWarnStateUpdateForUnmountedComponent[componentName] = true; }; @@ -11748,16 +12233,23 @@ var warnAboutInvalidUpdates = void 0; } var ReactFiberScheduler = function(config) { - var hostContext = ReactFiberHostContext(config); + var stack = ReactFiberStack(); + var hostContext = ReactFiberHostContext(config, stack); + var legacyContext = ReactFiberLegacyContext(stack); + var newContext = ReactFiberNewContext(stack); var popHostContext = hostContext.popHostContext, popHostContainer = hostContext.popHostContainer; + var popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject, + popLegacyContextProvider = legacyContext.popContextProvider; + var popProvider = newContext.popProvider; var hydrationContext = ReactFiberHydrationContext(config); - var resetHostContainer = hostContext.resetHostContainer; var _ReactFiberBeginWork = ReactFiberBeginWork( config, hostContext, + legacyContext, + newContext, hydrationContext, scheduleWork, computeExpirationForFiber @@ -11767,17 +12259,22 @@ var ReactFiberScheduler = function(config) { var _ReactFiberCompleteWo = ReactFiberCompleteWork( config, hostContext, + legacyContext, + newContext, hydrationContext ), completeWork = _ReactFiberCompleteWo.completeWork; var _ReactFiberUnwindWork = ReactFiberUnwindWork( hostContext, + legacyContext, + newContext, scheduleWork, isAlreadyFailedLegacyErrorBoundary ), throwException = _ReactFiberUnwindWork.throwException, - unwindWork = _ReactFiberUnwindWork.unwindWork; + unwindWork = _ReactFiberUnwindWork.unwindWork, + unwindInterruptedWork = _ReactFiberUnwindWork.unwindInterruptedWork; var _ReactFiberCommitWork = ReactFiberCommitWork( config, @@ -11787,6 +12284,8 @@ var ReactFiberScheduler = function(config) { markLegacyErrorBoundaryAsFailed, recalculateCurrentTime ), + commitBeforeMutationLifeCycles = + _ReactFiberCommitWork.commitBeforeMutationLifeCycles, commitResetTextContent = _ReactFiberCommitWork.commitResetTextContent, commitPlacement = _ReactFiberCommitWork.commitPlacement, commitDeletion = _ReactFiberCommitWork.commitDeletion, @@ -11838,21 +12337,29 @@ var ReactFiberScheduler = function(config) { var stashedWorkInProgressProperties = void 0; var replayUnitOfWork = void 0; + var isReplayingFailedUnitOfWork = void 0; + var originalReplayError = void 0; + var rethrowOriginalError = void 0; if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { stashedWorkInProgressProperties = null; - replayUnitOfWork = function(failedUnitOfWork, isAsync) { - // Retore the original state of the work-in-progress - Object.assign(failedUnitOfWork, stashedWorkInProgressProperties); + isReplayingFailedUnitOfWork = false; + originalReplayError = null; + replayUnitOfWork = function(failedUnitOfWork, error, isAsync) { + // Restore the original state of the work-in-progress + assignFiberPropertiesInDEV( + failedUnitOfWork, + stashedWorkInProgressProperties + ); switch (failedUnitOfWork.tag) { case HostRoot: popHostContainer(failedUnitOfWork); - popTopLevelContextObject(failedUnitOfWork); + popTopLevelLegacyContextObject(failedUnitOfWork); break; case HostComponent: popHostContext(failedUnitOfWork); break; case ClassComponent: - popContextProvider(failedUnitOfWork); + popLegacyContextProvider(failedUnitOfWork); break; case HostPortal: popHostContainer(failedUnitOfWork); @@ -11862,28 +12369,36 @@ var ReactFiberScheduler = function(config) { break; } // Replay the begin phase. + isReplayingFailedUnitOfWork = true; + originalReplayError = error; invokeGuardedCallback$2(null, workLoop, null, isAsync); + isReplayingFailedUnitOfWork = false; + originalReplayError = null; if (hasCaughtError()) { clearCaughtError(); } else { - // This should be unreachable because the render phase is - // idempotent + // If the begin phase did not fail the second time, set this pointer + // back to the original value. + nextUnitOfWork = failedUnitOfWork; } }; + rethrowOriginalError = function() { + throw originalReplayError; + }; } - function resetContextStack() { - // Reset the stack - reset(); - // Reset the cursors - resetContext(); - resetHostContainer(); - - // TODO: Unify new context implementation with other stacks - resetProviderStack(); + function resetStack() { + if (nextUnitOfWork !== null) { + var interruptedWork = nextUnitOfWork["return"]; + while (interruptedWork !== null) { + unwindInterruptedWork(interruptedWork); + interruptedWork = interruptedWork["return"]; + } + } { ReactStrictModeWarnings.discardPendingWarnings(); + stack.checkThatStackIsEmpty(); } nextRoot = null; @@ -11901,6 +12416,7 @@ var ReactFiberScheduler = function(config) { recordEffect(); var effectTag = nextEffect.effectTag; + if (effectTag & ContentReset) { commitResetTextContent(nextEffect); } @@ -11958,6 +12474,22 @@ var ReactFiberScheduler = function(config) { } } + function commitBeforeMutationLifecycles() { + while (nextEffect !== null) { + var effectTag = nextEffect.effectTag; + + if (effectTag & Snapshot) { + recordEffect(); + var current = nextEffect.alternate; + commitBeforeMutationLifeCycles(current, nextEffect); + } + + // Don't cleanup effects yet; + // This will be done by commitAllLifeCycles() + nextEffect = nextEffect.nextEffect; + } + } + function commitAllLifeCycles( finishedRoot, currentTime, @@ -12065,16 +12597,14 @@ var ReactFiberScheduler = function(config) { prepareForCommit(root.containerInfo); - // Commit all the side-effects within a tree. We'll do this in two passes. - // The first pass performs all the host insertions, updates, deletions and - // ref unmounts. + // Invoke instances of getSnapshotBeforeUpdate before mutation. nextEffect = firstEffect; - startCommitHostEffectsTimer(); + startCommitSnapshotEffectsTimer(); while (nextEffect !== null) { var didError = false; var error = void 0; { - invokeGuardedCallback$2(null, commitAllHostEffects, null); + invokeGuardedCallback$2(null, commitBeforeMutationLifecycles, null); if (hasCaughtError()) { didError = true; error = clearCaughtError(); @@ -12093,6 +12623,36 @@ var ReactFiberScheduler = function(config) { } } } + stopCommitSnapshotEffectsTimer(); + + // Commit all the side-effects within a tree. We'll do this in two passes. + // The first pass performs all the host insertions, updates, deletions and + // ref unmounts. + nextEffect = firstEffect; + startCommitHostEffectsTimer(); + while (nextEffect !== null) { + var _didError = false; + var _error = void 0; + { + invokeGuardedCallback$2(null, commitAllHostEffects, null); + if (hasCaughtError()) { + _didError = true; + _error = clearCaughtError(); + } + } + if (_didError) { + invariant( + nextEffect !== null, + "Should have next effect. This error is likely caused by a bug " + + "in React. Please file an issue." + ); + onCommitPhaseError(nextEffect, _error); + // Clean-up + if (nextEffect !== null) { + nextEffect = nextEffect.nextEffect; + } + } + } stopCommitHostEffectsTimer(); resetAfterCommit(root.containerInfo); @@ -12110,8 +12670,8 @@ var ReactFiberScheduler = function(config) { nextEffect = firstEffect; startCommitLifeCyclesTimer(); while (nextEffect !== null) { - var _didError = false; - var _error = void 0; + var _didError2 = false; + var _error2 = void 0; { invokeGuardedCallback$2( null, @@ -12122,17 +12682,17 @@ var ReactFiberScheduler = function(config) { committedExpirationTime ); if (hasCaughtError()) { - _didError = true; - _error = clearCaughtError(); + _didError2 = true; + _error2 = clearCaughtError(); } } - if (_didError) { + if (_didError2) { invariant( nextEffect !== null, "Should have next effect. This error is likely caused by a bug " + "in React. Please file an issue." ); - onCommitPhaseError(nextEffect, _error); + onCommitPhaseError(nextEffect, _error2); if (nextEffect !== null) { nextEffect = nextEffect.nextEffect; } @@ -12356,12 +12916,21 @@ var ReactFiberScheduler = function(config) { } if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { - stashedWorkInProgressProperties = Object.assign({}, workInProgress); + stashedWorkInProgressProperties = assignFiberPropertiesInDEV( + stashedWorkInProgressProperties, + workInProgress + ); } var next = beginWork(current, workInProgress, nextRenderExpirationTime); - { ReactDebugCurrentFiber.resetCurrentFiber(); + if (isReplayingFailedUnitOfWork) { + // Currently replaying a failed unit of work. This should be unreachable, + // because the render phase is meant to be idempotent, and it should + // have thrown again. Since it didn't, rethrow the original error, so + // React's internal stack is not misaligned. + rethrowOriginalError(); + } } if (true && ReactFiberInstrumentation_1.debugTool) { ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress); @@ -12407,7 +12976,7 @@ var ReactFiberScheduler = function(config) { nextUnitOfWork === null ) { // Reset the stack and start working from the root. - resetContextStack(); + resetStack(); nextRoot = root; nextRenderExpirationTime = expirationTime; nextUnitOfWork = createWorkInProgress( @@ -12435,13 +13004,18 @@ var ReactFiberScheduler = function(config) { if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { var failedUnitOfWork = nextUnitOfWork; - replayUnitOfWork(failedUnitOfWork, isAsync); + replayUnitOfWork(failedUnitOfWork, thrownValue, isAsync); } var sourceFiber = nextUnitOfWork; var returnFiber = sourceFiber["return"]; if (returnFiber === null) { - // This is a fatal error. + // This is the root. The root could capture its own errors. However, + // we don't know if it errors before or after we pushed the host + // context. This information is needed to avoid a stack mismatch. + // Because we're not sure, treat this as a fatal error. We could track + // which phase it fails in, but doesn't seem worth it. At least + // for now. didFatal = true; onUncaughtError(thrownValue); break; @@ -12453,23 +13027,32 @@ var ReactFiberScheduler = function(config) { } while (true); // We're done performing work. Time to clean up. - stopWorkLoopTimer(interruptedBy); - interruptedBy = null; + var didCompleteRoot = false; isWorking = false; // Yield back to main thread. if (didFatal) { + stopWorkLoopTimer(interruptedBy, didCompleteRoot); + interruptedBy = null; // There was a fatal error. + { + stack.resetStackAfterFatalErrorInDev(); + } return null; } else if (nextUnitOfWork === null) { // We reached the root. if (isRootReadyForCommit) { + didCompleteRoot = true; + stopWorkLoopTimer(interruptedBy, didCompleteRoot); + interruptedBy = null; // The root successfully completed. It's ready for commit. root.pendingCommitExpirationTime = expirationTime; var finishedWork = root.current.alternate; return finishedWork; } else { // The root did not complete. + stopWorkLoopTimer(interruptedBy, didCompleteRoot); + interruptedBy = null; invariant( false, "Expired work should have completed. This error is likely caused " + @@ -12477,6 +13060,8 @@ var ReactFiberScheduler = function(config) { ); } } else { + stopWorkLoopTimer(interruptedBy, didCompleteRoot); + interruptedBy = null; // There's more work to do, but we ran out of time. Yield back to // the renderer. return null; @@ -12660,9 +13245,17 @@ var ReactFiberScheduler = function(config) { ) { // This is an interruption. (Used for performance tracking.) interruptedBy = fiber; - resetContextStack(); + resetStack(); } - if (nextRoot !== root || !isWorking) { + if ( + // If we're in the render phase, we don't need to schedule this root + // for an update, because we'll do it before we exit... + !isWorking || + isCommitting || + // ...unless this is a different root than the one we're rendering. + nextRoot !== root + ) { + // Add this root to the root schedule. requestWork(root, expirationTime); } if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { @@ -12922,7 +13515,8 @@ var ReactFiberScheduler = function(config) { if (enableUserTimingAPI && deadline !== null) { var didExpire = nextFlushedExpirationTime < recalculateCurrentTime(); - stopRequestCallbackTimer(didExpire); + var timeout = expirationTimeToMs(nextFlushedExpirationTime); + stopRequestCallbackTimer(didExpire, timeout); } if (isAsync) { @@ -12982,7 +13576,11 @@ var ReactFiberScheduler = function(config) { // Perform work on root as if the given expiration time is the current time. // This has the effect of synchronously flushing all work up to and // including the given time. + nextFlushedRoot = root; + nextFlushedExpirationTime = expirationTime; performWorkOnRoot(root, expirationTime, false); + // Flush any sync work that was scheduled by lifecycles + performSyncWork(); finishRendering(); } @@ -13231,7 +13829,8 @@ var ReactFiberScheduler = function(config) { syncUpdates: syncUpdates, interactiveUpdates: interactiveUpdates, flushInteractiveUpdates: flushInteractiveUpdates, - computeUniqueAsyncExpiration: computeUniqueAsyncExpiration + computeUniqueAsyncExpiration: computeUniqueAsyncExpiration, + legacyContext: legacyContext }; }; @@ -13244,18 +13843,6 @@ var didWarnAboutNestedUpdates = void 0; // 0 is PROD, 1 is DEV. // Might add PROFILE later. -function getContextForSubtree(parentComponent) { - if (!parentComponent) { - return emptyObject; - } - - var fiber = get(parentComponent); - var parentContext = findCurrentUnmaskedContext(fiber); - return isContextProvider(fiber) - ? processChildContext(fiber, parentContext) - : parentContext; -} - var ReactFiberReconciler$1 = function(config) { var getPublicInstance = config.getPublicInstance; @@ -13274,7 +13861,24 @@ var ReactFiberReconciler$1 = function(config) { deferredUpdates = _ReactFiberScheduler.deferredUpdates, syncUpdates = _ReactFiberScheduler.syncUpdates, interactiveUpdates = _ReactFiberScheduler.interactiveUpdates, - flushInteractiveUpdates = _ReactFiberScheduler.flushInteractiveUpdates; + flushInteractiveUpdates = _ReactFiberScheduler.flushInteractiveUpdates, + legacyContext = _ReactFiberScheduler.legacyContext; + + var findCurrentUnmaskedContext = legacyContext.findCurrentUnmaskedContext, + isContextProvider = legacyContext.isContextProvider, + processChildContext = legacyContext.processChildContext; + + function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyObject; + } + + var fiber = get(parentComponent); + var parentContext = findCurrentUnmaskedContext(fiber); + return isContextProvider(fiber) + ? processChildContext(fiber, parentContext) + : parentContext; + } function scheduleRootUpdate( current, @@ -13303,12 +13907,14 @@ var ReactFiberReconciler$1 = function(config) { callback = callback === undefined ? null : callback; { - warning( - callback === null || typeof callback === "function", - "render(...): Expected the last optional `callback` argument to be a " + - "function. Instead received: %s.", - callback - ); + !(callback === null || typeof callback === "function") + ? warning( + false, + "render(...): Expected the last optional `callback` argument to be a " + + "function. Instead received: %s.", + callback + ) + : void 0; } var update = { @@ -13630,7 +14236,8 @@ var frameDeadline = 0; var frameDeadlineObject = { timeRemaining: function() { return frameDeadline - now(); - } + }, + didTimeout: false }; function setTimeoutCallback() { diff --git a/Libraries/Renderer/ReactNativeRenderer-prod.js b/Libraries/Renderer/ReactNativeRenderer-prod.js index ca27b720b33dfe..055ddd7bb0c161 100644 --- a/Libraries/Renderer/ReactNativeRenderer-prod.js +++ b/Libraries/Renderer/ReactNativeRenderer-prod.js @@ -1174,6 +1174,9 @@ var hasSymbol = "function" === typeof Symbol && Symbol["for"], REACT_PROVIDER_TYPE = hasSymbol ? Symbol["for"]("react.provider") : 60109, REACT_CONTEXT_TYPE = hasSymbol ? Symbol["for"]("react.context") : 60110, REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol["for"]("react.async_mode") : 60111, + REACT_FORWARD_REF_TYPE = hasSymbol + ? Symbol["for"]("react.forward_ref") + : 60112, MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { if (null === maybeIterable || "undefined" === typeof maybeIterable) @@ -1819,141 +1822,6 @@ function findCurrentHostFiberWithNoPortals(parent) { } return null; } -var valueStack = [], - index = -1; -function pop(cursor) { - 0 > index || - ((cursor.current = valueStack[index]), (valueStack[index] = null), index--); -} -function push(cursor, value) { - index++; - valueStack[index] = cursor.current; - cursor.current = value; -} -function getStackAddendumByWorkInProgressFiber(workInProgress) { - var info = ""; - do { - a: switch (workInProgress.tag) { - case 0: - case 1: - case 2: - case 5: - var owner = workInProgress._debugOwner, - source = workInProgress._debugSource; - var JSCompiler_inline_result = getComponentName(workInProgress); - var ownerName = null; - owner && (ownerName = getComponentName(owner)); - owner = source; - JSCompiler_inline_result = - "\n in " + - (JSCompiler_inline_result || "Unknown") + - (owner - ? " (at " + - owner.fileName.replace(/^.*[\\\/]/, "") + - ":" + - owner.lineNumber + - ")" - : ownerName ? " (created by " + ownerName + ")" : ""); - break a; - default: - JSCompiler_inline_result = ""; - } - info += JSCompiler_inline_result; - workInProgress = workInProgress["return"]; - } while (workInProgress); - return info; -} -var _require = require("ReactFeatureFlags"), - enableGetDerivedStateFromCatch = _require.enableGetDerivedStateFromCatch, - debugRenderPhaseSideEffects = _require.debugRenderPhaseSideEffects, - debugRenderPhaseSideEffectsForStrictMode = - _require.debugRenderPhaseSideEffectsForStrictMode; -new Set(); -var contextStackCursor = { current: emptyObject }, - didPerformWorkStackCursor = { current: !1 }, - previousContext = emptyObject; -function getUnmaskedContext(workInProgress) { - return isContextProvider(workInProgress) - ? previousContext - : contextStackCursor.current; -} -function getMaskedContext(workInProgress, unmaskedContext) { - var contextTypes = workInProgress.type.contextTypes; - if (!contextTypes) return emptyObject; - var instance = workInProgress.stateNode; - if ( - instance && - instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext - ) - return instance.__reactInternalMemoizedMaskedChildContext; - var context = {}, - key; - for (key in contextTypes) context[key] = unmaskedContext[key]; - instance && - ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); - return context; -} -function isContextProvider(fiber) { - return 2 === fiber.tag && null != fiber.type.childContextTypes; -} -function popContextProvider(fiber) { - isContextProvider(fiber) && - (pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber)); -} -function pushTopLevelContextObject(fiber, context, didChange) { - invariant( - null == contextStackCursor.cursor, - "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." - ); - push(contextStackCursor, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); -} -function processChildContext(fiber, parentContext) { - var instance = fiber.stateNode, - childContextTypes = fiber.type.childContextTypes; - if ("function" !== typeof instance.getChildContext) return parentContext; - instance = instance.getChildContext(); - for (var contextKey in instance) - invariant( - contextKey in childContextTypes, - '%s.getChildContext(): key "%s" is not defined in childContextTypes.', - getComponentName(fiber) || "Unknown", - contextKey - ); - return Object.assign({}, parentContext, instance); -} -function pushContextProvider(workInProgress) { - if (!isContextProvider(workInProgress)) return !1; - var instance = workInProgress.stateNode; - instance = - (instance && instance.__reactInternalMemoizedMergedChildContext) || - emptyObject; - previousContext = contextStackCursor.current; - push(contextStackCursor, instance, workInProgress); - push( - didPerformWorkStackCursor, - didPerformWorkStackCursor.current, - workInProgress - ); - return !0; -} -function invalidateContextProvider(workInProgress, didChange) { - var instance = workInProgress.stateNode; - invariant( - instance, - "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." - ); - if (didChange) { - var mergedContext = processChildContext(workInProgress, previousContext); - instance.__reactInternalMemoizedMergedChildContext = mergedContext; - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor, workInProgress); - push(contextStackCursor, mergedContext, workInProgress); - } else pop(didPerformWorkStackCursor, workInProgress); - push(didPerformWorkStackCursor, didChange, workInProgress); -} function FiberNode(tag, pendingProps, key, mode) { this.tag = tag; this.key = key; @@ -2037,6 +1905,9 @@ function createFiberFromElement(element, mode, expirationTime) { case REACT_CONTEXT_TYPE: fiberTag = 12; break; + case REACT_FORWARD_REF_TYPE: + fiberTag = 14; + break; default: if ("number" === typeof type.tag) return ( @@ -2117,6 +1988,45 @@ function onCommitRoot(root) { function onCommitUnmount(fiber) { "function" === typeof onCommitFiberUnmount && onCommitFiberUnmount(fiber); } +function getStackAddendumByWorkInProgressFiber(workInProgress) { + var info = ""; + do { + a: switch (workInProgress.tag) { + case 0: + case 1: + case 2: + case 5: + var owner = workInProgress._debugOwner, + source = workInProgress._debugSource; + var JSCompiler_inline_result = getComponentName(workInProgress); + var ownerName = null; + owner && (ownerName = getComponentName(owner)); + owner = source; + JSCompiler_inline_result = + "\n in " + + (JSCompiler_inline_result || "Unknown") + + (owner + ? " (at " + + owner.fileName.replace(/^.*[\\\/]/, "") + + ":" + + owner.lineNumber + + ")" + : ownerName ? " (created by " + ownerName + ")" : ""); + break a; + default: + JSCompiler_inline_result = ""; + } + info += JSCompiler_inline_result; + workInProgress = workInProgress["return"]; + } while (workInProgress); + return info; +} +var _require = require("ReactFeatureFlags"), + enableGetDerivedStateFromCatch = _require.enableGetDerivedStateFromCatch, + debugRenderPhaseSideEffects = _require.debugRenderPhaseSideEffects, + debugRenderPhaseSideEffectsForStrictMode = + _require.debugRenderPhaseSideEffectsForStrictMode; +new Set(); function createUpdateQueue(baseState) { return { baseState: baseState, @@ -2288,6 +2198,7 @@ function callGetDerivedStateFromCatch(ctor, capturedValues) { return resultState; } function ReactFiberClassComponent( + legacyContext, scheduleWork, computeExpirationForFiber, memoizeProps, @@ -2335,81 +2246,82 @@ function ReactFiberClassComponent( instance.state !== workInProgress && updater.enqueueReplaceState(instance, instance.state, null); } - function callGetDerivedStateFromProps(workInProgress, instance, props) { + function callGetDerivedStateFromProps( + workInProgress, + instance, + nextProps, + prevState + ) { instance = workInProgress.type; if ("function" === typeof instance.getDerivedStateFromProps) return ( (debugRenderPhaseSideEffects || (debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & 2)) && - instance.getDerivedStateFromProps.call( - null, - props, - workInProgress.memoizedState - ), - instance.getDerivedStateFromProps.call( - null, - props, - workInProgress.memoizedState - ) + instance.getDerivedStateFromProps.call(null, nextProps, prevState), + instance.getDerivedStateFromProps.call(null, nextProps, prevState) ); } - var updater = { - isMounted: isMounted, - enqueueSetState: function(instance, partialState, callback) { - instance = instance._reactInternalFiber; - callback = void 0 === callback ? null : callback; - var expirationTime = computeExpirationForFiber(instance); - insertUpdateIntoFiber(instance, { - expirationTime: expirationTime, - partialState: partialState, - callback: callback, - isReplace: !1, - isForced: !1, - capturedValue: null, - next: null - }); - scheduleWork(instance, expirationTime); - }, - enqueueReplaceState: function(instance, state, callback) { - instance = instance._reactInternalFiber; - callback = void 0 === callback ? null : callback; - var expirationTime = computeExpirationForFiber(instance); - insertUpdateIntoFiber(instance, { - expirationTime: expirationTime, - partialState: state, - callback: callback, - isReplace: !0, - isForced: !1, - capturedValue: null, - next: null - }); - scheduleWork(instance, expirationTime); - }, - enqueueForceUpdate: function(instance, callback) { - instance = instance._reactInternalFiber; - callback = void 0 === callback ? null : callback; - var expirationTime = computeExpirationForFiber(instance); - insertUpdateIntoFiber(instance, { - expirationTime: expirationTime, - partialState: null, - callback: callback, - isReplace: !1, - isForced: !0, - capturedValue: null, - next: null - }); - scheduleWork(instance, expirationTime); - } - }; + var cacheContext = legacyContext.cacheContext, + getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + isContextConsumer = legacyContext.isContextConsumer, + hasContextChanged = legacyContext.hasContextChanged, + updater = { + isMounted: isMounted, + enqueueSetState: function(instance, partialState, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: partialState, + callback: callback, + isReplace: !1, + isForced: !1, + capturedValue: null, + next: null + }); + scheduleWork(instance, expirationTime); + }, + enqueueReplaceState: function(instance, state, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: state, + callback: callback, + isReplace: !0, + isForced: !1, + capturedValue: null, + next: null + }); + scheduleWork(instance, expirationTime); + }, + enqueueForceUpdate: function(instance, callback) { + instance = instance._reactInternalFiber; + callback = void 0 === callback ? null : callback; + var expirationTime = computeExpirationForFiber(instance); + insertUpdateIntoFiber(instance, { + expirationTime: expirationTime, + partialState: null, + callback: callback, + isReplace: !1, + isForced: !0, + capturedValue: null, + next: null + }); + scheduleWork(instance, expirationTime); + } + }; return { adoptClassInstance: adoptClassInstance, callGetDerivedStateFromProps: callGetDerivedStateFromProps, constructClassInstance: function(workInProgress, props) { var ctor = workInProgress.type, unmaskedContext = getUnmaskedContext(workInProgress), - needsContext = - 2 === workInProgress.tag && null != workInProgress.type.contextTypes, + needsContext = isContextConsumer(workInProgress), context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject; @@ -2422,7 +2334,7 @@ function ReactFiberClassComponent( null !== ctor.state && void 0 !== ctor.state ? ctor.state : null; adoptClassInstance(workInProgress, ctor); workInProgress.memoizedState = state; - props = callGetDerivedStateFromProps(workInProgress, ctor, props); + props = callGetDerivedStateFromProps(workInProgress, ctor, props, state); null !== props && void 0 !== props && (workInProgress.memoizedState = Object.assign( @@ -2430,10 +2342,7 @@ function ReactFiberClassComponent( workInProgress.memoizedState, props )); - needsContext && - ((workInProgress = workInProgress.stateNode), - (workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext), - (workInProgress.__reactInternalMemoizedMaskedChildContext = context)); + needsContext && cacheContext(workInProgress, unmaskedContext, context); return ctor; }, mountClassInstance: function(workInProgress, renderExpirationTime) { @@ -2446,9 +2355,10 @@ function ReactFiberClassComponent( instance.state = workInProgress.memoizedState; instance.refs = emptyObject; instance.context = getMaskedContext(workInProgress, unmaskedContext); - ("function" !== typeof instance.UNSAFE_componentWillMount && - "function" !== typeof instance.componentWillMount) || - "function" === typeof ctor.getDerivedStateFromProps || + "function" === typeof ctor.getDerivedStateFromProps || + "function" === typeof instance.getSnapshotBeforeUpdate || + ("function" !== typeof instance.UNSAFE_componentWillMount && + "function" !== typeof instance.componentWillMount) || ((ctor = instance.state), "function" === typeof instance.componentWillMount && instance.componentWillMount(), @@ -2479,9 +2389,12 @@ function ReactFiberClassComponent( oldContext = instance.context, newUnmaskedContext = getUnmaskedContext(workInProgress); newUnmaskedContext = getMaskedContext(workInProgress, newUnmaskedContext); - ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && - "function" !== typeof instance.componentWillReceiveProps) || + var hasNewLifecycles = "function" === typeof ctor.getDerivedStateFromProps || + "function" === typeof instance.getSnapshotBeforeUpdate; + hasNewLifecycles || + ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && + "function" !== typeof instance.componentWillReceiveProps) || ((oldProps !== newProps || oldContext !== newUnmaskedContext) && callComponentWillReceiveProps( workInProgress, @@ -2489,15 +2402,8 @@ function ReactFiberClassComponent( newProps, newUnmaskedContext )); - oldContext = void 0; - oldProps !== newProps && - (oldContext = callGetDerivedStateFromProps( - workInProgress, - instance, - newProps - )); - var oldState = workInProgress.memoizedState, - derivedStateFromCatch = void 0; + oldContext = workInProgress.memoizedState; + var derivedStateFromCatch = void 0; if (null !== workInProgress.updateQueue) { renderExpirationTime = processUpdateQueue( null, @@ -2516,24 +2422,46 @@ function ReactFiberClassComponent( ctor, updateQueue.capturedValues )); - } else renderExpirationTime = oldState; - null !== oldContext && - void 0 !== oldContext && - (renderExpirationTime = + } else renderExpirationTime = oldContext; + ctor = void 0; + oldProps !== newProps && + (ctor = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + renderExpirationTime + )); + null !== ctor && + void 0 !== ctor && + ((renderExpirationTime = null === renderExpirationTime || void 0 === renderExpirationTime - ? oldContext - : Object.assign({}, renderExpirationTime, oldContext)); + ? ctor + : Object.assign({}, renderExpirationTime, ctor)), + (updateQueue = workInProgress.updateQueue), + null !== updateQueue && + (updateQueue.baseState = Object.assign( + {}, + updateQueue.baseState, + ctor + ))); null !== derivedStateFromCatch && void 0 !== derivedStateFromCatch && - (renderExpirationTime = + ((renderExpirationTime = null === renderExpirationTime || void 0 === renderExpirationTime ? derivedStateFromCatch - : Object.assign({}, renderExpirationTime, derivedStateFromCatch)); + : Object.assign({}, renderExpirationTime, derivedStateFromCatch)), + (ctor = workInProgress.updateQueue), + null !== ctor && + (ctor.baseState = Object.assign( + {}, + ctor.baseState, + derivedStateFromCatch + ))); if ( !( oldProps !== newProps || - oldState !== renderExpirationTime || - didPerformWorkStackCursor.current || + oldContext !== renderExpirationTime || + hasContextChanged() || (null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate) ) @@ -2547,26 +2475,18 @@ function ReactFiberClassComponent( workInProgress, oldProps, newProps, - oldState, + oldContext, renderExpirationTime, newUnmaskedContext )) - ? (("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - "function" === typeof ctor.getDerivedStateFromProps || - ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate( - newProps, - renderExpirationTime, - newUnmaskedContext - ), - "function" === typeof instance.UNSAFE_componentWillUpdate && - instance.UNSAFE_componentWillUpdate( - newProps, - renderExpirationTime, - newUnmaskedContext - )), - "function" === typeof instance.componentDidUpdate && + ? (hasNewLifecycles || + ("function" !== typeof instance.UNSAFE_componentWillMount && + "function" !== typeof instance.componentWillMount) || + ("function" === typeof instance.componentWillMount && + instance.componentWillMount(), + "function" === typeof instance.UNSAFE_componentWillMount && + instance.UNSAFE_componentWillMount()), + "function" === typeof instance.componentDidMount && (workInProgress.effectTag |= 4)) : ("function" === typeof instance.componentDidMount && (workInProgress.effectTag |= 4), @@ -2591,9 +2511,12 @@ function ReactFiberClassComponent( oldContext = instance.context, newUnmaskedContext = getUnmaskedContext(workInProgress); newUnmaskedContext = getMaskedContext(workInProgress, newUnmaskedContext); - ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && - "function" !== typeof instance.componentWillReceiveProps) || + var hasNewLifecycles = "function" === typeof ctor.getDerivedStateFromProps || + "function" === typeof instance.getSnapshotBeforeUpdate; + hasNewLifecycles || + ("function" !== typeof instance.UNSAFE_componentWillReceiveProps && + "function" !== typeof instance.componentWillReceiveProps) || ((oldProps !== newProps || oldContext !== newUnmaskedContext) && callComponentWillReceiveProps( workInProgress, @@ -2601,13 +2524,6 @@ function ReactFiberClassComponent( newProps, newUnmaskedContext )); - var derivedStateFromProps = void 0; - oldProps !== newProps && - (derivedStateFromProps = callGetDerivedStateFromProps( - workInProgress, - instance, - newProps - )); oldContext = workInProgress.memoizedState; var derivedStateFromCatch = void 0; if (null !== workInProgress.updateQueue) { @@ -2629,23 +2545,45 @@ function ReactFiberClassComponent( updateQueue.capturedValues )); } else renderExpirationTime = oldContext; - null !== derivedStateFromProps && - void 0 !== derivedStateFromProps && - (renderExpirationTime = + ctor = void 0; + oldProps !== newProps && + (ctor = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + renderExpirationTime + )); + null !== ctor && + void 0 !== ctor && + ((renderExpirationTime = null === renderExpirationTime || void 0 === renderExpirationTime - ? derivedStateFromProps - : Object.assign({}, renderExpirationTime, derivedStateFromProps)); + ? ctor + : Object.assign({}, renderExpirationTime, ctor)), + (updateQueue = workInProgress.updateQueue), + null !== updateQueue && + (updateQueue.baseState = Object.assign( + {}, + updateQueue.baseState, + ctor + ))); null !== derivedStateFromCatch && void 0 !== derivedStateFromCatch && - (renderExpirationTime = + ((renderExpirationTime = null === renderExpirationTime || void 0 === renderExpirationTime ? derivedStateFromCatch - : Object.assign({}, renderExpirationTime, derivedStateFromCatch)); + : Object.assign({}, renderExpirationTime, derivedStateFromCatch)), + (ctor = workInProgress.updateQueue), + null !== ctor && + (ctor.baseState = Object.assign( + {}, + ctor.baseState, + derivedStateFromCatch + ))); if ( !( oldProps !== newProps || oldContext !== renderExpirationTime || - didPerformWorkStackCursor.current || + hasContextChanged() || (null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate) ) @@ -2655,9 +2593,13 @@ function ReactFiberClassComponent( (oldProps === current.memoizedProps && oldContext === current.memoizedState) || (workInProgress.effectTag |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldContext === current.memoizedState) || + (workInProgress.effectTag |= 2048), !1 ); - (derivedStateFromProps = checkShouldComponentUpdate( + (derivedStateFromCatch = checkShouldComponentUpdate( workInProgress, oldProps, newProps, @@ -2665,9 +2607,9 @@ function ReactFiberClassComponent( renderExpirationTime, newUnmaskedContext )) - ? (("function" !== typeof instance.UNSAFE_componentWillUpdate && - "function" !== typeof instance.componentWillUpdate) || - "function" === typeof ctor.getDerivedStateFromProps || + ? (hasNewLifecycles || + ("function" !== typeof instance.UNSAFE_componentWillUpdate && + "function" !== typeof instance.componentWillUpdate) || ("function" === typeof instance.componentWillUpdate && instance.componentWillUpdate( newProps, @@ -2681,17 +2623,23 @@ function ReactFiberClassComponent( newUnmaskedContext )), "function" === typeof instance.componentDidUpdate && - (workInProgress.effectTag |= 4)) + (workInProgress.effectTag |= 4), + "function" === typeof instance.getSnapshotBeforeUpdate && + (workInProgress.effectTag |= 2048)) : ("function" !== typeof instance.componentDidUpdate || (oldProps === current.memoizedProps && oldContext === current.memoizedState) || (workInProgress.effectTag |= 4), + "function" !== typeof instance.getSnapshotBeforeUpdate || + (oldProps === current.memoizedProps && + oldContext === current.memoizedState) || + (workInProgress.effectTag |= 2048), memoizeProps(workInProgress, newProps), memoizeState(workInProgress, renderExpirationTime)); instance.props = newProps; instance.state = renderExpirationTime; instance.context = newUnmaskedContext; - return derivedStateFromProps; + return derivedStateFromCatch; } }; } @@ -3368,34 +3316,12 @@ function ChildReconciler(shouldTrackSideEffects) { }; } var reconcileChildFibers = ChildReconciler(!0), - mountChildFibers = ChildReconciler(!1), - changedBitsStack = [], - currentValueStack = [], - stack = [], - index$1 = -1; -function pushProvider(providerFiber) { - var context = providerFiber.type.context; - index$1 += 1; - changedBitsStack[index$1] = context._changedBits; - currentValueStack[index$1] = context._currentValue; - stack[index$1] = providerFiber; - context._currentValue = providerFiber.pendingProps.value; - context._changedBits = providerFiber.stateNode; -} -function popProvider(providerFiber) { - var changedBits = changedBitsStack[index$1], - currentValue = currentValueStack[index$1]; - changedBitsStack[index$1] = null; - currentValueStack[index$1] = null; - stack[index$1] = null; - --index$1; - providerFiber = providerFiber.type.context; - providerFiber._currentValue = currentValue; - providerFiber._changedBits = changedBits; -} + mountChildFibers = ChildReconciler(!1); function ReactFiberBeginWork( config, hostContext, + legacyContext, + newContext, hydrationContext, scheduleWork, computeExpirationForFiber @@ -3501,7 +3427,12 @@ function ReactFiberBeginWork( changedBits, renderExpirationTime ) { - for (var fiber = workInProgress.child; null !== fiber; ) { + var fiber = workInProgress.child; + for ( + null !== fiber && (fiber["return"] = workInProgress); + null !== fiber; + + ) { switch (fiber.tag) { case 12: var nextFiber = fiber.stateNode | 0; @@ -3557,10 +3488,10 @@ function ReactFiberBeginWork( workInProgress, renderExpirationTime ) { - var context = workInProgress.type.context, + var context = workInProgress.type._context, newProps = workInProgress.pendingProps, oldProps = workInProgress.memoizedProps; - if (!didPerformWorkStackCursor.current && oldProps === newProps) + if (!hasLegacyContextChanged() && oldProps === newProps) return ( (workInProgress.stateNode = 0), pushProvider(workInProgress), @@ -3647,11 +3578,19 @@ function ReactFiberBeginWork( shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree, pushHostContext = hostContext.pushHostContext, pushHostContainer = hostContext.pushHostContainer, + pushProvider = newContext.pushProvider, + getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + hasLegacyContextChanged = legacyContext.hasContextChanged, + pushLegacyContextProvider = legacyContext.pushContextProvider, + pushTopLevelContextObject = legacyContext.pushTopLevelContextObject, + invalidateContextProvider = legacyContext.invalidateContextProvider, enterHydrationState = hydrationContext.enterHydrationState, resetHydrationState = hydrationContext.resetHydrationState, tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance; config = ReactFiberClassComponent( + legacyContext, scheduleWork, computeExpirationForFiber, function(workInProgress, nextProps) { @@ -3678,7 +3617,7 @@ function ReactFiberBeginWork( pushHostRootContext(workInProgress); break; case 2: - pushContextProvider(workInProgress); + pushLegacyContextProvider(workInProgress); break; case 4: pushHostContainer( @@ -3715,7 +3654,8 @@ function ReactFiberBeginWork( ((props = callGetDerivedStateFromProps( workInProgress, fn, - props + props, + workInProgress.memoizedState )), null !== props && void 0 !== props && @@ -3724,7 +3664,7 @@ function ReactFiberBeginWork( workInProgress.memoizedState, props ))), - (props = pushContextProvider(workInProgress)), + (props = pushLegacyContextProvider(workInProgress)), adoptClassInstance(workInProgress, fn), mountClassInstance(workInProgress, renderExpirationTime), (current = finishClassComponent( @@ -3744,7 +3684,7 @@ function ReactFiberBeginWork( return ( (props = workInProgress.type), (renderExpirationTime = workInProgress.pendingProps), - didPerformWorkStackCursor.current || + hasLegacyContextChanged() || workInProgress.memoizedProps !== renderExpirationTime ? ((fn = getUnmaskedContext(workInProgress)), (fn = getMaskedContext(workInProgress, fn)), @@ -3760,7 +3700,7 @@ function ReactFiberBeginWork( current ); case 2: - props = pushContextProvider(workInProgress); + props = pushLegacyContextProvider(workInProgress); null === current ? null === workInProgress.stateNode ? (constructClassInstance( @@ -3842,7 +3782,7 @@ function ReactFiberBeginWork( updateQueue = workInProgress.memoizedProps; fn = workInProgress.pendingProps; unmaskedContext = null !== current ? current.memoizedProps : null; - if (!didPerformWorkStackCursor.current && updateQueue === fn) { + if (!hasLegacyContextChanged() && updateQueue === fn) { if ( (updateQueue = workInProgress.mode & 1 && @@ -3884,7 +3824,7 @@ function ReactFiberBeginWork( case 7: return ( (props = workInProgress.pendingProps), - didPerformWorkStackCursor.current || + hasLegacyContextChanged() || workInProgress.memoizedProps !== props || (props = workInProgress.memoizedProps), (fn = props.children), @@ -3914,8 +3854,7 @@ function ReactFiberBeginWork( workInProgress.stateNode.containerInfo ), (props = workInProgress.pendingProps), - didPerformWorkStackCursor.current || - workInProgress.memoizedProps !== props + hasLegacyContextChanged() || workInProgress.memoizedProps !== props ? (null === current ? (workInProgress.child = reconcileChildFibers( workInProgress, @@ -3932,10 +3871,21 @@ function ReactFiberBeginWork( )), current ); + case 14: + return ( + (renderExpirationTime = workInProgress.type.render), + (renderExpirationTime = renderExpirationTime( + workInProgress.pendingProps, + workInProgress.ref + )), + reconcileChildren(current, workInProgress, renderExpirationTime), + (workInProgress.memoizedProps = renderExpirationTime), + workInProgress.child + ); case 10: return ( (renderExpirationTime = workInProgress.pendingProps), - didPerformWorkStackCursor.current || + hasLegacyContextChanged() || workInProgress.memoizedProps !== renderExpirationTime ? (reconcileChildren( current, @@ -3953,7 +3903,7 @@ function ReactFiberBeginWork( case 11: return ( (renderExpirationTime = workInProgress.pendingProps.children), - didPerformWorkStackCursor.current || + hasLegacyContextChanged() || (null !== renderExpirationTime && workInProgress.memoizedProps !== renderExpirationTime) ? (reconcileChildren( @@ -3976,43 +3926,33 @@ function ReactFiberBeginWork( renderExpirationTime ); case 12: - a: { - fn = workInProgress.type; - unmaskedContext = workInProgress.pendingProps; - updateQueue = workInProgress.memoizedProps; - props = fn._currentValue; - var changedBits = fn._changedBits; - if ( - didPerformWorkStackCursor.current || - 0 !== changedBits || - updateQueue !== unmaskedContext - ) { - workInProgress.memoizedProps = unmaskedContext; - var observedBits = unmaskedContext.unstable_observedBits; - if (void 0 === observedBits || null === observedBits) - observedBits = 1073741823; - workInProgress.stateNode = observedBits; - if (0 !== (changedBits & observedBits)) - propagateContextChange( - workInProgress, - fn, - changedBits, - renderExpirationTime - ); - else if ( - null !== updateQueue && - updateQueue.children === unmaskedContext.children - ) { - current = bailoutOnAlreadyFinishedWork(current, workInProgress); - break a; - } - renderExpirationTime = unmaskedContext.children; - renderExpirationTime = renderExpirationTime(props); - reconcileChildren(current, workInProgress, renderExpirationTime); - current = workInProgress.child; - } else - current = bailoutOnAlreadyFinishedWork(current, workInProgress); - } + fn = workInProgress.type; + unmaskedContext = workInProgress.pendingProps; + var oldProps = workInProgress.memoizedProps; + props = fn._currentValue; + updateQueue = fn._changedBits; + if ( + hasLegacyContextChanged() || + 0 !== updateQueue || + oldProps !== unmaskedContext + ) { + workInProgress.memoizedProps = unmaskedContext; + oldProps = unmaskedContext.unstable_observedBits; + if (void 0 === oldProps || null === oldProps) oldProps = 1073741823; + workInProgress.stateNode = oldProps; + 0 !== (updateQueue & oldProps) && + propagateContextChange( + workInProgress, + fn, + updateQueue, + renderExpirationTime + ); + renderExpirationTime = unmaskedContext.children; + renderExpirationTime = renderExpirationTime(props); + reconcileChildren(current, workInProgress, renderExpirationTime); + current = workInProgress.child; + } else + current = bailoutOnAlreadyFinishedWork(current, workInProgress); return current; default: invariant( @@ -4023,7 +3963,13 @@ function ReactFiberBeginWork( } }; } -function ReactFiberCompleteWork(config, hostContext, hydrationContext) { +function ReactFiberCompleteWork( + config, + hostContext, + legacyContext, + newContext, + hydrationContext +) { function markUpdate(workInProgress) { workInProgress.effectTag |= 4; } @@ -4037,6 +3983,9 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { popHostContext = hostContext.popHostContext, getHostContext = hostContext.getHostContext, popHostContainer = hostContext.popHostContainer, + popLegacyContextProvider = legacyContext.popContextProvider, + popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject, + popProvider = newContext.popProvider, prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance, prepareToHydrateHostTextInstance = @@ -4065,7 +4014,7 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { return null; case 2: return ( - popContextProvider(workInProgress), + popLegacyContextProvider(workInProgress), (current = workInProgress.stateNode), (newProps = workInProgress.updateQueue), null !== newProps && @@ -4078,8 +4027,7 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { ); case 3: popHostContainer(workInProgress); - pop(didPerformWorkStackCursor, workInProgress); - pop(contextStackCursor, workInProgress); + popTopLevelLegacyContextObject(workInProgress); newProps = workInProgress.stateNode; newProps.pendingContext && ((newProps.context = newProps.pendingContext), @@ -4263,6 +4211,8 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { return (workInProgress.tag = 7), null; case 9: return null; + case 14: + return null; case 10: return null; case 11: @@ -4293,11 +4243,16 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { } function ReactFiberUnwindWork( hostContext, + legacyContext, + newContext, scheduleWork, isAlreadyFailedLegacyErrorBoundary ) { var popHostContainer = hostContext.popHostContainer, - popHostContext = hostContext.popHostContext; + popHostContext = hostContext.popHostContext, + popLegacyContextProvider = legacyContext.popContextProvider, + popTopLevelLegacyContextObject = legacyContext.popTopLevelContextObject, + popProvider = newContext.popProvider; return { throwException: function(returnFiber, sourceFiber, rawValue) { sourceFiber.effectTag |= 512; @@ -4341,7 +4296,7 @@ function ReactFiberUnwindWork( unwindWork: function(workInProgress) { switch (workInProgress.tag) { case 2: - popContextProvider(workInProgress); + popLegacyContextProvider(workInProgress); var effectTag = workInProgress.effectTag; return effectTag & 1024 ? ((workInProgress.effectTag = (effectTag & -1025) | 64), @@ -4350,8 +4305,7 @@ function ReactFiberUnwindWork( case 3: return ( popHostContainer(workInProgress), - pop(didPerformWorkStackCursor, workInProgress), - pop(contextStackCursor, workInProgress), + popTopLevelLegacyContextObject(workInProgress), (effectTag = workInProgress.effectTag), effectTag & 1024 ? ((workInProgress.effectTag = (effectTag & -1025) | 64), @@ -4367,6 +4321,25 @@ function ReactFiberUnwindWork( default: return null; } + }, + unwindInterruptedWork: function(interruptedWork) { + switch (interruptedWork.tag) { + case 2: + popLegacyContextProvider(interruptedWork); + break; + case 3: + popHostContainer(interruptedWork); + popTopLevelLegacyContextObject(interruptedWork); + break; + case 5: + popHostContext(interruptedWork); + break; + case 4: + popHostContainer(interruptedWork); + break; + case 13: + popProvider(interruptedWork); + } } }; } @@ -4375,9 +4348,9 @@ function logError(boundary, errorInfo) { stack = errorInfo.stack; null === stack && (stack = getStackAddendumByWorkInProgressFiber(source)); null !== source && getComponentName(source); + source = null !== stack ? stack : ""; errorInfo = errorInfo.value; - stack = null !== stack ? stack : ""; - null !== boundary && getComponentName(boundary); + null !== boundary && 2 === boundary.tag && getComponentName(boundary); try { if (errorInfo instanceof Error) { var message = errorInfo.message, @@ -4387,13 +4360,13 @@ function logError(boundary, errorInfo) { errorToHandle.message = (message ? name + ": " + message : name) + "\n\nThis error is located at:" + - stack; + source; } catch (e) {} } else errorToHandle = "string" === typeof errorInfo - ? Error(errorInfo + "\n\nThis error is located at:" + stack) - : Error("Unspecified error at:" + stack); + ? Error(errorInfo + "\n\nThis error is located at:" + source) + : Error("Unspecified error at:" + source); ExceptionsManager.handleException(errorToHandle, !1); } catch (e) { (e && e.suppressReactErrorLogging) || console.error(e); @@ -4415,19 +4388,19 @@ function ReactFiberCommitWork( } catch (refError) { captureError(current, refError); } - else ref.value = null; + else ref.current = null; } function commitUnmount(current) { "function" === typeof onCommitUnmount && onCommitUnmount(current); switch (current.tag) { case 2: safelyDetachRef(current); - var _instance6 = current.stateNode; - if ("function" === typeof _instance6.componentWillUnmount) + var _instance7 = current.stateNode; + if ("function" === typeof _instance7.componentWillUnmount) try { - (_instance6.props = current.memoizedProps), - (_instance6.state = current.memoizedState), - _instance6.componentWillUnmount(); + (_instance7.props = current.memoizedProps), + (_instance7.state = current.memoizedState), + _instance7.componentWillUnmount(); } catch (unmountError) { captureError(current, unmountError); } @@ -4537,6 +4510,34 @@ function ReactFiberCommitWork( removeChild = mutation.removeChild, removeChildFromContainer = mutation.removeChildFromContainer; return { + commitBeforeMutationLifeCycles: function(current, finishedWork) { + switch (finishedWork.tag) { + case 2: + if (finishedWork.effectTag & 2048 && null !== current) { + var prevProps = current.memoizedProps, + prevState = current.memoizedState; + current = finishedWork.stateNode; + current.props = finishedWork.memoizedProps; + current.state = finishedWork.memoizedState; + finishedWork = current.getSnapshotBeforeUpdate( + prevProps, + prevState + ); + current.__reactInternalSnapshotBeforeUpdate = finishedWork; + } + break; + case 3: + case 5: + case 6: + case 4: + break; + default: + invariant( + !1, + "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue." + ); + } + }, commitResetTextContent: function(current) { resetTextContent(current.stateNode); }, @@ -4642,8 +4643,8 @@ function ReactFiberCommitWork( case 2: break; case 5: - var _instance7 = finishedWork.stateNode; - if (null != _instance7) { + var _instance8 = finishedWork.stateNode; + if (null != _instance8) { var newProps = finishedWork.memoizedProps; current = null !== current ? current.memoizedProps : newProps; var type = finishedWork.type, @@ -4651,7 +4652,7 @@ function ReactFiberCommitWork( finishedWork.updateQueue = null; null !== updatePayload && commitUpdate( - _instance7, + _instance8, updatePayload, type, current, @@ -4665,11 +4666,11 @@ function ReactFiberCommitWork( null !== finishedWork.stateNode, "This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue." ); - _instance7 = finishedWork.memoizedProps; + _instance8 = finishedWork.memoizedProps; commitTextUpdate( finishedWork.stateNode, - null !== current ? current.memoizedProps : _instance7, - _instance7 + null !== current ? current.memoizedProps : _instance8, + _instance8 ); break; case 3: @@ -4695,7 +4696,11 @@ function ReactFiberCommitWork( current = current.memoizedState; finishedRoot.props = finishedWork.memoizedProps; finishedRoot.state = finishedWork.memoizedState; - finishedRoot.componentDidUpdate(prevProps, current); + finishedRoot.componentDidUpdate( + prevProps, + current, + finishedRoot.__reactInternalSnapshotBeforeUpdate + ); } finishedWork = finishedWork.updateQueue; null !== finishedWork && commitCallbacks(finishedWork, finishedRoot); @@ -4757,9 +4762,12 @@ function ReactFiberCommitWork( onUncaughtError.state = finishedWork.memoizedState; for (ctor = 0; ctor < capturedErrors.length; ctor++) { updateQueue = capturedErrors[ctor]; - var _error = updateQueue.value; + var _error = updateQueue.value, + stack = updateQueue.stack; logError(finishedWork, updateQueue); - onUncaughtError.componentDidCatch(_error); + onUncaughtError.componentDidCatch(_error, { + componentStack: null !== stack ? stack : "" + }); } break; case 3: @@ -4785,17 +4793,17 @@ function ReactFiberCommitWork( commitAttachRef: function(finishedWork) { var ref = finishedWork.ref; if (null !== ref) { - var _instance5 = finishedWork.stateNode; + var _instance6 = finishedWork.stateNode; switch (finishedWork.tag) { case 5: - finishedWork = getPublicInstance(_instance5); + finishedWork = getPublicInstance(_instance6); break; default: - finishedWork = _instance5; + finishedWork = _instance6; } "function" === typeof ref ? ref(finishedWork) - : (ref.value = finishedWork); + : (ref.current = finishedWork); } }, commitDetachRef: function(current) { @@ -4803,12 +4811,12 @@ function ReactFiberCommitWork( null !== current && ("function" === typeof current ? current(null) - : (current.value = null)); + : (current.current = null)); } }; } var NO_CONTEXT = {}; -function ReactFiberHostContext(config) { +function ReactFiberHostContext(config, stack) { function requiredContext(c) { invariant( c !== NO_CONTEXT, @@ -4817,10 +4825,13 @@ function ReactFiberHostContext(config) { return c; } var getChildHostContext = config.getChildHostContext, - getRootHostContext = config.getRootHostContext, - contextStackCursor = { current: NO_CONTEXT }, - contextFiberStackCursor = { current: NO_CONTEXT }, - rootInstanceStackCursor = { current: NO_CONTEXT }; + getRootHostContext = config.getRootHostContext; + config = stack.createCursor; + var push = stack.push, + pop = stack.pop, + contextStackCursor = config(NO_CONTEXT), + contextFiberStackCursor = config(NO_CONTEXT), + rootInstanceStackCursor = config(NO_CONTEXT); return { getHostContext: function() { return requiredContext(contextStackCursor.current); @@ -4839,8 +4850,10 @@ function ReactFiberHostContext(config) { }, pushHostContainer: function(fiber, nextRootInstance) { push(rootInstanceStackCursor, nextRootInstance, fiber); - nextRootInstance = getRootHostContext(nextRootInstance); push(contextFiberStackCursor, fiber, fiber); + push(contextStackCursor, NO_CONTEXT, fiber); + nextRootInstance = getRootHostContext(nextRootInstance); + pop(contextStackCursor, fiber); push(contextStackCursor, nextRootInstance, fiber); }, pushHostContext: function(fiber) { @@ -4850,10 +4863,6 @@ function ReactFiberHostContext(config) { context !== rootInstance && (push(contextFiberStackCursor, fiber, fiber), push(contextStackCursor, rootInstance, fiber)); - }, - resetHostContainer: function() { - contextStackCursor.current = NO_CONTEXT; - rootInstanceStackCursor.current = NO_CONTEXT; } }; } @@ -5013,22 +5022,198 @@ function ReactFiberHydrationContext(config) { } }; } -function ReactFiberScheduler(config) { - function resetContextStack() { - for (; -1 < index; ) (valueStack[index] = null), index--; +function ReactFiberLegacyContext(stack) { + function cacheContext(workInProgress, unmaskedContext, maskedContext) { + workInProgress = workInProgress.stateNode; + workInProgress.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + workInProgress.__reactInternalMemoizedMaskedChildContext = maskedContext; + } + function isContextProvider(fiber) { + return 2 === fiber.tag && null != fiber.type.childContextTypes; + } + function processChildContext(fiber, parentContext) { + var instance = fiber.stateNode, + childContextTypes = fiber.type.childContextTypes; + if ("function" !== typeof instance.getChildContext) return parentContext; + instance = instance.getChildContext(); + for (var contextKey in instance) + invariant( + contextKey in childContextTypes, + '%s.getChildContext(): key "%s" is not defined in childContextTypes.', + getComponentName(fiber) || "Unknown", + contextKey + ); + return Object.assign({}, parentContext, instance); + } + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop, + contextStackCursor = createCursor(emptyObject), + didPerformWorkStackCursor = createCursor(!1), previousContext = emptyObject; - contextStackCursor.current = emptyObject; - didPerformWorkStackCursor.current = !1; - resetHostContainer(); - for (var i = index$1; -1 < i; i--) { - var context = stack[i].type.context; - context._currentValue = context._defaultValue; - context._changedBits = 0; - changedBitsStack[i] = null; - currentValueStack[i] = null; - stack[i] = null; + return { + getUnmaskedContext: function(workInProgress) { + return isContextProvider(workInProgress) + ? previousContext + : contextStackCursor.current; + }, + cacheContext: cacheContext, + getMaskedContext: function(workInProgress, unmaskedContext) { + var contextTypes = workInProgress.type.contextTypes; + if (!contextTypes) return emptyObject; + var instance = workInProgress.stateNode; + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext + ) + return instance.__reactInternalMemoizedMaskedChildContext; + var context = {}, + key; + for (key in contextTypes) context[key] = unmaskedContext[key]; + instance && cacheContext(workInProgress, unmaskedContext, context); + return context; + }, + hasContextChanged: function() { + return didPerformWorkStackCursor.current; + }, + isContextConsumer: function(fiber) { + return 2 === fiber.tag && null != fiber.type.contextTypes; + }, + isContextProvider: isContextProvider, + popContextProvider: function(fiber) { + isContextProvider(fiber) && + (pop(didPerformWorkStackCursor, fiber), pop(contextStackCursor, fiber)); + }, + popTopLevelContextObject: function(fiber) { + pop(didPerformWorkStackCursor, fiber); + pop(contextStackCursor, fiber); + }, + pushTopLevelContextObject: function(fiber, context, didChange) { + invariant( + null == contextStackCursor.cursor, + "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." + ); + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); + }, + processChildContext: processChildContext, + pushContextProvider: function(workInProgress) { + if (!isContextProvider(workInProgress)) return !1; + var instance = workInProgress.stateNode; + instance = + (instance && instance.__reactInternalMemoizedMergedChildContext) || + emptyObject; + previousContext = contextStackCursor.current; + push(contextStackCursor, instance, workInProgress); + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ); + return !0; + }, + invalidateContextProvider: function(workInProgress, didChange) { + var instance = workInProgress.stateNode; + invariant( + instance, + "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." + ); + if (didChange) { + var mergedContext = processChildContext( + workInProgress, + previousContext + ); + instance.__reactInternalMemoizedMergedChildContext = mergedContext; + pop(didPerformWorkStackCursor, workInProgress); + pop(contextStackCursor, workInProgress); + push(contextStackCursor, mergedContext, workInProgress); + } else pop(didPerformWorkStackCursor, workInProgress); + push(didPerformWorkStackCursor, didChange, workInProgress); + }, + findCurrentUnmaskedContext: function(fiber) { + for ( + invariant( + 2 === isFiberMountedImpl(fiber) && 2 === fiber.tag, + "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." + ); + 3 !== fiber.tag; + + ) { + if (isContextProvider(fiber)) + return fiber.stateNode.__reactInternalMemoizedMergedChildContext; + fiber = fiber["return"]; + invariant( + fiber, + "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." + ); + } + return fiber.stateNode.context; + } + }; +} +function ReactFiberNewContext(stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop, + providerCursor = createCursor(null), + valueCursor = createCursor(null), + changedBitsCursor = createCursor(0); + return { + pushProvider: function(providerFiber) { + var context = providerFiber.type._context; + push(changedBitsCursor, context._changedBits, providerFiber); + push(valueCursor, context._currentValue, providerFiber); + push(providerCursor, providerFiber, providerFiber); + context._currentValue = providerFiber.pendingProps.value; + context._changedBits = providerFiber.stateNode; + }, + popProvider: function(providerFiber) { + var changedBits = changedBitsCursor.current, + currentValue = valueCursor.current; + pop(providerCursor, providerFiber); + pop(valueCursor, providerFiber); + pop(changedBitsCursor, providerFiber); + providerFiber = providerFiber.type._context; + providerFiber._currentValue = currentValue; + providerFiber._changedBits = changedBits; } - index$1 = -1; + }; +} +function ReactFiberStack() { + var valueStack = [], + index = -1; + return { + createCursor: function(defaultValue) { + return { current: defaultValue }; + }, + isEmpty: function() { + return -1 === index; + }, + pop: function(cursor) { + 0 > index || + ((cursor.current = valueStack[index]), + (valueStack[index] = null), + index--); + }, + push: function(cursor, value) { + index++; + valueStack[index] = cursor.current; + cursor.current = value; + }, + checkThatStackIsEmpty: function() {}, + resetStackAfterFatalErrorInDev: function() {} + }; +} +function ReactFiberScheduler(config) { + function resetStack() { + if (null !== nextUnitOfWork) + for ( + var interruptedWork = nextUnitOfWork["return"]; + null !== interruptedWork; + + ) + unwindInterruptedWork(interruptedWork), + (interruptedWork = interruptedWork["return"]); nextRoot = null; nextRenderExpirationTime = 0; nextUnitOfWork = null; @@ -5101,7 +5286,7 @@ function ReactFiberScheduler(config) { workInProgress$jscomp$0 = unwindWork(workInProgress$jscomp$0); if (null !== workInProgress$jscomp$0) return ( - (workInProgress$jscomp$0.effectTag &= 511), workInProgress$jscomp$0 + (workInProgress$jscomp$0.effectTag &= 2559), workInProgress$jscomp$0 ); null !== returnFiber && ((returnFiber.firstEffect = returnFiber.lastEffect = null), @@ -5134,7 +5319,7 @@ function ReactFiberScheduler(config) { root !== nextRoot || null === nextUnitOfWork ) - resetContextStack(), + resetStack(), (nextRoot = root), (nextRenderExpirationTime = expirationTime), (nextUnitOfWork = createWorkInProgress( @@ -5264,8 +5449,8 @@ function ReactFiberScheduler(config) { !isWorking && 0 !== nextRenderExpirationTime && expirationTime < nextRenderExpirationTime && - resetContextStack(); - (nextRoot === root && isWorking) || + resetStack(); + (isWorking && !isCommitting && nextRoot === root) || requestWork(root, expirationTime); nestedUpdateCount > NESTED_UPDATE_LIMIT && invariant( @@ -5329,7 +5514,7 @@ function ReactFiberScheduler(config) { (nextFlushedExpirationTime = 1), performWorkOnRoot(root, 1, !1)) : 1 === expirationTime - ? performWork(1, !1, null) + ? performSyncWork() : scheduleCallbackWithExpiration(expirationTime)); } function findHighestPriorityRoot() { @@ -5389,6 +5574,9 @@ function ReactFiberScheduler(config) { function performAsyncWork(dl) { performWork(0, !0, dl); } + function performSyncWork() { + performWork(1, !1, null); + } function performWork(minExpirationTime, isAsync, dl) { deadline = dl; findHighestPriorityRoot(); @@ -5511,6 +5699,25 @@ function ReactFiberScheduler(config) { for (nextEffect = firstEffect; null !== nextEffect; ) { var didError = !1, error = void 0; + try { + for (; null !== nextEffect; ) + nextEffect.effectTag & 2048 && + commitBeforeMutationLifeCycles(nextEffect.alternate, nextEffect), + (nextEffect = nextEffect.nextEffect); + } catch (e) { + (didError = !0), (error = e); + } + didError && + (invariant( + null !== nextEffect, + "Should have next effect. This error is likely caused by a bug in React. Please file an issue." + ), + onCommitPhaseError(nextEffect, error), + null !== nextEffect && (nextEffect = nextEffect.nextEffect)); + } + for (nextEffect = firstEffect; null !== nextEffect; ) { + didError = !1; + error = void 0; try { for (; null !== nextEffect; ) { var effectTag = nextEffect.effectTag; @@ -5608,25 +5815,37 @@ function ReactFiberScheduler(config) { nextFlushedRoot.remainingExpirationTime = 0; hasUnhandledError || ((hasUnhandledError = !0), (unhandledError = error)); } - var hostContext = ReactFiberHostContext(config), - hydrationContext = ReactFiberHydrationContext(config), - resetHostContainer = hostContext.resetHostContainer, + var stack = ReactFiberStack(), + hostContext = ReactFiberHostContext(config, stack), + legacyContext = ReactFiberLegacyContext(stack); + stack = ReactFiberNewContext(stack); + var hydrationContext = ReactFiberHydrationContext(config), beginWork = ReactFiberBeginWork( config, hostContext, + legacyContext, + stack, hydrationContext, scheduleWork, computeExpirationForFiber ).beginWork, - completeWork = ReactFiberCompleteWork(config, hostContext, hydrationContext) - .completeWork; + completeWork = ReactFiberCompleteWork( + config, + hostContext, + legacyContext, + stack, + hydrationContext + ).completeWork; hostContext = ReactFiberUnwindWork( hostContext, + legacyContext, + stack, scheduleWork, isAlreadyFailedLegacyErrorBoundary ); var throwException = hostContext.throwException, - unwindWork = hostContext.unwindWork; + unwindWork = hostContext.unwindWork, + unwindInterruptedWork = hostContext.unwindInterruptedWork; hostContext = ReactFiberCommitWork( config, onCommitPhaseError, @@ -5639,7 +5858,9 @@ function ReactFiberScheduler(config) { }, recalculateCurrentTime ); - var commitResetTextContent = hostContext.commitResetTextContent, + var commitBeforeMutationLifeCycles = + hostContext.commitBeforeMutationLifeCycles, + commitResetTextContent = hostContext.commitResetTextContent, commitPlacement = hostContext.commitPlacement, commitDeletion = hostContext.commitDeletion, commitWork = hostContext.commitWork, @@ -5694,7 +5915,10 @@ function ReactFiberScheduler(config) { !isRendering, "work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method." ); + nextFlushedRoot = root; + nextFlushedExpirationTime = expirationTime; performWorkOnRoot(root, expirationTime, !1); + performSyncWork(); finishRendering(); }, batchedUpdates: function(fn, a) { @@ -5705,7 +5929,7 @@ function ReactFiberScheduler(config) { } finally { (isBatchingUpdates = previousIsBatchingUpdates) || isRendering || - performWork(1, !1, null); + performSyncWork(); } }, unbatchedUpdates: function(fn, a) { @@ -5729,8 +5953,7 @@ function ReactFiberScheduler(config) { try { return syncUpdates(fn, a); } finally { - (isBatchingUpdates = previousIsBatchingUpdates), - performWork(1, !1, null); + (isBatchingUpdates = previousIsBatchingUpdates), performSyncWork(); } }, flushControlled: function(fn) { @@ -5771,7 +5994,7 @@ function ReactFiberScheduler(config) { (isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates), (isBatchingUpdates = previousIsBatchingUpdates) || isRendering || - performWork(1, !1, null); + performSyncWork(); } }, flushInteractiveUpdates: function() { @@ -5785,7 +6008,8 @@ function ReactFiberScheduler(config) { result <= lastUniqueAsyncExpiration && (result = lastUniqueAsyncExpiration + 1); return (lastUniqueAsyncExpiration = result); - } + }, + legacyContext: legacyContext }; } function ReactFiberReconciler$1(config) { @@ -5800,27 +6024,7 @@ function ReactFiberReconciler$1(config) { currentTime = container.current; if (parentComponent) { parentComponent = parentComponent._reactInternalFiber; - var parentContext; - b: { - invariant( - 2 === isFiberMountedImpl(parentComponent) && - 2 === parentComponent.tag, - "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." - ); - for (parentContext = parentComponent; 3 !== parentContext.tag; ) { - if (isContextProvider(parentContext)) { - parentContext = - parentContext.stateNode.__reactInternalMemoizedMergedChildContext; - break b; - } - parentContext = parentContext["return"]; - invariant( - parentContext, - "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." - ); - } - parentContext = parentContext.stateNode.context; - } + var parentContext = findCurrentUnmaskedContext(parentComponent); parentComponent = isContextProvider(parentComponent) ? processChildContext(parentComponent, parentContext) : parentContext; @@ -5849,7 +6053,11 @@ function ReactFiberReconciler$1(config) { config = ReactFiberScheduler(config); var recalculateCurrentTime = config.recalculateCurrentTime, computeExpirationForFiber = config.computeExpirationForFiber, - scheduleWork = config.scheduleWork; + scheduleWork = config.scheduleWork, + legacyContext = config.legacyContext, + findCurrentUnmaskedContext = legacyContext.findCurrentUnmaskedContext, + isContextProvider = legacyContext.isContextProvider, + processChildContext = legacyContext.processChildContext; return { createContainer: function(containerInfo, isAsync, hydrate) { isAsync = new FiberNode(3, null, null, isAsync ? 3 : 0); @@ -6018,7 +6226,8 @@ var ReactFiberReconciler$2 = Object.freeze({ default: ReactFiberReconciler$1 }), frameDeadlineObject = { timeRemaining: function() { return frameDeadline - now(); - } + }, + didTimeout: !1 }; function setTimeoutCallback() { frameDeadline = now() + 5; @@ -6352,7 +6561,7 @@ NativeRenderer.injectIntoDevTools({ findFiberByHostInstance: getInstanceFromTag, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.3.0-alpha.1", + version: "16.3.1", rendererPackageName: "react-native-renderer" }); var ReactNativeRenderer$2 = Object.freeze({ default: ReactNativeRenderer }), diff --git a/Libraries/Renderer/shims/ReactTypes.js b/Libraries/Renderer/shims/ReactTypes.js index bede9f00e30069..87a769a148c95d 100644 --- a/Libraries/Renderer/shims/ReactTypes.js +++ b/Libraries/Renderer/shims/ReactTypes.js @@ -62,7 +62,7 @@ export type ReactProvider = { export type ReactProviderType = { $$typeof: Symbol | number, - context: ReactContext, + _context: ReactContext, }; export type ReactConsumer = { @@ -72,7 +72,7 @@ export type ReactConsumer = { ref: null, props: { children: (value: T) => ReactNodeList, - bits?: number, + unstable_observedBits?: number, }, }; diff --git a/package.json b/package.json index 8dda61d84ae124..4f4f558451100f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.55.0", + "version": "1000.0.0", "description": "A framework for building native apps using React", "license": "MIT", "repository": { @@ -127,22 +127,22 @@ "lint": "eslint .", "prettier": "find . -name node_modules -prune -or -name '*.js' -print | xargs prettier --write", "start": "/usr/bin/env bash -c './scripts/packager.sh \"$@\" || true' --", - "test-android-setup": "docker pull hramos/android-base:latest", - "test-android-build-base": "docker build -t hramos/android-base -f ContainerShip/Dockerfile.android-base .", - "test-android-build": "docker build -t react/android -f ContainerShip/Dockerfile.android .", + "docker-setup-android": "docker pull hramos/android-base:latest", + "docker-build-android-base": "docker build -t hramos/android-base -f ContainerShip/Dockerfile.android-base .", + "docker-build-android": "docker build -t react/android -f ContainerShip/Dockerfile.android .", "test-android-run-instrumentation": "docker run --cap-add=SYS_ADMIN -it react/android bash ContainerShip/scripts/run-android-docker-instrumentation-tests.sh", "test-android-run-unit": "docker run --cap-add=SYS_ADMIN -it react/android bash ContainerShip/scripts/run-android-docker-unit-tests.sh", "test-android-run-e2e": "docker run --privileged -it react/android bash ContainerShip/scripts/run-ci-e2e-tests.sh --android --js", - "test-android-all": "npm run test-android-build && npm run test-android-run-unit && npm run test-android-run-instrumentation && npm run test-android-run-e2e", - "test-android-instrumentation": "npm run test-android-build && npm run test-android-run-instrumentation", - "test-android-unit": "npm run test-android-build && npm run test-android-run-unit", - "test-android-e2e": "npm run test-android-build && npm run test-android-run-e2e" + "test-android-all": "yarn run docker-build-android && yarn run test-android-run-unit && yarn run test-android-run-instrumentation && yarn run test-android-run-e2e", + "test-android-instrumentation": "yarn run docker-build-android && yarn run test-android-run-instrumentation", + "test-android-unit": "yarn run docker-build-android && yarn run test-android-run-unit", + "test-android-e2e": "yarn run docker-build-android && yarn run test-android-run-e2e" }, "bin": { "react-native": "local-cli/wrong-react-native.js" }, "peerDependencies": { - "react": "^16.3.0-alpha.0" + "react": "16.3.1" }, "dependencies": { "absolute-path": "^0.0.0", @@ -175,8 +175,8 @@ "graceful-fs": "^4.1.3", "inquirer": "^3.0.6", "lodash": "^4.17.5", - "metro": "^0.30.0", - "metro-core": "^0.30.0", + "metro": "^0.31.0", + "metro-core": "^0.31.0", "mime": "^1.3.4", "minimist": "^1.2.0", "mkdirp": "^0.5.1", @@ -215,13 +215,13 @@ "eslint-plugin-jest": "21.8.0", "eslint-plugin-prettier": "2.6.0", "eslint-plugin-react": "7.6.1", - "flow-bin": "^0.67.1", - "jest": "22.4.2", + "flow-bin": "^0.69.0", + "jest": "23.0.0-alpha.4", "jest-junit": "3.6.0", "prettier": "1.9.1", - "react": "^16.3.0-alpha.1", - "react-test-renderer": "^16.3.0-alpha.1", + "react": "16.3.1", + "react-test-renderer": "16.3.1", "shelljs": "^0.7.8", "sinon": "^2.2.0" } -} \ No newline at end of file +}