diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index 824ff8c33a4..fc81a7c7f28 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 867873cd41d..0b7a78516c1 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,876 +4146,6 @@ function findCurrentHostFiberWithNoPortals(parent) { return null; } -var valueStack = []; - -var fiberStack = void 0; - -{ - fiberStack = []; -} - -var index = -1; - -function createCursor(defaultValue) { - return { - current: defaultValue - }; -} - -function pop(cursor, fiber) { - if (index < 0) { - { - warning(false, "Unexpected pop."); - } - return; - } - - { - if (fiber !== fiberStack[index]) { - warning(false, "Unexpected Fiber popped."); - } - } - - cursor.current = valueStack[index]; - - valueStack[index] = null; - - { - fiberStack[index] = null; - } - - index--; -} - -function push(cursor, value, fiber) { - index++; - - valueStack[index] = cursor.current; - - { - fiberStack[index] = fiber; - } - - cursor.current = value; -} - -function reset() { - while (index > -1) { - valueStack[index] = null; - - { - fiberStack[index] = null; - } - - index--; - } -} - -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 ""; - } -} - -// 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 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; -} - -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 resetCurrentFiber() { - ReactDebugCurrentFrame.getCurrentStack = null; - ReactDebugCurrentFiber.current = null; - ReactDebugCurrentFiber.phase = null; -} - -function setCurrentFiber(fiber) { - ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; - ReactDebugCurrentFiber.current = fiber; - ReactDebugCurrentFiber.phase = null; -} - -function setCurrentPhase(phase) { - ReactDebugCurrentFiber.phase = phase; -} - -var ReactDebugCurrentFiber = { - current: null, - phase: null, - resetCurrentFiber: resetCurrentFiber, - setCurrentFiber: setCurrentFiber, - setCurrentPhase: setCurrentPhase, - getCurrentFiberOwnerName: getCurrentFiberOwnerName, - getCurrentFiberStackAddendum: getCurrentFiberStackAddendum -}; - -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; - -// Only used in www builds. - -// 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"; - -// 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(); - -var formatMarkName = function(markName) { - return reactEmoji + " " + markName; -}; - -var formatLabel = function(label, warning$$1) { - var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; - var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; - return "" + prefix + label + suffix; -}; - -var beginMark = function(markName) { - performance.mark(formatMarkName(markName)); -}; - -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. - 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"]; - } -}; - -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++; - } -} - -function recordScheduleUpdate() { - if (enableUserTimingAPI) { - if (isCommitting) { - hasScheduledUpdateInCurrentCommit = true; - } - if ( - currentPhase !== null && - currentPhase !== "componentWillMount" && - currentPhase !== "componentWillReceiveProps" - ) { - hasScheduledUpdateInCurrentPhase = true; - } - } -} - -function startRequestCallbackTimer() { - if (enableUserTimingAPI) { - if (supportsUserTiming && !isWaitingForCallback) { - isWaitingForCallback = true; - beginMark("(Waiting for async callback...)"); - } - } -} - -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 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 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 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); - } -} - -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 - ); - } -} - -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; - } - 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 warnedAboutMissingGetChildContext = void 0; - -{ - 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; -} - -function cacheContext(workInProgress, unmaskedContext, maskedContext) { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; - instance.__reactInternalMemoizedMaskedChildContext = maskedContext; -} - -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 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." - ); - - push(contextStackCursor, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); -} - -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 pushContextProvider(workInProgress) { - if (!isContextProvider(workInProgress)) { - return false; - } - - 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 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) { - // 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 resetContext() { - previousContext = emptyObject; - contextStackCursor.current = emptyObject; - didPerformWorkStackCursor.current = false; -} - -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; -} - // Max 31 bit integer. The max integer size in V8 for 32-bit systems. // Math.pow(2, 30) - 1 // 0b111111111111111111111111111111 @@ -5242,6 +4388,9 @@ function createFiberFromElement(element, mode, expirationTime) { // 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 @@ -5339,6 +4488,47 @@ function createFiberFromPortal(portal, mode, expirationTime) { return fiber; } +// 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; +} + // TODO: This should be lifted into the renderer. function createFiberRoot(containerInfo, isAsync, hydrate) { @@ -5434,6 +4624,53 @@ function onCommitUnmount(fiber) { } } +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 ""; + } +} + +// 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; +} + /** * Forked from fbjs/warning: * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js @@ -5697,7 +4934,10 @@ var ReactStrictModeWarnings = { ) { pendingComponentWillReceivePropsWarnings.push(fiber); } - if (typeof instance.componentWillUpdate === "function") { + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { pendingComponentWillUpdateWarnings.push(fiber); } }; @@ -5768,6 +5008,529 @@ var ReactStrictModeWarnings = { }; } +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; + +// 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; +} + +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 resetCurrentFiber() { + ReactDebugCurrentFrame.getCurrentStack = null; + ReactDebugCurrentFiber.current = null; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentFiber(fiber) { + ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; + ReactDebugCurrentFiber.current = fiber; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentPhase(phase) { + ReactDebugCurrentFiber.phase = phase; +} + +var ReactDebugCurrentFiber = { + current: null, + phase: null, + resetCurrentFiber: resetCurrentFiber, + setCurrentFiber: setCurrentFiber, + setCurrentPhase: setCurrentPhase, + getCurrentFiberOwnerName: getCurrentFiberOwnerName, + getCurrentFiberStackAddendum: getCurrentFiberStackAddendum +}; + +// 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"; + +// 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(); + +var formatMarkName = function(markName) { + return reactEmoji + " " + markName; +}; + +var formatLabel = function(label, warning$$1) { + var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; + var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; + return "" + prefix + label + suffix; +}; + +var beginMark = function(markName) { + performance.mark(formatMarkName(markName)); +}; + +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. + 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"]; + } +}; + +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++; + } +} + +function recordScheduleUpdate() { + if (enableUserTimingAPI) { + if (isCommitting) { + hasScheduledUpdateInCurrentCommit = true; + } + if ( + currentPhase !== null && + currentPhase !== "componentWillMount" && + currentPhase !== "componentWillReceiveProps" + ) { + hasScheduledUpdateInCurrentPhase = true; + } + } +} + +function startRequestCallbackTimer() { + if (enableUserTimingAPI) { + if (supportsUserTiming && !isWaitingForCallback) { + isWaitingForCallback = true; + beginMark("(Waiting for async callback...)"); + } + } +} + +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 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 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 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); + } +} + +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, didCompleteRoot) { + 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; + 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); + } +} + +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 startCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Committing Snapshot Effects)"); + } +} + +function stopCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Committing Snapshot Effects: " + count + " Total)", + "(Committing Snapshot Effects)", + null + ); + } +} + +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; + } + 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 didWarnUpdateInsideUpdate = void 0; { @@ -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 - ); + !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,6 +10170,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; @@ -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 @@ -10866,8 +10921,8 @@ var ReactFiberCommitWork = function( return; } case HostComponent: { - var _instance7 = finishedWork.stateNode; - if (_instance7 != null) { + 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 @@ -10880,7 +10935,7 @@ var ReactFiberCommitWork = function( finishedWork.updateQueue = null; if (updatePayload !== null) { commitUpdate( - _instance7, + _instance8, updatePayload, type, oldProps, @@ -10925,6 +10980,7 @@ var ReactFiberCommitWork = function( if (enableMutatingReconciler) { return { + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, commitResetTextContent: commitResetTextContent, commitPlacement: commitPlacement, commitDeletion: commitDeletion, @@ -10941,9 +10997,12 @@ var ReactFiberCommitWork = function( var NO_CONTEXT = {}; -var ReactFiberHostContext = function(config) { +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); @@ -10967,12 +11026,19 @@ var ReactFiberHostContext = function(config) { // 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); + + // 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); } @@ -11014,19 +11080,13 @@ var ReactFiberHostContext = function(config) { pop(contextFiberStackCursor, fiber); } - function resetHostContainer() { - contextStackCursor.current = NO_CONTEXT; - rootInstanceStackCursor.current = NO_CONTEXT; - } - return { getHostContext: getHostContext, getRootHostContainer: getRootHostContainer, popHostContainer: popHostContainer, popHostContext: popHostContext, pushHostContainer: pushHostContainer, - pushHostContext: pushHostContext, - resetHostContainer: resetHostContainer + pushHostContext: pushHostContext }; }; @@ -11396,6 +11456,429 @@ var ReactFiberInstrumentation = { 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 cacheContext(workInProgress, unmaskedContext, maskedContext) { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; + } + + 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 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." + ); + + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); + } + + 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 pushContextProvider(workInProgress) { + if (!isContextProvider(workInProgress)) { + return false; + } + + 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 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) { + // 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 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 { + 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 ReactFiberNewContext = function(stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop; + + var providerCursor = createCursor(null); + var valueCursor = createCursor(null); + var changedBitsCursor = createCursor(0); + + var rendererSigil = void 0; + { + // Use this to detect multiple renderers using the same context + rendererSigil = {}; + } + + function pushProvider(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; + + { + !( + 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; + } + } + + function popProvider(providerFiber) { + var changedBits = changedBitsCursor.current; + var currentValue = valueCursor.current; + + pop(providerCursor, providerFiber); + pop(valueCursor, providerFiber); + pop(changedBitsCursor, providerFiber); + + var context = providerFiber.type._context; + context._currentValue = currentValue; + context._changedBits = changedBits; + } + + return { + pushProvider: pushProvider, + popProvider: popProvider + }; +}; + +var ReactFiberStack = function() { + var valueStack = []; + + var fiberStack = void 0; + + { + fiberStack = []; + } + + var index = -1; + + function createCursor(defaultValue) { + return { + current: defaultValue + }; + } + + function isEmpty() { + return index === -1; + } + + function pop(cursor, fiber) { + if (index < 0) { + { + warning(false, "Unexpected pop."); + } + return; + } + + { + if (fiber !== fiberStack[index]) { + warning(false, "Unexpected Fiber popped."); + } + } + + cursor.current = valueStack[index]; + + valueStack[index] = null; + + { + fiberStack[index] = null; + } + + index--; + } + + function push(cursor, value, fiber) { + index++; + + valueStack[index] = cursor.current; + + { + fiberStack[index] = fiber; + } + + cursor.current = value; + } + + function checkThatStackIsEmpty() { + { + if (index !== -1) { + warning( + false, + "Expected an empty stack. Something was not reset properly." + ); + } + } + } + + function resetStackAfterFatalErrorInDev() { + { + index = -1; + valueStack.length = 0; + fiberStack.length = 0; + } + } + + return { + createCursor: createCursor, + isEmpty: isEmpty, + pop: pop, + push: push, + checkThatStackIsEmpty: checkThatStackIsEmpty, + resetStackAfterFatalErrorInDev: resetStackAfterFatalErrorInDev + }; +}; + 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 950e09890f8..c12ebd601c8 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; } - index$1 = -1; + }; +} +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; + } + }; +} +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 400472d29a3..7fd62f11ca6 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,879 +4400,6 @@ function findCurrentHostFiberWithNoPortals(parent) { return null; } -var valueStack = []; - -var fiberStack = void 0; - -{ - fiberStack = []; -} - -var index = -1; - -function createCursor(defaultValue) { - return { - current: defaultValue - }; -} - -function pop(cursor, fiber) { - if (index < 0) { - { - warning(false, "Unexpected pop."); - } - return; - } - - { - if (fiber !== fiberStack[index]) { - warning(false, "Unexpected Fiber popped."); - } - } - - cursor.current = valueStack[index]; - - valueStack[index] = null; - - { - fiberStack[index] = null; - } - - index--; -} - -function push(cursor, value, fiber) { - index++; - - valueStack[index] = cursor.current; - - { - fiberStack[index] = fiber; - } - - cursor.current = value; -} - -function reset() { - while (index > -1) { - valueStack[index] = null; - - { - fiberStack[index] = null; - } - - index--; - } -} - -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 ""; - } -} - -// 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 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; -} - -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 resetCurrentFiber() { - ReactDebugCurrentFrame.getCurrentStack = null; - ReactDebugCurrentFiber.current = null; - ReactDebugCurrentFiber.phase = null; -} - -function setCurrentFiber(fiber) { - ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; - ReactDebugCurrentFiber.current = fiber; - ReactDebugCurrentFiber.phase = null; -} - -function setCurrentPhase(phase) { - ReactDebugCurrentFiber.phase = phase; -} - -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. - -// 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"; - -// 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(); - -var formatMarkName = function(markName) { - return reactEmoji + " " + markName; -}; - -var formatLabel = function(label, warning$$1) { - var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; - var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; - return "" + prefix + label + suffix; -}; - -var beginMark = function(markName) { - performance.mark(formatMarkName(markName)); -}; - -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. - 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"]; - } -}; - -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++; - } -} - -function recordScheduleUpdate() { - if (enableUserTimingAPI) { - if (isCommitting) { - hasScheduledUpdateInCurrentCommit = true; - } - if ( - currentPhase !== null && - currentPhase !== "componentWillMount" && - currentPhase !== "componentWillReceiveProps" - ) { - hasScheduledUpdateInCurrentPhase = true; - } - } -} - -function startRequestCallbackTimer() { - if (enableUserTimingAPI) { - if (supportsUserTiming && !isWaitingForCallback) { - isWaitingForCallback = true; - beginMark("(Waiting for async callback...)"); - } - } -} - -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 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 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 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); - } -} - -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 - ); - } -} - -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; - } - 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 warnedAboutMissingGetChildContext = void 0; - -{ - 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; -} - -function cacheContext(workInProgress, unmaskedContext, maskedContext) { - var instance = workInProgress.stateNode; - instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; - instance.__reactInternalMemoizedMaskedChildContext = maskedContext; -} - -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 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." - ); - - push(contextStackCursor, context, fiber); - push(didPerformWorkStackCursor, didChange, fiber); -} - -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 pushContextProvider(workInProgress) { - if (!isContextProvider(workInProgress)) { - return false; - } - - 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 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) { - // 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 resetContext() { - previousContext = emptyObject; - contextStackCursor.current = emptyObject; - didPerformWorkStackCursor.current = false; -} - -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; -} - // Max 31 bit integer. The max integer size in V8 for 32-bit systems. // Math.pow(2, 30) - 1 // 0b111111111111111111111111111111 @@ -5500,6 +4642,9 @@ function createFiberFromElement(element, mode, expirationTime) { // 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 @@ -5597,6 +4742,47 @@ function createFiberFromPortal(portal, mode, expirationTime) { return fiber; } +// 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; +} + // TODO: This should be lifted into the renderer. function createFiberRoot(containerInfo, isAsync, hydrate) { @@ -5692,6 +4878,53 @@ function onCommitUnmount(fiber) { } } +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 ""; + } +} + +// 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; +} + /** * Forked from fbjs/warning: * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js @@ -5955,7 +5188,10 @@ var ReactStrictModeWarnings = { ) { pendingComponentWillReceivePropsWarnings.push(fiber); } - if (typeof instance.componentWillUpdate === "function") { + if ( + typeof instance.componentWillUpdate === "function" && + instance.componentWillUpdate.__suppressDeprecationWarning !== true + ) { pendingComponentWillUpdateWarnings.push(fiber); } }; @@ -6026,6 +5262,533 @@ var ReactStrictModeWarnings = { }; } +// 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 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; +} + +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 resetCurrentFiber() { + ReactDebugCurrentFrame.getCurrentStack = null; + ReactDebugCurrentFiber.current = null; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentFiber(fiber) { + ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; + ReactDebugCurrentFiber.current = fiber; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentPhase(phase) { + ReactDebugCurrentFiber.phase = phase; +} + +var ReactDebugCurrentFiber = { + current: null, + phase: null, + resetCurrentFiber: resetCurrentFiber, + setCurrentFiber: setCurrentFiber, + setCurrentPhase: setCurrentPhase, + getCurrentFiberOwnerName: getCurrentFiberOwnerName, + getCurrentFiberStackAddendum: getCurrentFiberStackAddendum +}; + +// 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"; + +// 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(); + +var formatMarkName = function(markName) { + return reactEmoji + " " + markName; +}; + +var formatLabel = function(label, warning$$1) { + var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " "; + var suffix = warning$$1 ? " Warning: " + warning$$1 : ""; + return "" + prefix + label + suffix; +}; + +var beginMark = function(markName) { + performance.mark(formatMarkName(markName)); +}; + +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. + 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"]; + } +}; + +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++; + } +} + +function recordScheduleUpdate() { + if (enableUserTimingAPI) { + if (isCommitting) { + hasScheduledUpdateInCurrentCommit = true; + } + if ( + currentPhase !== null && + currentPhase !== "componentWillMount" && + currentPhase !== "componentWillReceiveProps" + ) { + hasScheduledUpdateInCurrentPhase = true; + } + } +} + +function startRequestCallbackTimer() { + if (enableUserTimingAPI) { + if (supportsUserTiming && !isWaitingForCallback) { + isWaitingForCallback = true; + beginMark("(Waiting for async callback...)"); + } + } +} + +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 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 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 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); + } +} + +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, didCompleteRoot) { + 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; + 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); + } +} + +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 startCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + effectCountInCurrentCommit = 0; + beginMark("(Committing Snapshot Effects)"); + } +} + +function stopCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return; + } + var count = effectCountInCurrentCommit; + effectCountInCurrentCommit = 0; + endMark( + "(Committing Snapshot Effects: " + count + " Total)", + "(Committing Snapshot Effects)", + null + ); + } +} + +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; + } + 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 didWarnUpdateInsideUpdate = void 0; { @@ -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,7 +10552,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." + ); } } } @@ -10583,50 +10618,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). @@ -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 @@ -11158,8 +11213,8 @@ var ReactFiberCommitWork = function( return; } case HostComponent: { - var _instance7 = finishedWork.stateNode; - if (_instance7 != null) { + 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 @@ -11172,7 +11227,7 @@ var ReactFiberCommitWork = function( finishedWork.updateQueue = null; if (updatePayload !== null) { commitUpdate( - _instance7, + _instance8, updatePayload, type, oldProps, @@ -11217,6 +11272,7 @@ var ReactFiberCommitWork = function( if (enableMutatingReconciler) { return { + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, commitResetTextContent: commitResetTextContent, commitPlacement: commitPlacement, commitDeletion: commitDeletion, @@ -11233,9 +11289,12 @@ var ReactFiberCommitWork = function( var NO_CONTEXT = {}; -var ReactFiberHostContext = function(config) { +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); @@ -11259,12 +11318,19 @@ var ReactFiberHostContext = function(config) { // 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); + + // 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); } @@ -11306,19 +11372,13 @@ var ReactFiberHostContext = function(config) { pop(contextFiberStackCursor, fiber); } - function resetHostContainer() { - contextStackCursor.current = NO_CONTEXT; - rootInstanceStackCursor.current = NO_CONTEXT; - } - return { getHostContext: getHostContext, getRootHostContainer: getRootHostContainer, popHostContainer: popHostContainer, popHostContext: popHostContext, pushHostContainer: pushHostContainer, - pushHostContext: pushHostContext, - resetHostContainer: resetHostContainer + pushHostContext: pushHostContext }; }; @@ -11688,6 +11748,429 @@ var ReactFiberInstrumentation = { 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 cacheContext(workInProgress, unmaskedContext, maskedContext) { + var instance = workInProgress.stateNode; + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; + instance.__reactInternalMemoizedMaskedChildContext = maskedContext; + } + + 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 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." + ); + + push(contextStackCursor, context, fiber); + push(didPerformWorkStackCursor, didChange, fiber); + } + + 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 pushContextProvider(workInProgress) { + if (!isContextProvider(workInProgress)) { + return false; + } + + 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 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) { + // 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 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 { + 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 ReactFiberNewContext = function(stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop; + + var providerCursor = createCursor(null); + var valueCursor = createCursor(null); + var changedBitsCursor = createCursor(0); + + var rendererSigil = void 0; + { + // Use this to detect multiple renderers using the same context + rendererSigil = {}; + } + + function pushProvider(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; + + { + !( + 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; + } + } + + function popProvider(providerFiber) { + var changedBits = changedBitsCursor.current; + var currentValue = valueCursor.current; + + pop(providerCursor, providerFiber); + pop(valueCursor, providerFiber); + pop(changedBitsCursor, providerFiber); + + var context = providerFiber.type._context; + context._currentValue = currentValue; + context._changedBits = changedBits; + } + + return { + pushProvider: pushProvider, + popProvider: popProvider + }; +}; + +var ReactFiberStack = function() { + var valueStack = []; + + var fiberStack = void 0; + + { + fiberStack = []; + } + + var index = -1; + + function createCursor(defaultValue) { + return { + current: defaultValue + }; + } + + function isEmpty() { + return index === -1; + } + + function pop(cursor, fiber) { + if (index < 0) { + { + warning(false, "Unexpected pop."); + } + return; + } + + { + if (fiber !== fiberStack[index]) { + warning(false, "Unexpected Fiber popped."); + } + } + + cursor.current = valueStack[index]; + + valueStack[index] = null; + + { + fiberStack[index] = null; + } + + index--; + } + + function push(cursor, value, fiber) { + index++; + + valueStack[index] = cursor.current; + + { + fiberStack[index] = fiber; + } + + cursor.current = value; + } + + function checkThatStackIsEmpty() { + { + if (index !== -1) { + warning( + false, + "Expected an empty stack. Something was not reset properly." + ); + } + } + } + + function resetStackAfterFatalErrorInDev() { + { + index = -1; + valueStack.length = 0; + fiberStack.length = 0; + } + } + + return { + createCursor: createCursor, + isEmpty: isEmpty, + pop: pop, + push: push, + checkThatStackIsEmpty: checkThatStackIsEmpty, + resetStackAfterFatalErrorInDev: resetStackAfterFatalErrorInDev + }; +}; + 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 ca27b720b33..055ddd7bb0c 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; } - index$1 = -1; + }; +} +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; + } + }; +} +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 bede9f00e30..87a769a148c 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 8dda61d84ae..4f4f5584511 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 +}