From cd938d731c7531a683c050cd829a543d145e3dc1 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 29 Nov 2017 10:12:57 -0800 Subject: [PATCH] React sync for revisions 2d23a45...9491dee Reviewed By: flarnie Differential Revision: D6436328 fbshipit-source-id: 370b862c23c9804bd6df72812d08baceaebfca78 --- Libraries/Renderer/REVISION | 2 +- Libraries/Renderer/ReactNativeRenderer-dev.js | 695 +++++---- .../Renderer/ReactNativeRenderer-prod.js | 1258 +++++++++-------- Libraries/Renderer/shims/ReactFeatureFlags.js | 16 + package.json | 6 +- 5 files changed, 1048 insertions(+), 929 deletions(-) create mode 100644 Libraries/Renderer/shims/ReactFeatureFlags.js diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index 75daa905d..3b4141767 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -2d23a4563ef2bec7d90c4a7edff2657c890b4334 \ No newline at end of file +9491dee79586d21c115cd4d5986c81b7d88d2b3f \ No newline at end of file diff --git a/Libraries/Renderer/ReactNativeRenderer-dev.js b/Libraries/Renderer/ReactNativeRenderer-dev.js index 26ed7534d..cdcf5115e 100644 --- a/Libraries/Renderer/ReactNativeRenderer-dev.js +++ b/Libraries/Renderer/ReactNativeRenderer-dev.js @@ -179,6 +179,22 @@ var invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) { e, f ) { + // If document doesn't exist we know for sure we will crash in this method + // when we call document.createEvent(). However this can cause confusing + // errors: https://github.com/facebookincubator/create-react-app/issues/3482 + // So we preemptively throw with a better message instead. + invariant( + typeof document !== "undefined", + "The `document` global was defined when React was initialized, but is not " + + "defined anymore. This can happen in a test environment if a component " + + "schedules an update from an asynchronous callback, but the test has already " + + "finished running. To solve this, you can either unmount the component at " + + "the end of your test (and ensure that any asynchronous operations get " + + "canceled in `componentWillUnmount`), or you can change the test itself " + + "to be asynchronous." + ); + var evt = document.createEvent("Event"); + // Keeps track of whether the user-provided callback threw an error. We // set this to true at the beginning, then set it to false right after // calling the function. If the function errors, `didError` will never be @@ -234,7 +250,6 @@ var invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) { // Synchronously dispatch our fake event. If the user-provided function // errors, it will trigger our global error handler. - var evt = document.createEvent("Event"); evt.initEvent(evtType, false, false); fakeNode.dispatchEvent(evt); @@ -393,13 +408,11 @@ function publishRegistrationName(registrationName, pluginModule, eventName) { registrationName ); registrationNameModules[registrationName] = pluginModule; + registrationNameDependencies[registrationName] = + pluginModule.eventTypes[eventName].dependencies; + { var lowerCasedName = registrationName.toLowerCase(); - possibleRegistrationNames[lowerCasedName] = registrationName; - - if (registrationName === "onDoubleClick") { - possibleRegistrationNames.ondblclick = registrationName; - } } } @@ -427,6 +440,7 @@ var registrationNameModules = {}; /** * Mapping from registration name to event name */ +var registrationNameDependencies = {}; /** * Mapping from lowercase registration names to the properly cased version, @@ -434,7 +448,7 @@ var registrationNameModules = {}; * only in true. * @type {Object} */ -var possibleRegistrationNames = {}; + // Trust the developer to only use possibleRegistrationNames in true /** @@ -919,6 +933,11 @@ function processEventQueue(simulated) { // events get enqueued while processing. var processingEventQueue = eventQueue; eventQueue = null; + + if (!processingEventQueue) { + return; + } + if (simulated) { forEachAccumulated( processingEventQueue, @@ -2796,6 +2815,12 @@ function logCapturedError(capturedError) { return; } + var error = capturedError.error; + var suppressLogging = error && error.suppressReactErrorLogging; + if (suppressLogging) { + return; + } + { var componentName = capturedError.componentName, componentStack = capturedError.componentStack, @@ -2859,13 +2884,31 @@ var injection$4 = { } }; -// The Symbol used to tag the special React types. If there is no native Symbol +// The Symbol used to tag the ReactElement-like types. If there is no native Symbol // nor polyfill, then a plain number is used for performance. -var REACT_PORTAL_TYPE = - (typeof Symbol === "function" && - Symbol["for"] && - Symbol["for"]("react.portal")) || - 0xeaca; +var hasSymbol = typeof Symbol === "function" && Symbol["for"]; + +var REACT_ELEMENT_TYPE = hasSymbol ? Symbol["for"]("react.element") : 0xeac7; +var REACT_CALL_TYPE = hasSymbol ? Symbol["for"]("react.call") : 0xeac8; +var REACT_RETURN_TYPE = hasSymbol ? Symbol["for"]("react.return") : 0xeac9; +var REACT_PORTAL_TYPE = hasSymbol ? Symbol["for"]("react.portal") : 0xeaca; +var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol["for"]("react.fragment") : 0xeacb; + +var MAYBE_ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; +var FAUX_ITERATOR_SYMBOL = "@@iterator"; + +function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable === "undefined") { + return null; + } + var maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; + if (typeof maybeIterator === "function") { + return maybeIterator; + } + return null; +} function createPortal( children, @@ -3041,7 +3084,7 @@ var ReactGlobalSharedState = Object.freeze({ // TODO: this is special because it gets imported during build. -var ReactVersion = "16.1.1"; +var ReactVersion = "16.2.0"; // Module provided by RN: /** @@ -3685,19 +3728,16 @@ function getComponentName(fiber) { return null; } +// Re-export dynamic flags from the fbsource version. +var _require = require("ReactFeatureFlags"); + +var debugRenderPhaseSideEffects = _require.debugRenderPhaseSideEffects; + var enableAsyncSubtreeAPI = true; -// Exports React.Fragment -var enableReactFragment = false; -// Exports ReactDOM.createRoot - var enableUserTimingAPI = true; - -// Mutating mode (React DOM, React ART, React Native): var enableMutatingReconciler = true; -// Experimental noop mode (currently unused): var enableNoopReconciler = false; -// Experimental persistent mode (CS): var enablePersistentReconciler = false; // Only used in www builds. @@ -4840,6 +4880,10 @@ function msToExpirationTime(ms) { return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET; } +function expirationTimeToMs(expirationTime) { + return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE; +} + function ceiling(num, precision) { return (((num / precision) | 0) + 1) * precision; } @@ -4859,8 +4903,7 @@ var AsyncUpdates = 1; try { var nonExtensibleObject = Object.preventExtensions({}); /* eslint-disable no-new */ - new Map([[nonExtensibleObject, null]]); - new Set([nonExtensibleObject]); + /* eslint-enable no-new */ } catch (e) { // TODO: Consider warning about bad polyfills @@ -4875,7 +4918,7 @@ var AsyncUpdates = 1; var debugCounter = 1; } -function FiberNode(tag, key, internalContextTag) { +function FiberNode(tag, pendingProps, key, internalContextTag) { // Instance this.tag = tag; this.key = key; @@ -4890,7 +4933,7 @@ function FiberNode(tag, key, internalContextTag) { this.ref = null; - this.pendingProps = null; + this.pendingProps = pendingProps; this.memoizedProps = null; this.updateQueue = null; this.memoizedState = null; @@ -4932,9 +4975,9 @@ function FiberNode(tag, key, internalContextTag) { // is faster. // 5) It should be easy to port this to a C struct and keep a C implementation // compatible. -var createFiber = function(tag, key, internalContextTag) { +var createFiber = function(tag, pendingProps, key, internalContextTag) { // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors - return new FiberNode(tag, key, internalContextTag); + return new FiberNode(tag, pendingProps, key, internalContextTag); }; function shouldConstruct(Component) { @@ -4952,6 +4995,7 @@ function createWorkInProgress(current, pendingProps, expirationTime) { // reclaim the extra memory if needed. workInProgress = createFiber( current.tag, + pendingProps, current.key, current.internalContextTag ); @@ -4968,6 +5012,8 @@ function createWorkInProgress(current, pendingProps, expirationTime) { workInProgress.alternate = current; current.alternate = workInProgress; } else { + workInProgress.pendingProps = pendingProps; + // We already have an alternate. // Reset the effect tag. workInProgress.effectTag = NoEffect; @@ -4979,7 +5025,6 @@ function createWorkInProgress(current, pendingProps, expirationTime) { } workInProgress.expirationTime = expirationTime; - workInProgress.pendingProps = pendingProps; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; @@ -5006,19 +5051,22 @@ function createFiberFromElement(element, internalContextTag, expirationTime) { } var fiber = void 0; - var type = element.type, - key = element.key; - + var type = element.type; + var key = element.key; + var pendingProps = element.props; if (typeof type === "function") { fiber = shouldConstruct(type) - ? createFiber(ClassComponent, key, internalContextTag) - : createFiber(IndeterminateComponent, key, internalContextTag); + ? createFiber(ClassComponent, pendingProps, key, internalContextTag) + : createFiber( + IndeterminateComponent, + pendingProps, + key, + internalContextTag + ); fiber.type = type; - fiber.pendingProps = element.props; } else if (typeof type === "string") { - fiber = createFiber(HostComponent, key, internalContextTag); + fiber = createFiber(HostComponent, pendingProps, key, internalContextTag); fiber.type = type; - fiber.pendingProps = element.props; } else if ( typeof type === "object" && type !== null && @@ -5031,7 +5079,7 @@ function createFiberFromElement(element, internalContextTag, expirationTime) { // we don't know if we can reuse that fiber or if we need to clone it. // There is probably a clever way to restructure this. fiber = type; - fiber.pendingProps = element.props; + fiber.pendingProps = pendingProps; } else { var info = ""; { @@ -5075,42 +5123,44 @@ function createFiberFromFragment( expirationTime, key ) { - var fiber = createFiber(Fragment, key, internalContextTag); - fiber.pendingProps = elements; + var fiber = createFiber(Fragment, elements, key, internalContextTag); fiber.expirationTime = expirationTime; return fiber; } function createFiberFromText(content, internalContextTag, expirationTime) { - var fiber = createFiber(HostText, null, internalContextTag); - fiber.pendingProps = content; + var fiber = createFiber(HostText, content, null, internalContextTag); fiber.expirationTime = expirationTime; return fiber; } function createFiberFromHostInstanceForDeletion() { - var fiber = createFiber(HostComponent, null, NoContext); + var fiber = createFiber(HostComponent, null, null, NoContext); fiber.type = "DELETED"; return fiber; } function createFiberFromCall(call, internalContextTag, expirationTime) { - var fiber = createFiber(CallComponent, call.key, internalContextTag); + var fiber = createFiber(CallComponent, call, call.key, internalContextTag); fiber.type = call.handler; - fiber.pendingProps = call; fiber.expirationTime = expirationTime; return fiber; } function createFiberFromReturn(returnNode, internalContextTag, expirationTime) { - var fiber = createFiber(ReturnComponent, null, internalContextTag); + var fiber = createFiber(ReturnComponent, null, null, internalContextTag); fiber.expirationTime = expirationTime; return fiber; } function createFiberFromPortal(portal, internalContextTag, expirationTime) { - var fiber = createFiber(HostPortal, portal.key, internalContextTag); - fiber.pendingProps = portal.children || []; + var pendingProps = portal.children !== null ? portal.children : []; + var fiber = createFiber( + HostPortal, + pendingProps, + portal.key, + internalContextTag + ); fiber.expirationTime = expirationTime; fiber.stateNode = { containerInfo: portal.containerInfo, @@ -5120,6 +5170,8 @@ function createFiberFromPortal(portal, internalContextTag, expirationTime) { return fiber; } +// TODO: This should be lifted into the renderer. + function createFiberRoot(containerInfo, hydrate) { // Cyclic construction. This cheats the type system right now because // stateNode is any. @@ -5134,6 +5186,7 @@ function createFiberRoot(containerInfo, hydrate) { context: null, pendingContext: null, hydrate: hydrate, + firstBatch: null, nextScheduledRoot: null }; uninitializedFiber.stateNode = root; @@ -5339,6 +5392,12 @@ function getStateFromUpdate(update, instance, prevState, props) { var partialState = update.partialState; if (typeof partialState === "function") { var updateFn = partialState; + + // Invoke setState callback an extra time to help detect side-effects. + if (debugRenderPhaseSideEffects) { + updateFn.call(instance, prevState, props); + } + return updateFn.call(instance, prevState, props); } else { return partialState; @@ -5633,6 +5692,11 @@ var ReactFiberClassComponent = function( ); stopPhaseTimer(); + // Simulate an async bailout/interruption by invoking lifecycle twice. + if (debugRenderPhaseSideEffects) { + instance.shouldComponentUpdate(newProps, newState, newContext); + } + { warning( shouldUpdate !== undefined, @@ -5785,14 +5849,14 @@ var ReactFiberClassComponent = function( var state = instance.state; if (state && (typeof state !== "object" || isArray(state))) { - invariant( + warning( false, "%s.state: must be set to an object or null", getComponentName(workInProgress) ); } if (typeof instance.getChildContext === "function") { - invariant( + warning( typeof workInProgress.type.childContextTypes === "object", "%s.getChildContext(): childContextTypes must be defined in order to " + "use getChildContext().", @@ -5839,9 +5903,13 @@ var ReactFiberClassComponent = function( startPhaseTimer(workInProgress, "componentWillMount"); var oldState = instance.state; instance.componentWillMount(); - stopPhaseTimer(); + // Simulate an async bailout/interruption by invoking lifecycle twice. + if (debugRenderPhaseSideEffects) { + instance.componentWillMount(); + } + if (oldState !== instance.state) { { warning( @@ -5867,6 +5935,11 @@ var ReactFiberClassComponent = function( instance.componentWillReceiveProps(newProps, newContext); stopPhaseTimer(); + // Simulate an async bailout/interruption by invoking lifecycle twice. + if (debugRenderPhaseSideEffects) { + instance.componentWillReceiveProps(newProps, newContext); + } + if (instance.state !== oldState) { { var componentName = getComponentName(workInProgress) || "Component"; @@ -5895,14 +5968,7 @@ var ReactFiberClassComponent = function( var instance = workInProgress.stateNode; var state = instance.state || null; - var props = workInProgress.pendingProps; - invariant( - props, - "There must be pending props for an initial mount. This error is " + - "likely caused by a bug in React. Please file an issue." - ); - var unmaskedContext = getUnmaskedContext(workInProgress); instance.props = props; @@ -6052,16 +6118,6 @@ var ReactFiberClassComponent = function( var oldProps = workInProgress.memoizedProps; var newProps = workInProgress.pendingProps; - if (!newProps) { - // If there aren't any new props, then we'll reuse the memoized props. - // This could be from already completed work. - newProps = oldProps; - invariant( - newProps != null, - "There should always be pending or memoized props. This error is " + - "likely caused by a bug in React. Please file an issue." - ); - } var oldContext = instance.context; var newUnmaskedContext = getUnmaskedContext(workInProgress); var newContext = getMaskedContext(workInProgress, newUnmaskedContext); @@ -6135,6 +6191,11 @@ var ReactFiberClassComponent = function( startPhaseTimer(workInProgress, "componentWillUpdate"); instance.componentWillUpdate(newProps, newState, newContext); stopPhaseTimer(); + + // Simulate an async bailout/interruption by invoking lifecycle twice. + if (debugRenderPhaseSideEffects) { + instance.componentWillUpdate(newProps, newState, newContext); + } } if (typeof instance.componentDidUpdate === "function") { workInProgress.effectTag |= Update; @@ -6224,40 +6285,6 @@ var getCurrentFiberStackAddendum$1 = var isArray$1 = Array.isArray; -var ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = "@@iterator"; // Before Symbol spec. - -// The Symbol used to tag the ReactElement-like types. If there is no native Symbol -// nor polyfill, then a plain number is used for performance. -var REACT_ELEMENT_TYPE; -var REACT_CALL_TYPE; -var REACT_RETURN_TYPE; -var REACT_FRAGMENT_TYPE; -if (typeof Symbol === "function" && Symbol["for"]) { - REACT_ELEMENT_TYPE = Symbol["for"]("react.element"); - REACT_CALL_TYPE = Symbol["for"]("react.call"); - REACT_RETURN_TYPE = Symbol["for"]("react.return"); - REACT_FRAGMENT_TYPE = Symbol["for"]("react.fragment"); -} else { - REACT_ELEMENT_TYPE = 0xeac7; - REACT_CALL_TYPE = 0xeac8; - REACT_RETURN_TYPE = 0xeac9; - REACT_FRAGMENT_TYPE = 0xeacb; -} - -function getIteratorFn(maybeIterable) { - if (maybeIterable === null || typeof maybeIterable === "undefined") { - return null; - } - var iteratorFn = - (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - if (typeof iteratorFn === "function") { - return iteratorFn; - } - return null; -} - function coerceRef(current, element) { var mixedRef = element.ref; if (mixedRef !== null && typeof mixedRef !== "function") { @@ -6359,21 +6386,12 @@ function warnOnFunctionType() { // to be able to optimize each path individually by branching early. This needs // a compiler or we can do it manually. Helpers that don't need this branching // live outside of this function. -function ChildReconciler(shouldClone, shouldTrackSideEffects) { +function ChildReconciler(shouldTrackSideEffects) { function deleteChild(returnFiber, childToDelete) { if (!shouldTrackSideEffects) { // Noop. return; } - if (!shouldClone) { - // When we're reconciling in place we have a work in progress copy. We - // actually want the current copy. If there is no current copy, then we - // don't need to track deletion side-effects. - if (childToDelete.alternate === null) { - return; - } - childToDelete = childToDelete.alternate; - } // Deletions are added in reversed order so we add it to the front. // At this point, the return fiber's effect list is empty except for // deletions, so we can just append the deletion to the list. The remaining @@ -6426,22 +6444,10 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { function useFiber(fiber, pendingProps, expirationTime) { // We currently set sibling to null and index to 0 here because it is easy // to forget to do before returning it. E.g. for the single child case. - if (shouldClone) { - var clone = createWorkInProgress(fiber, pendingProps, expirationTime); - clone.index = 0; - clone.sibling = null; - return clone; - } else { - // We override the expiration time even if it is earlier, because if - // we're reconciling at a later time that means that this was - // down-prioritized. - fiber.expirationTime = expirationTime; - fiber.effectTag = NoEffect; - fiber.index = 0; - fiber.sibling = null; - fiber.pendingProps = pendingProps; - return fiber; - } + var clone = createWorkInProgress(fiber, pendingProps, expirationTime); + clone.index = 0; + clone.sibling = null; + return clone; } function placeChild(newFiber, lastPlacedIndex, newIndex) { @@ -7503,7 +7509,6 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { // This leads to an ambiguity between <>{[...]} and <>.... // We treat the ambiguous cases above the same. if ( - enableReactFragment && typeof newChild === "object" && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && @@ -7632,11 +7637,8 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { return reconcileChildFibers; } -var reconcileChildFibers = ChildReconciler(true, true); - -var reconcileChildFibersInPlace = ChildReconciler(false, true); - -var mountChildFibersInPlace = ChildReconciler(false, false); +var reconcileChildFibers = ChildReconciler(true); +var mountChildFibers = ChildReconciler(false); function cloneChildFibers(current, workInProgress) { invariant( @@ -7723,13 +7725,13 @@ var ReactFiberBeginWork = function( // won't update its child set by applying minimal side-effects. Instead, // we will add them all to the child before it gets rendered. That means // we can optimize this reconciliation pass by not tracking side-effects. - workInProgress.child = mountChildFibersInPlace( + workInProgress.child = mountChildFibers( workInProgress, - workInProgress.child, + null, nextChildren, renderExpirationTime ); - } else if (current.child === workInProgress.child) { + } else { // If the current child is the same as the work in progress, it means that // we haven't yet started any work on these children. Therefore, we use // the clone algorithm to create a copy of all the current children. @@ -7738,17 +7740,7 @@ var ReactFiberBeginWork = function( // let's throw it out. workInProgress.child = reconcileChildFibers( workInProgress, - workInProgress.child, - nextChildren, - renderExpirationTime - ); - } else { - // If, on the other hand, it is already using a clone, that means we've - // already begun some work on this tree and we can continue where we left - // off by reconciling against the existing children. - workInProgress.child = reconcileChildFibersInPlace( - workInProgress, - workInProgress.child, + current.child, nextChildren, renderExpirationTime ); @@ -7760,9 +7752,6 @@ var ReactFiberBeginWork = function( if (hasContextChanged()) { // 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. - if (nextChildren === null) { - nextChildren = workInProgress.memoizedProps; - } } else if ( nextChildren === null || workInProgress.memoizedProps === nextChildren @@ -7786,15 +7775,11 @@ var ReactFiberBeginWork = function( var fn = workInProgress.type; var nextProps = workInProgress.pendingProps; - var memoizedProps = workInProgress.memoizedProps; if (hasContextChanged()) { // 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. - if (nextProps === null) { - nextProps = memoizedProps; - } } else { - if (nextProps === null || memoizedProps === nextProps) { + if (workInProgress.memoizedProps === nextProps) { return bailoutOnAlreadyFinishedWork(current, workInProgress); } // TODO: consider bringing fn.shouldComponentUpdate() back. @@ -7878,6 +7863,9 @@ var ReactFiberBeginWork = function( { ReactDebugCurrentFiber.setCurrentPhase("render"); nextChildren = instance.render(); + if (debugRenderPhaseSideEffects) { + instance.render(); + } ReactDebugCurrentFiber.setCurrentPhase(null); } // React DevTools reads this flag. @@ -7951,9 +7939,9 @@ var ReactFiberBeginWork = function( // Ensure that children mount into this root without tracking // side-effects. This ensures that we don't store Placement effects on // nodes that will be hydrated. - workInProgress.child = mountChildFibersInPlace( + workInProgress.child = mountChildFibers( workInProgress, - workInProgress.child, + null, element, renderExpirationTime ); @@ -7981,20 +7969,12 @@ var ReactFiberBeginWork = function( var type = workInProgress.type; var memoizedProps = workInProgress.memoizedProps; var nextProps = workInProgress.pendingProps; - if (nextProps === null) { - nextProps = memoizedProps; - invariant( - nextProps !== null, - "We should always have pending or current props. This error is " + - "likely caused by a bug in React. Please file an issue." - ); - } var prevProps = current !== null ? current.memoizedProps : null; if (hasContextChanged()) { // 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 (nextProps === null || memoizedProps === nextProps) { + } else if (memoizedProps === nextProps) { return bailoutOnAlreadyFinishedWork(current, workInProgress); } @@ -8037,9 +8017,6 @@ var ReactFiberBeginWork = function( tryToClaimNextHydratableInstance(workInProgress); } var nextProps = workInProgress.pendingProps; - if (nextProps === null) { - nextProps = workInProgress.memoizedProps; - } memoizeProps(workInProgress, nextProps); // Nothing to do here. This is terminal. We'll do the completion step // immediately after. @@ -8143,15 +8120,7 @@ var ReactFiberBeginWork = function( if (hasContextChanged()) { // 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. - if (nextCall === null) { - nextCall = current && current.memoizedProps; - invariant( - nextCall !== null, - "We should always have pending or current props. This error is " + - "likely caused by a bug in React. Please file an issue." - ); - } - } else if (nextCall === null || workInProgress.memoizedProps === nextCall) { + } else if (workInProgress.memoizedProps === nextCall) { nextCall = workInProgress.memoizedProps; // TODO: When bailing out, we might need to return the stateNode instead // of the child. To check it for work. @@ -8163,21 +8132,14 @@ var ReactFiberBeginWork = function( // The following is a fork of reconcileChildrenAtExpirationTime but using // stateNode to store the child. if (current === null) { - workInProgress.stateNode = mountChildFibersInPlace( - workInProgress, - workInProgress.stateNode, - nextChildren, - renderExpirationTime - ); - } else if (current.child === workInProgress.child) { - workInProgress.stateNode = reconcileChildFibers( + workInProgress.stateNode = mountChildFibers( workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime ); } else { - workInProgress.stateNode = reconcileChildFibersInPlace( + workInProgress.stateNode = reconcileChildFibers( workInProgress, workInProgress.stateNode, nextChildren, @@ -8201,18 +8163,7 @@ var ReactFiberBeginWork = function( if (hasContextChanged()) { // 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. - if (nextChildren === null) { - nextChildren = current && current.memoizedProps; - invariant( - nextChildren != null, - "We should always have pending or current props. This error is " + - "likely caused by a bug in React. Please file an issue." - ); - } - } else if ( - nextChildren === null || - workInProgress.memoizedProps === nextChildren - ) { + } else if (workInProgress.memoizedProps === nextChildren) { return bailoutOnAlreadyFinishedWork(current, workInProgress); } @@ -8222,9 +8173,9 @@ var ReactFiberBeginWork = function( // flow doesn't do during mount. This doesn't happen at the root because // the root always starts with a "current" with a null child. // TODO: Consider unifying this with how the root works. - workInProgress.child = reconcileChildFibersInPlace( + workInProgress.child = reconcileChildFibers( workInProgress, - workInProgress.child, + null, nextChildren, renderExpirationTime ); @@ -8761,18 +8712,7 @@ var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) { } function completeWork(current, workInProgress, renderExpirationTime) { - // Get the latest props. var newProps = workInProgress.pendingProps; - if (newProps === null) { - newProps = workInProgress.memoizedProps; - } else if ( - workInProgress.expirationTime !== Never || - renderExpirationTime === Never - ) { - // Reset the pending props, unless this was a down-prioritization. - workInProgress.pendingProps = null; - } - switch (workInProgress.tag) { case FunctionalComponent: return null; @@ -10139,6 +10079,7 @@ var ReactFiberScheduler = function(config) { var now = config.now, scheduleDeferredCallback = config.scheduleDeferredCallback, + cancelDeferredCallback = config.cancelDeferredCallback, useSyncScheduling = config.useSyncScheduling, prepareForCommit = config.prepareForCommit, resetAfterCommit = config.resetAfterCommit; @@ -10148,6 +10089,9 @@ var ReactFiberScheduler = function(config) { var startTime = now(); var mostRecentCurrentTime = msToExpirationTime(0); + // Used to ensure computeUniqueAsyncExpiration is monotonically increases. + var lastUniqueAsyncExpiration = 0; + // Represents the expiration time that incoming updates should use. (If this // is NoWork, use the default strategy: async updates in async mode, sync // updates in sync mode.) @@ -10564,6 +10508,7 @@ var ReactFiberScheduler = function(config) { { ReactDebugCurrentFiber.setCurrentFiber(workInProgress); } + var next = beginWork(current, workInProgress, nextRenderExpirationTime); { ReactDebugCurrentFiber.resetCurrentFiber(); @@ -10923,7 +10868,10 @@ var ReactFiberScheduler = function(config) { } catch (e) { // Prevent cycle if logCapturedError() throws. // A cycle may still occur if logCapturedError renders a component that throws. - console.error(e); + var suppressLogging = e && e.suppressReactErrorLogging; + if (!suppressLogging) { + console.error(e); + } } // If we're in the commit phase, defer scheduling an update on the @@ -11051,6 +10999,19 @@ var ReactFiberScheduler = function(config) { return computeExpirationBucket(currentTime, expirationMs, bucketSizeMs); } + // Creates a unique async expiration time. + function computeUniqueAsyncExpiration() { + var result = computeAsyncExpiration(); + if (result <= lastUniqueAsyncExpiration) { + // Since we assume the current time monotonically increases, we only hit + // this branch when computeUniqueAsyncExpiration is fired multiple times + // within a 200ms window (or whatever the async bucket size is). + result = lastUniqueAsyncExpiration + 1; + } + lastUniqueAsyncExpiration = result; + return lastUniqueAsyncExpiration; + } + function computeExpirationForFiber(fiber) { var expirationTime = void 0; if (expirationContext !== NoWork) { @@ -11084,6 +11045,23 @@ var ReactFiberScheduler = function(config) { return scheduleWorkImpl(fiber, expirationTime, false); } + function checkRootNeedsClearing(root, fiber, expirationTime) { + if ( + !isWorking && + root === nextRoot && + expirationTime < nextRenderExpirationTime + ) { + // Restart the root from the top. + if (nextUnitOfWork !== null) { + // This is an interruption. (Used for performance tracking.) + interruptedBy = fiber; + } + nextRoot = null; + nextUnitOfWork = null; + nextRenderExpirationTime = NoWork; + } + } + function scheduleWorkImpl(fiber, expirationTime, isErrorRecovery) { recordScheduleUpdate(); @@ -11115,21 +11093,10 @@ var ReactFiberScheduler = function(config) { if (node["return"] === null) { if (node.tag === HostRoot) { var root = node.stateNode; - if ( - !isWorking && - root === nextRoot && - expirationTime <= nextRenderExpirationTime - ) { - // Restart the root from the top. - if (nextUnitOfWork !== null) { - // This is an interruption. (Used for performance tracking.) - interruptedBy = fiber; - } - nextRoot = null; - nextUnitOfWork = null; - nextRenderExpirationTime = NoWork; - } + + checkRootNeedsClearing(root, fiber, expirationTime); requestWork(root, expirationTime); + checkRootNeedsClearing(root, fiber, expirationTime); } else { { if (!isErrorRecovery && fiber.tag === ClassComponent) { @@ -11181,7 +11148,8 @@ var ReactFiberScheduler = function(config) { var firstScheduledRoot = null; var lastScheduledRoot = null; - var isCallbackScheduled = false; + var callbackExpirationTime = NoWork; + var callbackID = -1; var isRendering = false; var nextFlushedRoot = null; var nextFlushedExpirationTime = NoWork; @@ -11193,12 +11161,41 @@ var ReactFiberScheduler = function(config) { var isBatchingUpdates = false; var isUnbatchingUpdates = false; + var completedBatches = null; + // Use these to prevent an infinite loop of nested updates var NESTED_UPDATE_LIMIT = 1000; var nestedUpdateCount = 0; var timeHeuristicForUnitOfWork = 1; + function scheduleCallbackWithExpiration(expirationTime) { + if (callbackExpirationTime !== NoWork) { + // A callback is already scheduled. Check its expiration time (timeout). + if (expirationTime > callbackExpirationTime) { + // Existing callback has sufficient timeout. Exit. + return; + } else { + // Existing callback has insufficient timeout. Cancel and schedule a + // new one. + cancelDeferredCallback(callbackID); + } + // The request callback timer is already running. Don't start a new one. + } else { + startRequestCallbackTimer(); + } + + // Compute a timeout for the given expiration time. + var currentMs = now() - startTime; + var expirationMs = expirationTimeToMs(expirationTime); + var timeout = expirationMs - currentMs; + + callbackExpirationTime = expirationTime; + callbackID = scheduleDeferredCallback(performAsyncWork, { + timeout: timeout + }); + } + // requestWork is called by the scheduler whenever a root receives an update. // It's up to the renderer to call renderRoot at some point in the future. function requestWork(root, expirationTime) { @@ -11248,7 +11245,9 @@ var ReactFiberScheduler = function(config) { if (isUnbatchingUpdates) { // ...unless we're inside unbatchedUpdates, in which case we should // flush it now. - performWorkOnRoot(root, Sync); + nextFlushedRoot = root; + nextFlushedExpirationTime = Sync; + performWorkOnRoot(root, Sync, recalculateCurrentTime()); } return; } @@ -11256,10 +11255,8 @@ var ReactFiberScheduler = function(config) { // TODO: Get rid of Sync and use current time? if (expirationTime === Sync) { performWork(Sync, null); - } else if (!isCallbackScheduled) { - isCallbackScheduled = true; - startRequestCallbackTimer(); - scheduleDeferredCallback(performAsyncWork); + } else { + scheduleCallbackWithExpiration(expirationTime); } } @@ -11362,7 +11359,11 @@ var ReactFiberScheduler = function(config) { nextFlushedExpirationTime <= minExpirationTime) && !deadlineDidExpire ) { - performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime); + performWorkOnRoot( + nextFlushedRoot, + nextFlushedExpirationTime, + recalculateCurrentTime() + ); // Find the next highest priority work. findHighestPriorityRoot(); } @@ -11372,13 +11373,12 @@ var ReactFiberScheduler = function(config) { // If we're inside a callback, set this to false since we just completed it. if (deadline !== null) { - isCallbackScheduled = false; + callbackExpirationTime = NoWork; + callbackID = -1; } // If there's work left over, schedule a new callback. - if (nextFlushedRoot !== null && !isCallbackScheduled) { - isCallbackScheduled = true; - startRequestCallbackTimer(); - scheduleDeferredCallback(performAsyncWork); + if (nextFlushedExpirationTime !== NoWork) { + scheduleCallbackWithExpiration(nextFlushedExpirationTime); } // Clean-up. @@ -11386,6 +11386,39 @@ var ReactFiberScheduler = function(config) { deadlineDidExpire = false; nestedUpdateCount = 0; + finishRendering(); + } + + function flushRoot(root, expirationTime) { + invariant( + !isRendering, + "work.commit(): Cannot commit while already rendering. This likely " + + "means you attempted to commit from inside a lifecycle method." + ); + // 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. + performWorkOnRoot(root, expirationTime, expirationTime); + finishRendering(); + } + + function finishRendering() { + if (completedBatches !== null) { + var batches = completedBatches; + completedBatches = null; + for (var i = 0; i < batches.length; i++) { + var batch = batches[i]; + try { + batch._onComplete(); + } catch (error) { + if (!hasUnhandledError) { + hasUnhandledError = true; + unhandledError = error; + } + } + } + } + if (hasUnhandledError) { var _error4 = unhandledError; unhandledError = null; @@ -11394,7 +11427,7 @@ var ReactFiberScheduler = function(config) { } } - function performWorkOnRoot(root, expirationTime) { + function performWorkOnRoot(root, expirationTime, currentTime) { invariant( !isRendering, "performWorkOnRoot was called recursively. This error is likely caused " + @@ -11404,20 +11437,18 @@ var ReactFiberScheduler = function(config) { isRendering = true; // Check if this is async work or sync/expired work. - // TODO: Pass current time as argument to renderRoot, commitRoot - if (expirationTime <= recalculateCurrentTime()) { + if (expirationTime <= currentTime) { // Flush sync work. var finishedWork = root.finishedWork; if (finishedWork !== null) { // This root is already complete. We can commit it. - root.finishedWork = null; - root.remainingExpirationTime = commitRoot(finishedWork); + completeRoot(root, finishedWork, expirationTime); } else { root.finishedWork = null; finishedWork = renderRoot(root, expirationTime); if (finishedWork !== null) { // We've completed the root. Commit it. - root.remainingExpirationTime = commitRoot(finishedWork); + completeRoot(root, finishedWork, expirationTime); } } } else { @@ -11425,8 +11456,7 @@ var ReactFiberScheduler = function(config) { var _finishedWork = root.finishedWork; if (_finishedWork !== null) { // This root is already complete. We can commit it. - root.finishedWork = null; - root.remainingExpirationTime = commitRoot(_finishedWork); + completeRoot(root, _finishedWork, expirationTime); } else { root.finishedWork = null; _finishedWork = renderRoot(root, expirationTime); @@ -11435,7 +11465,7 @@ var ReactFiberScheduler = function(config) { // before committing. if (!shouldYield()) { // Still time left. Commit the root. - root.remainingExpirationTime = commitRoot(_finishedWork); + completeRoot(root, _finishedWork, expirationTime); } else { // There's no time left. Mark this root as complete. We'll come // back and commit it later. @@ -11448,6 +11478,29 @@ var ReactFiberScheduler = function(config) { isRendering = false; } + function completeRoot(root, finishedWork, expirationTime) { + // Check if there's a batch that matches this expiration time. + var firstBatch = root.firstBatch; + if (firstBatch !== null && firstBatch._expirationTime <= expirationTime) { + if (completedBatches === null) { + completedBatches = [firstBatch]; + } else { + completedBatches.push(firstBatch); + } + if (firstBatch._defer) { + // This root is blocked from committing by a batch. Unschedule it until + // we receive another update. + root.finishedWork = finishedWork; + root.remainingExpirationTime = NoWork; + return; + } + } + + // Commit the root. + root.finishedWork = null; + root.remainingExpirationTime = commitRoot(finishedWork); + } + // When working on async work, the reconciler asks the renderer if it should // yield execution. For DOM, we implement this with requestIdleCallback. function shouldYield() { @@ -11455,6 +11508,8 @@ var ReactFiberScheduler = function(config) { return false; } if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) { + // Disregard deadline.didTimeout. Only expired work should be flushed + // during a timeout. This path is only hit for non-expired work. return false; } deadlineDidExpire = true; @@ -11529,10 +11584,13 @@ var ReactFiberScheduler = function(config) { computeAsyncExpiration: computeAsyncExpiration, computeExpirationForFiber: computeExpirationForFiber, scheduleWork: scheduleWork, + requestWork: requestWork, + flushRoot: flushRoot, batchedUpdates: batchedUpdates, unbatchedUpdates: unbatchedUpdates, flushSync: flushSync, - deferredUpdates: deferredUpdates + deferredUpdates: deferredUpdates, + computeUniqueAsyncExpiration: computeUniqueAsyncExpiration }; }; @@ -11560,14 +11618,37 @@ var ReactFiberReconciler$1 = function(config) { var _ReactFiberScheduler = ReactFiberScheduler(config), computeAsyncExpiration = _ReactFiberScheduler.computeAsyncExpiration, + computeUniqueAsyncExpiration = + _ReactFiberScheduler.computeUniqueAsyncExpiration, computeExpirationForFiber = _ReactFiberScheduler.computeExpirationForFiber, scheduleWork = _ReactFiberScheduler.scheduleWork, + requestWork = _ReactFiberScheduler.requestWork, + flushRoot = _ReactFiberScheduler.flushRoot, batchedUpdates = _ReactFiberScheduler.batchedUpdates, unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates, flushSync = _ReactFiberScheduler.flushSync, deferredUpdates = _ReactFiberScheduler.deferredUpdates; - function scheduleTopLevelUpdate(current, element, callback) { + function computeRootExpirationTime(current, element) { + var expirationTime = void 0; + // Check if the top-level element is an async wrapper component. If so, + // treat updates to the root as async. This is a bit weird but lets us + // avoid a separate `renderAsync` API. + if ( + enableAsyncSubtreeAPI && + element != null && + element.type != null && + element.type.prototype != null && + element.type.prototype.unstable_isAsyncReactComponent === true + ) { + expirationTime = computeAsyncExpiration(); + } else { + expirationTime = computeExpirationForFiber(current); + } + return expirationTime; + } + + function scheduleRootUpdate(current, element, expirationTime, callback) { { if ( ReactDebugCurrentFiber.phase === "render" && @@ -11596,33 +11677,50 @@ var ReactFiberReconciler$1 = function(config) { ); } - var expirationTime = void 0; - // Check if the top-level element is an async wrapper component. If so, - // treat updates to the root as async. This is a bit weird but lets us - // avoid a separate `renderAsync` API. - if ( - enableAsyncSubtreeAPI && - element != null && - element.type != null && - element.type.prototype != null && - element.type.prototype.unstable_isAsyncReactComponent === true - ) { - expirationTime = computeAsyncExpiration(); - } else { - expirationTime = computeExpirationForFiber(current); - } - var update = { expirationTime: expirationTime, partialState: { element: element }, callback: callback, isReplace: false, isForced: false, - nextCallback: null, next: null }; insertUpdateIntoFiber(current, update); scheduleWork(current, expirationTime); + + return expirationTime; + } + + function updateContainerAtExpirationTime( + element, + container, + parentComponent, + expirationTime, + callback + ) { + // TODO: If this is a nested container, this won't be the root. + var current = container.current; + + { + if (ReactFiberInstrumentation_1.debugTool) { + if (current.alternate === null) { + ReactFiberInstrumentation_1.debugTool.onMountContainer(container); + } else if (element === null) { + ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container); + } else { + ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container); + } + } + } + + var context = getContextForSubtree(parentComponent); + if (container.context === null) { + container.context = context; + } else { + container.pendingContext = context; + } + + return scheduleRootUpdate(current, element, expirationTime, callback); } function findHostInstance(fiber) { @@ -11638,31 +11736,25 @@ var ReactFiberReconciler$1 = function(config) { return createFiberRoot(containerInfo, hydrate); }, updateContainer: function(element, container, parentComponent, callback) { - // TODO: If this is a nested container, this won't be the root. var current = container.current; - - { - if (ReactFiberInstrumentation_1.debugTool) { - if (current.alternate === null) { - ReactFiberInstrumentation_1.debugTool.onMountContainer(container); - } else if (element === null) { - ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container); - } else { - ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container); - } - } - } - - var context = getContextForSubtree(parentComponent); - if (container.context === null) { - container.context = context; - } else { - container.pendingContext = context; - } - - scheduleTopLevelUpdate(current, element, callback); + var expirationTime = computeRootExpirationTime(current, element); + return updateContainerAtExpirationTime( + element, + container, + parentComponent, + expirationTime, + callback + ); }, + updateContainerAtExpirationTime: updateContainerAtExpirationTime, + + flushRoot: flushRoot, + + requestWork: requestWork, + + computeUniqueAsyncExpiration: computeUniqueAsyncExpiration, + batchedUpdates: batchedUpdates, unbatchedUpdates: unbatchedUpdates, @@ -11854,10 +11946,6 @@ var ReactNativeFiberHostComponent = (function() { return ReactNativeFiberHostComponent; })(); -// eslint-disable-next-line no-unused-expressions - -ReactNativeFiberHostComponent.prototype; - var hasNativePerformanceNow = typeof performance === "object" && typeof performance.now === "function"; @@ -11869,7 +11957,6 @@ var now = hasNativePerformanceNow return Date.now(); }; -var isCallbackScheduled = false; var scheduledCallback = null; var frameDeadline = 0; @@ -11880,8 +11967,6 @@ var frameDeadlineObject = { }; function setTimeoutCallback() { - isCallbackScheduled = false; - // TODO (bvaughn) Hard-coded 5ms unblocks initial async testing. // React API probably changing to boolean rather than time remaining. // Longer-term plan is to rewrite this using shared memory, @@ -11901,13 +11986,12 @@ function setTimeoutCallback() { function scheduleDeferredCallback(callback) { // We assume only one callback is scheduled at a time b'c that's how Fiber works. scheduledCallback = callback; + return setTimeout(setTimeoutCallback, 1); +} - if (!isCallbackScheduled) { - isCallbackScheduled = true; - setTimeout(setTimeoutCallback, 1); - } - - return 0; +function cancelDeferredCallback(callbackID) { + scheduledCallback = null; + clearTimeout(callbackID); } // Modules provided by RN: @@ -12037,6 +12121,7 @@ var NativeRenderer = reactReconciler({ }, scheduleDeferredCallback: scheduleDeferredCallback, + cancelDeferredCallback: cancelDeferredCallback, shouldDeprioritizeSubtree: function(type, props) { return false; @@ -12664,10 +12749,6 @@ var ReactNativeComponent = (function(_React$Component) { return ReactNativeComponent; })(React.Component); -// eslint-disable-next-line no-unused-expressions - -ReactNativeComponent.prototype; - // Module provided by RN: var getInspectorDataForViewTag = void 0; diff --git a/Libraries/Renderer/ReactNativeRenderer-prod.js b/Libraries/Renderer/ReactNativeRenderer-prod.js index 936be8252..a7497b75b 100644 --- a/Libraries/Renderer/ReactNativeRenderer-prod.js +++ b/Libraries/Renderer/ReactNativeRenderer-prod.js @@ -1094,12 +1094,13 @@ function handleTopLevel( events && (eventQueue = accumulateInto(eventQueue, events)); topLevelType = eventQueue; eventQueue = null; - forEachAccumulated(topLevelType, executeDispatchesAndReleaseTopLevel); - invariant( - !eventQueue, - "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." - ); - ReactErrorUtils.rethrowCaughtError(); + topLevelType && + (forEachAccumulated(topLevelType, executeDispatchesAndReleaseTopLevel), + invariant( + !eventQueue, + "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." + ), + ReactErrorUtils.rethrowCaughtError()); } var ReactNativeTagHandles = { tagsStartAt: 1, @@ -1198,11 +1199,21 @@ function defaultShowDialog() { return !0; } var showDialog = defaultShowDialog, - REACT_PORTAL_TYPE = - ("function" === typeof Symbol && - Symbol["for"] && - Symbol["for"]("react.portal")) || - 60106; + hasSymbol = "function" === typeof Symbol && Symbol["for"], + REACT_ELEMENT_TYPE = hasSymbol ? Symbol["for"]("react.element") : 60103, + REACT_CALL_TYPE = hasSymbol ? Symbol["for"]("react.call") : 60104, + REACT_RETURN_TYPE = hasSymbol ? Symbol["for"]("react.return") : 60105, + REACT_PORTAL_TYPE = hasSymbol ? Symbol["for"]("react.portal") : 60106, + REACT_FRAGMENT_TYPE = hasSymbol ? Symbol["for"]("react.fragment") : 60107, + MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; +function getIteratorFn(maybeIterable) { + if (null === maybeIterable || "undefined" === typeof maybeIterable) + return null; + maybeIterable = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable["@@iterator"]; + return "function" === typeof maybeIterable ? maybeIterable : null; +} function createPortal(children, containerInfo, implementation) { var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null; @@ -1588,6 +1599,8 @@ function getComponentName(fiber) { ? fiber : "function" === typeof fiber ? fiber.displayName || fiber.name : null; } +var debugRenderPhaseSideEffects = require("ReactFeatureFlags") + .debugRenderPhaseSideEffects; function isFiberMountedImpl(fiber) { var node = fiber; if (fiber.alternate) for (; node["return"]; ) node = node["return"]; @@ -1814,24 +1827,30 @@ function invalidateContextProvider(workInProgress, didChange) { } else pop(didPerformWorkStackCursor, workInProgress); push(didPerformWorkStackCursor, didChange, workInProgress); } -function FiberNode(tag, key, internalContextTag) { +function FiberNode(tag, pendingProps, key, internalContextTag) { this.tag = tag; this.key = key; this.stateNode = this.type = null; this.sibling = this.child = this["return"] = null; this.index = 0; - this.memoizedState = this.updateQueue = this.memoizedProps = this.pendingProps = this.ref = null; + this.ref = null; + this.pendingProps = pendingProps; + this.memoizedState = this.updateQueue = this.memoizedProps = null; this.internalContextTag = internalContextTag; this.effectTag = 0; this.lastEffect = this.firstEffect = this.nextEffect = null; this.expirationTime = 0; this.alternate = null; } +function createFiber(tag, pendingProps, key, internalContextTag) { + return new FiberNode(tag, pendingProps, key, internalContextTag); +} function createWorkInProgress(current, pendingProps, expirationTime) { var workInProgress = current.alternate; null === workInProgress - ? ((workInProgress = new FiberNode( + ? ((workInProgress = createFiber( current.tag, + pendingProps, current.key, current.internalContextTag )), @@ -1839,12 +1858,12 @@ function createWorkInProgress(current, pendingProps, expirationTime) { (workInProgress.stateNode = current.stateNode), (workInProgress.alternate = current), (current.alternate = workInProgress)) - : ((workInProgress.effectTag = 0), + : ((workInProgress.pendingProps = pendingProps), + (workInProgress.effectTag = 0), (workInProgress.nextEffect = null), (workInProgress.firstEffect = null), (workInProgress.lastEffect = null)); workInProgress.expirationTime = expirationTime; - workInProgress.pendingProps = pendingProps; workInProgress.child = current.child; workInProgress.memoizedProps = current.memoizedProps; workInProgress.memoizedState = current.memoizedState; @@ -1858,21 +1877,20 @@ function createFiberFromElement(element, internalContextTag, expirationTime) { var fiber = void 0, type = element.type, key = element.key; + element = element.props; "function" === typeof type ? ((fiber = type.prototype && type.prototype.isReactComponent - ? new FiberNode(2, key, internalContextTag) - : new FiberNode(0, key, internalContextTag)), - (fiber.type = type), - (fiber.pendingProps = element.props)) + ? createFiber(2, element, key, internalContextTag) + : createFiber(0, element, key, internalContextTag)), + (fiber.type = type)) : "string" === typeof type - ? ((fiber = new FiberNode(5, key, internalContextTag)), - (fiber.type = type), - (fiber.pendingProps = element.props)) + ? ((fiber = createFiber(5, element, key, internalContextTag)), + (fiber.type = type)) : "object" === typeof type && null !== type && "number" === typeof type.tag - ? ((fiber = type), (fiber.pendingProps = element.props)) + ? ((fiber = type), (fiber.pendingProps = element)) : invariant( !1, "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", @@ -1888,32 +1906,33 @@ function createFiberFromFragment( expirationTime, key ) { - internalContextTag = new FiberNode(10, key, internalContextTag); - internalContextTag.pendingProps = elements; - internalContextTag.expirationTime = expirationTime; - return internalContextTag; + elements = createFiber(10, elements, key, internalContextTag); + elements.expirationTime = expirationTime; + return elements; } function createFiberFromText(content, internalContextTag, expirationTime) { - internalContextTag = new FiberNode(6, null, internalContextTag); - internalContextTag.pendingProps = content; - internalContextTag.expirationTime = expirationTime; - return internalContextTag; + content = createFiber(6, content, null, internalContextTag); + content.expirationTime = expirationTime; + return content; } function createFiberFromCall(call, internalContextTag, expirationTime) { - internalContextTag = new FiberNode(7, call.key, internalContextTag); + internalContextTag = createFiber(7, call, call.key, internalContextTag); internalContextTag.type = call.handler; - internalContextTag.pendingProps = call; internalContextTag.expirationTime = expirationTime; return internalContextTag; } function createFiberFromReturn(returnNode, internalContextTag, expirationTime) { - returnNode = new FiberNode(9, null, internalContextTag); + returnNode = createFiber(9, null, null, internalContextTag); returnNode.expirationTime = expirationTime; return returnNode; } function createFiberFromPortal(portal, internalContextTag, expirationTime) { - internalContextTag = new FiberNode(4, portal.key, internalContextTag); - internalContextTag.pendingProps = portal.children || []; + internalContextTag = createFiber( + 4, + null !== portal.children ? portal.children : [], + portal.key, + internalContextTag + ); internalContextTag.expirationTime = expirationTime; internalContextTag.stateNode = { containerInfo: portal.containerInfo, @@ -1993,7 +2012,8 @@ function insertUpdateIntoFiber(fiber, update) { function getStateFromUpdate(update, instance, prevState, props) { update = update.partialState; return "function" === typeof update - ? update.call(instance, prevState, props) + ? (debugRenderPhaseSideEffects && update.call(instance, prevState, props), + update.call(instance, prevState, props)) : update; } function processUpdateQueue( @@ -2170,12 +2190,8 @@ function ReactFiberClassComponent( var current = workInProgress.alternate, instance = workInProgress.stateNode, state = instance.state || null, - props = workInProgress.pendingProps; - invariant( - props, - "There must be pending props for an initial mount. This error is likely caused by a bug in React. Please file an issue." - ); - var unmaskedContext = getUnmaskedContext(workInProgress); + props = workInProgress.pendingProps, + unmaskedContext = getUnmaskedContext(workInProgress); instance.props = props; instance.state = workInProgress.memoizedState = state; instance.refs = emptyObject; @@ -2187,6 +2203,7 @@ function ReactFiberClassComponent( "function" === typeof instance.componentWillMount && ((state = instance.state), instance.componentWillMount(), + debugRenderPhaseSideEffects && instance.componentWillMount(), state !== instance.state && updater.enqueueReplaceState(instance, instance.state, null), (state = workInProgress.updateQueue), @@ -2211,20 +2228,16 @@ function ReactFiberClassComponent( instance.props = workInProgress.memoizedProps; instance.state = workInProgress.memoizedState; var oldProps = workInProgress.memoizedProps, - newProps = workInProgress.pendingProps; - newProps || - ((newProps = oldProps), - invariant( - null != newProps, - "There should always be pending or memoized props. This error is likely caused by a bug in React. Please file an issue." - )); - var oldContext = instance.context, + newProps = workInProgress.pendingProps, + oldContext = instance.context, newUnmaskedContext = getUnmaskedContext(workInProgress); newUnmaskedContext = getMaskedContext(workInProgress, newUnmaskedContext); "function" !== typeof instance.componentWillReceiveProps || (oldProps === newProps && oldContext === newUnmaskedContext) || ((oldContext = instance.state), instance.componentWillReceiveProps(newProps, newUnmaskedContext), + debugRenderPhaseSideEffects && + instance.componentWillReceiveProps(newProps, newUnmaskedContext), instance.state !== oldContext && updater.enqueueReplaceState(instance, instance.state, null)); oldContext = workInProgress.memoizedState; @@ -2255,35 +2268,47 @@ function ReactFiberClassComponent( (workInProgress.effectTag |= 4), !1 ); - var shouldUpdate = newProps; if ( null === oldProps || (null !== workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate) ) - shouldUpdate = !0; + var shouldUpdate = !0; else { - var instance$jscomp$0 = workInProgress.stateNode, - type = workInProgress.type; - shouldUpdate = - "function" === typeof instance$jscomp$0.shouldComponentUpdate - ? instance$jscomp$0.shouldComponentUpdate( - shouldUpdate, + shouldUpdate = workInProgress.stateNode; + var type = workInProgress.type; + "function" === typeof shouldUpdate.shouldComponentUpdate + ? ((type = shouldUpdate.shouldComponentUpdate( + newProps, + renderExpirationTime, + newUnmaskedContext + )), + debugRenderPhaseSideEffects && + shouldUpdate.shouldComponentUpdate( + newProps, renderExpirationTime, newUnmaskedContext - ) - : type.prototype && type.prototype.isPureReactComponent - ? !shallowEqual(oldProps, shouldUpdate) || - !shallowEqual(oldContext, renderExpirationTime) - : !0; + ), + (shouldUpdate = type)) + : (shouldUpdate = + type.prototype && type.prototype.isPureReactComponent + ? !shallowEqual(oldProps, newProps) || + !shallowEqual(oldContext, renderExpirationTime) + : !0); } shouldUpdate ? ("function" === typeof instance.componentWillUpdate && - instance.componentWillUpdate( + (instance.componentWillUpdate( newProps, renderExpirationTime, newUnmaskedContext ), + debugRenderPhaseSideEffects && + instance.componentWillUpdate( + newProps, + renderExpirationTime, + newUnmaskedContext + )), "function" === typeof instance.componentDidUpdate && (workInProgress.effectTag |= 4)) : ("function" !== typeof instance.componentDidUpdate || @@ -2299,29 +2324,7 @@ function ReactFiberClassComponent( } }; } -var isArray$1 = Array.isArray, - ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator, - REACT_ELEMENT_TYPE, - REACT_CALL_TYPE, - REACT_RETURN_TYPE, - REACT_FRAGMENT_TYPE; -"function" === typeof Symbol && Symbol["for"] - ? ((REACT_ELEMENT_TYPE = Symbol["for"]("react.element")), - (REACT_CALL_TYPE = Symbol["for"]("react.call")), - (REACT_RETURN_TYPE = Symbol["for"]("react.return")), - (REACT_FRAGMENT_TYPE = Symbol["for"]("react.fragment"))) - : ((REACT_ELEMENT_TYPE = 60103), - (REACT_CALL_TYPE = 60104), - (REACT_RETURN_TYPE = 60105), - (REACT_FRAGMENT_TYPE = 60107)); -function getIteratorFn(maybeIterable) { - if (null === maybeIterable || "undefined" === typeof maybeIterable) - return null; - maybeIterable = - (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL]) || - maybeIterable["@@iterator"]; - return "function" === typeof maybeIterable ? maybeIterable : null; -} +var isArray$1 = Array.isArray; function coerceRef(current, element) { var mixedRef = element.ref; if (null !== mixedRef && "function" !== typeof mixedRef) { @@ -2376,13 +2379,9 @@ function throwOnInvalidObjectType(returnFiber, newChild) { "" ); } -function ChildReconciler(shouldClone, shouldTrackSideEffects) { +function ChildReconciler(shouldTrackSideEffects) { function deleteChild(returnFiber, childToDelete) { if (shouldTrackSideEffects) { - if (!shouldClone) { - if (null === childToDelete.alternate) return; - childToDelete = childToDelete.alternate; - } var last = returnFiber.lastEffect; null !== last ? ((last.nextEffect = childToDelete), @@ -2408,18 +2407,9 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { return returnFiber; } function useFiber(fiber, pendingProps, expirationTime) { - if (shouldClone) - return ( - (fiber = createWorkInProgress(fiber, pendingProps, expirationTime)), - (fiber.index = 0), - (fiber.sibling = null), - fiber - ); - fiber.expirationTime = expirationTime; - fiber.effectTag = 0; + fiber = createWorkInProgress(fiber, pendingProps, expirationTime); fiber.index = 0; fiber.sibling = null; - fiber.pendingProps = pendingProps; return fiber; } function placeChild(newFiber, lastPlacedIndex, newIndex) { @@ -2937,6 +2927,11 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { return iteratorFn; } return function(returnFiber, currentFirstChild, newChild, expirationTime) { + "object" === typeof newChild && + null !== newChild && + newChild.type === REACT_FRAGMENT_TYPE && + null === newChild.key && + (newChild = newChild.props.children); var isObject = "object" === typeof newChild && null !== newChild; if (isObject) switch (newChild.$$typeof) { @@ -2970,14 +2965,14 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { isObject = isObject.sibling; } newChild.type === REACT_FRAGMENT_TYPE - ? ((newChild = createFiberFromFragment( + ? ((currentFirstChild = createFiberFromFragment( newChild.props.children, returnFiber.internalContextTag, expirationTime, newChild.key )), - (newChild["return"] = returnFiber), - (returnFiber = newChild)) + (currentFirstChild["return"] = returnFiber), + (returnFiber = currentFirstChild)) : ((expirationTime = createFiberFromElement( newChild, returnFiber.internalContextTag, @@ -2997,13 +2992,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { returnFiber, currentFirstChild.sibling ); - newChild = useFiber( + currentFirstChild = useFiber( currentFirstChild, newChild, expirationTime ); - newChild["return"] = returnFiber; - returnFiber = newChild; + currentFirstChild["return"] = returnFiber; + returnFiber = currentFirstChild; break a; } else { deleteRemainingChildren(returnFiber, currentFirstChild); @@ -3012,13 +3007,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { else deleteChild(returnFiber, currentFirstChild); currentFirstChild = currentFirstChild.sibling; } - newChild = createFiberFromCall( + currentFirstChild = createFiberFromCall( newChild, returnFiber.internalContextTag, expirationTime ); - newChild["return"] = returnFiber; - returnFiber = newChild; + currentFirstChild["return"] = returnFiber; + returnFiber = currentFirstChild; } return placeSingleChild(returnFiber); case REACT_RETURN_TYPE: @@ -3061,13 +3056,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { returnFiber, currentFirstChild.sibling ); - newChild = useFiber( + currentFirstChild = useFiber( currentFirstChild, newChild.children || [], expirationTime ); - newChild["return"] = returnFiber; - returnFiber = newChild; + currentFirstChild["return"] = returnFiber; + returnFiber = currentFirstChild; break a; } else { deleteRemainingChildren(returnFiber, currentFirstChild); @@ -3076,13 +3071,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { else deleteChild(returnFiber, currentFirstChild); currentFirstChild = currentFirstChild.sibling; } - newChild = createFiberFromPortal( + currentFirstChild = createFiberFromPortal( newChild, returnFiber.internalContextTag, expirationTime ); - newChild["return"] = returnFiber; - returnFiber = newChild; + currentFirstChild["return"] = returnFiber; + returnFiber = currentFirstChild; } return placeSingleChild(returnFiber); } @@ -3091,15 +3086,19 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { (newChild = "" + newChild), null !== currentFirstChild && 6 === currentFirstChild.tag ? (deleteRemainingChildren(returnFiber, currentFirstChild.sibling), - (newChild = useFiber(currentFirstChild, newChild, expirationTime))) + (currentFirstChild = useFiber( + currentFirstChild, + newChild, + expirationTime + ))) : (deleteRemainingChildren(returnFiber, currentFirstChild), - (newChild = createFiberFromText( + (currentFirstChild = createFiberFromText( newChild, returnFiber.internalContextTag, expirationTime ))), - (newChild["return"] = returnFiber), - (returnFiber = newChild), + (currentFirstChild["return"] = returnFiber), + (returnFiber = currentFirstChild), placeSingleChild(returnFiber) ); if (isArray$1(newChild)) @@ -3121,19 +3120,18 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { switch (returnFiber.tag) { case 2: case 1: - (newChild = returnFiber.type), + (expirationTime = returnFiber.type), invariant( !1, "%s(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.", - newChild.displayName || newChild.name || "Component" + expirationTime.displayName || expirationTime.name || "Component" ); } return deleteRemainingChildren(returnFiber, currentFirstChild); }; } -var reconcileChildFibers = ChildReconciler(!0, !0), - reconcileChildFibersInPlace = ChildReconciler(!1, !0), - mountChildFibersInPlace = ChildReconciler(!1, !1); +var reconcileChildFibers = ChildReconciler(!0), + mountChildFibers = ChildReconciler(!1); function ReactFiberBeginWork( config, hostContext, @@ -3142,40 +3140,21 @@ function ReactFiberBeginWork( computeExpirationForFiber ) { function reconcileChildren(current, workInProgress, nextChildren) { - reconcileChildrenAtExpirationTime( - current, - workInProgress, - nextChildren, - workInProgress.expirationTime - ); - } - function reconcileChildrenAtExpirationTime( - current, - workInProgress, - nextChildren, - renderExpirationTime - ) { + var renderExpirationTime = workInProgress.expirationTime; workInProgress.child = null === current - ? mountChildFibersInPlace( + ? mountChildFibers( workInProgress, - workInProgress.child, + null, nextChildren, renderExpirationTime ) - : current.child === workInProgress.child - ? reconcileChildFibers( - workInProgress, - workInProgress.child, - nextChildren, - renderExpirationTime - ) - : reconcileChildFibersInPlace( - workInProgress, - workInProgress.child, - nextChildren, - renderExpirationTime - ); + : reconcileChildFibers( + workInProgress, + current.child, + nextChildren, + renderExpirationTime + ); } function markRef(current, workInProgress) { var ref = workInProgress.ref; @@ -3197,6 +3176,7 @@ function ReactFiberBeginWork( ); shouldUpdate = workInProgress.stateNode; ReactCurrentOwner.current = workInProgress; + debugRenderPhaseSideEffects && shouldUpdate.render(); var nextChildren = shouldUpdate.render(); workInProgress.effectTag |= 1; reconcileChildren(current, workInProgress, nextChildren); @@ -3307,7 +3287,7 @@ function ReactFiberBeginWork( (props = pushContextProvider(workInProgress)), adoptClassInstance(workInProgress, fn), mountClassInstance(workInProgress, renderExpirationTime), - (workInProgress = finishClassComponent( + (current = finishClassComponent( current, workInProgress, !0, @@ -3316,34 +3296,27 @@ function ReactFiberBeginWork( : ((workInProgress.tag = 1), reconcileChildren(current, workInProgress, fn), (workInProgress.memoizedProps = props), - (workInProgress = workInProgress.child)); - return workInProgress; + (current = workInProgress.child)); + return current; case 1: - a: { - props = workInProgress.type; - renderExpirationTime = workInProgress.pendingProps; - fn = workInProgress.memoizedProps; - if (didPerformWorkStackCursor.current) - null === renderExpirationTime && (renderExpirationTime = fn); - else if ( - null === renderExpirationTime || - fn === renderExpirationTime - ) { - workInProgress = bailoutOnAlreadyFinishedWork( - current, - workInProgress - ); - break a; - } - fn = getUnmaskedContext(workInProgress); - fn = getMaskedContext(workInProgress, fn); - props = props(renderExpirationTime, fn); - workInProgress.effectTag |= 1; - reconcileChildren(current, workInProgress, props); - workInProgress.memoizedProps = renderExpirationTime; - workInProgress = workInProgress.child; - } - return workInProgress; + return ( + (props = workInProgress.type), + (renderExpirationTime = workInProgress.pendingProps), + didPerformWorkStackCursor.current || + workInProgress.memoizedProps !== renderExpirationTime + ? ((fn = getUnmaskedContext(workInProgress)), + (fn = getMaskedContext(workInProgress, fn)), + (props = props(renderExpirationTime, fn)), + (workInProgress.effectTag |= 1), + reconcileChildren(current, workInProgress, props), + (workInProgress.memoizedProps = renderExpirationTime), + (current = workInProgress.child)) + : (current = bailoutOnAlreadyFinishedWork( + current, + workInProgress + )), + current + ); case 2: return ( (props = pushContextProvider(workInProgress)), @@ -3380,7 +3353,7 @@ function ReactFiberBeginWork( )), fn === props ? (resetHydrationState(), - (workInProgress = bailoutOnAlreadyFinishedWork( + (current = bailoutOnAlreadyFinishedWork( current, workInProgress ))) @@ -3390,22 +3363,22 @@ function ReactFiberBeginWork( unmaskedContext.hydrate && enterHydrationState(workInProgress) ? ((workInProgress.effectTag |= 2), - (workInProgress.child = mountChildFibersInPlace( + (workInProgress.child = mountChildFibers( workInProgress, - workInProgress.child, + null, fn, renderExpirationTime ))) : (resetHydrationState(), reconcileChildren(current, workInProgress, fn)), (workInProgress.memoizedState = props), - (workInProgress = workInProgress.child))) + (current = workInProgress.child))) : (resetHydrationState(), - (workInProgress = bailoutOnAlreadyFinishedWork( + (current = bailoutOnAlreadyFinishedWork( current, workInProgress ))), - workInProgress + current ); case 5: pushHostContext(workInProgress); @@ -3413,15 +3386,8 @@ function ReactFiberBeginWork( props = workInProgress.type; var memoizedProps = workInProgress.memoizedProps; fn = workInProgress.pendingProps; - null === fn && - ((fn = memoizedProps), - invariant( - null !== fn, - "We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue." - )); unmaskedContext = null !== current ? current.memoizedProps : null; - didPerformWorkStackCursor.current || - (null !== fn && memoizedProps !== fn) + didPerformWorkStackCursor.current || memoizedProps !== fn ? ((memoizedProps = fn.children), shouldSetTextContent(props, fn) ? (memoizedProps = null) @@ -3433,117 +3399,91 @@ function ReactFiberBeginWork( !useSyncScheduling && shouldDeprioritizeSubtree(props, fn) ? ((workInProgress.expirationTime = 2147483647), - (workInProgress = null)) + (current = null)) : (reconcileChildren(current, workInProgress, memoizedProps), (workInProgress.memoizedProps = fn), - (workInProgress = workInProgress.child))) - : (workInProgress = bailoutOnAlreadyFinishedWork( - current, - workInProgress - )); - return workInProgress; + (current = workInProgress.child))) + : (current = bailoutOnAlreadyFinishedWork(current, workInProgress)); + return current; case 6: return ( null === current && tryToClaimNextHydratableInstance(workInProgress), - (current = workInProgress.pendingProps), - null === current && (current = workInProgress.memoizedProps), - (workInProgress.memoizedProps = current), + (workInProgress.memoizedProps = workInProgress.pendingProps), null ); case 8: workInProgress.tag = 7; case 7: - props = workInProgress.pendingProps; - if (didPerformWorkStackCursor.current) - null === props && - ((props = current && current.memoizedProps), - invariant( - null !== props, - "We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue." - )); - else if (null === props || workInProgress.memoizedProps === props) - props = workInProgress.memoizedProps; - fn = props.children; - workInProgress.stateNode = - null === current - ? mountChildFibersInPlace( - workInProgress, - workInProgress.stateNode, - fn, - renderExpirationTime - ) - : current.child === workInProgress.child - ? reconcileChildFibers( + return ( + (props = workInProgress.pendingProps), + didPerformWorkStackCursor.current || + workInProgress.memoizedProps !== props || + (props = workInProgress.memoizedProps), + (fn = props.children), + (workInProgress.stateNode = + null === current + ? mountChildFibers( workInProgress, workInProgress.stateNode, fn, renderExpirationTime ) - : reconcileChildFibersInPlace( + : reconcileChildFibers( workInProgress, workInProgress.stateNode, fn, renderExpirationTime - ); - workInProgress.memoizedProps = props; - return workInProgress.stateNode; + )), + (workInProgress.memoizedProps = props), + workInProgress.stateNode + ); case 9: return null; case 4: - a: { + return ( pushHostContainer( workInProgress, workInProgress.stateNode.containerInfo - ); - props = workInProgress.pendingProps; - if (didPerformWorkStackCursor.current) - null === props && - ((props = current && current.memoizedProps), - invariant( - null != props, - "We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue." - )); - else if (null === props || workInProgress.memoizedProps === props) { - workInProgress = bailoutOnAlreadyFinishedWork( - current, - workInProgress - ); - break a; - } - null === current - ? (workInProgress.child = reconcileChildFibersInPlace( - workInProgress, - workInProgress.child, - props, - renderExpirationTime - )) - : reconcileChildren(current, workInProgress, props); - workInProgress.memoizedProps = props; - workInProgress = workInProgress.child; - } - return workInProgress; + ), + (props = workInProgress.pendingProps), + didPerformWorkStackCursor.current || + workInProgress.memoizedProps !== props + ? (null === current + ? (workInProgress.child = reconcileChildFibers( + workInProgress, + null, + props, + renderExpirationTime + )) + : reconcileChildren(current, workInProgress, props), + (workInProgress.memoizedProps = props), + (current = workInProgress.child)) + : (current = bailoutOnAlreadyFinishedWork( + current, + workInProgress + )), + current + ); case 10: - a: { - renderExpirationTime = workInProgress.pendingProps; - if (didPerformWorkStackCursor.current) - null === renderExpirationTime && - (renderExpirationTime = workInProgress.memoizedProps); - else if ( - null === renderExpirationTime || - workInProgress.memoizedProps === renderExpirationTime - ) { - workInProgress = bailoutOnAlreadyFinishedWork( - current, - workInProgress - ); - break a; - } - reconcileChildren(current, workInProgress, renderExpirationTime); - workInProgress.memoizedProps = renderExpirationTime; - workInProgress = workInProgress.child; - } - return workInProgress; + return ( + (renderExpirationTime = workInProgress.pendingProps), + didPerformWorkStackCursor.current || + (null !== renderExpirationTime && + workInProgress.memoizedProps !== renderExpirationTime) + ? (reconcileChildren( + current, + workInProgress, + renderExpirationTime + ), + (workInProgress.memoizedProps = renderExpirationTime), + (current = workInProgress.child)) + : (current = bailoutOnAlreadyFinishedWork( + current, + workInProgress + )), + current + ); default: invariant( !1, @@ -3577,12 +3517,15 @@ function ReactFiberBeginWork( return bailoutOnLowPriority(current, workInProgress); workInProgress.firstEffect = null; workInProgress.lastEffect = null; - reconcileChildrenAtExpirationTime( - current, - workInProgress, - null, - renderExpirationTime - ); + workInProgress.child = + null === current + ? mountChildFibers(workInProgress, null, null, renderExpirationTime) + : reconcileChildFibers( + workInProgress, + current.child, + null, + renderExpirationTime + ); 2 === workInProgress.tag && ((current = workInProgress.stateNode), (workInProgress.memoizedProps = current.props), @@ -3628,12 +3571,6 @@ function ReactFiberCompleteWork(config, hostContext, hydrationContext) { return { completeWork: function(current, workInProgress, renderExpirationTime) { var newProps = workInProgress.pendingProps; - if (null === newProps) newProps = workInProgress.memoizedProps; - else if ( - 2147483647 !== workInProgress.expirationTime || - 2147483647 === renderExpirationTime - ) - workInProgress.pendingProps = null; switch (workInProgress.tag) { case 1: return null; @@ -4225,7 +4162,7 @@ function ReactFiberHostContext(config) { } function ReactFiberHydrationContext(config) { function deleteHydratableInstance(returnFiber, instance) { - var fiber = new FiberNode(5, null, 0); + var fiber = createFiber(5, null, null, 0); fiber.type = "DELETED"; fiber.stateNode = instance; fiber["return"] = returnFiber; @@ -4380,134 +4317,6 @@ function ReactFiberHydrationContext(config) { }; } function ReactFiberScheduler(config) { - function commitRoot(finishedWork) { - isCommitting = isWorking = !0; - var root = finishedWork.stateNode; - invariant( - root.current !== finishedWork, - "Cannot commit the same tree as before. This is probably a bug related to the return field. This error is likely caused by a bug in React. Please file an issue." - ); - root.isReadyForCommit = !1; - ReactCurrentOwner.current = null; - if (1 < finishedWork.effectTag) - if (null !== finishedWork.lastEffect) { - finishedWork.lastEffect.nextEffect = finishedWork; - var firstEffect = finishedWork.firstEffect; - } else firstEffect = finishedWork; - else firstEffect = finishedWork.firstEffect; - prepareForCommit(); - for (nextEffect = firstEffect; null !== nextEffect; ) { - var didError = !1, - _error = void 0; - try { - for (; null !== nextEffect; ) { - var effectTag = nextEffect.effectTag; - effectTag & 16 && commitResetTextContent(nextEffect); - if (effectTag & 128) { - var current = nextEffect.alternate; - null !== current && commitDetachRef(current); - } - switch (effectTag & -242) { - case 2: - commitPlacement(nextEffect); - nextEffect.effectTag &= -3; - break; - case 6: - commitPlacement(nextEffect); - nextEffect.effectTag &= -3; - commitWork(nextEffect.alternate, nextEffect); - break; - case 4: - commitWork(nextEffect.alternate, nextEffect); - break; - case 8: - (isUnmounting = !0), - commitDeletion(nextEffect), - (isUnmounting = !1); - } - 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." - ), - captureError(nextEffect, _error), - null !== nextEffect && (nextEffect = nextEffect.nextEffect)); - } - resetAfterCommit(); - root.current = finishedWork; - for (nextEffect = firstEffect; null !== nextEffect; ) { - firstEffect = !1; - didError = void 0; - try { - for (; null !== nextEffect; ) { - var effectTag$jscomp$0 = nextEffect.effectTag; - effectTag$jscomp$0 & 36 && - commitLifeCycles(nextEffect.alternate, nextEffect); - effectTag$jscomp$0 & 128 && commitAttachRef(nextEffect); - if (effectTag$jscomp$0 & 64) - switch (((_error = nextEffect), - (effectTag = void 0), - null !== capturedErrors && - ((effectTag = capturedErrors.get(_error)), - capturedErrors["delete"](_error), - null == effectTag && - null !== _error.alternate && - ((_error = _error.alternate), - (effectTag = capturedErrors.get(_error)), - capturedErrors["delete"](_error))), - invariant( - null != effectTag, - "No error for given unit of work. This error is likely caused by a bug in React. Please file an issue." - ), - _error.tag)) { - case 2: - _error.stateNode.componentDidCatch(effectTag.error, { - componentStack: effectTag.componentStack - }); - break; - case 3: - null === firstUncaughtError && - (firstUncaughtError = effectTag.error); - break; - default: - invariant( - !1, - "Invalid type of work. This error is likely caused by a bug in React. Please file an issue." - ); - } - var next = nextEffect.nextEffect; - nextEffect.nextEffect = null; - nextEffect = next; - } - } catch (e) { - (firstEffect = !0), (didError = e); - } - firstEffect && - (invariant( - null !== nextEffect, - "Should have next effect. This error is likely caused by a bug in React. Please file an issue." - ), - captureError(nextEffect, didError), - null !== nextEffect && (nextEffect = nextEffect.nextEffect)); - } - isWorking = isCommitting = !1; - "function" === typeof onCommitRoot && onCommitRoot(finishedWork.stateNode); - commitPhaseBoundaries && - (commitPhaseBoundaries.forEach(scheduleErrorRecovery), - (commitPhaseBoundaries = null)); - null !== firstUncaughtError && - ((finishedWork = firstUncaughtError), - (firstUncaughtError = null), - onUncaughtError(finishedWork)); - root = root.current.expirationTime; - 0 === root && (failedBoundaries = capturedErrors = null); - return root; - } function completeUnitOfWork(workInProgress$jscomp$0) { for (;;) { var next = completeWork( @@ -4696,7 +4505,7 @@ function ReactFiberScheduler(config) { null !== expirationTime && onUncaughtError(expirationTime); return root.isReadyForCommit ? root.current.alternate : null; } - function captureError(failedWork, error) { + function captureError(failedWork, error$jscomp$0) { var boundary = (ReactCurrentOwner.current = null), errorBoundaryFound = !1, willRetry = !1, @@ -4767,20 +4576,23 @@ function ReactFiberScheduler(config) { node = info; failedWork = getComponentName(failedWork); null === capturedErrors && (capturedErrors = new Map()); - error = { + error$jscomp$0 = { componentName: failedWork, componentStack: node, - error: error, + error: error$jscomp$0, errorBoundary: errorBoundaryFound ? boundary.stateNode : null, errorBoundaryFound: errorBoundaryFound, errorBoundaryName: errorBoundaryName, willRetry: willRetry }; - capturedErrors.set(boundary, error); + capturedErrors.set(boundary, error$jscomp$0); try { - !1 !== showDialog(error) && console.error(error.error); + if (!1 !== showDialog(error$jscomp$0)) { + var error = error$jscomp$0.error; + (error && error.suppressReactErrorLogging) || console.error(error); + } } catch (e) { - console.error(e); + (e && e.suppressReactErrorLogging) || console.error(e); } isCommitting ? (null === commitPhaseBoundaries && @@ -4789,7 +4601,7 @@ function ReactFiberScheduler(config) { : scheduleErrorRecovery(boundary); return boundary; } - null === firstUncaughtError && (firstUncaughtError = error); + null === firstUncaughtError && (firstUncaughtError = error$jscomp$0); return null; } function hasCapturedError(fiber) { @@ -4821,54 +4633,28 @@ function ReactFiberScheduler(config) { function scheduleWork(fiber, expirationTime) { return scheduleWorkImpl(fiber, expirationTime, !1); } - function scheduleWorkImpl(fiber, expirationTime$jscomp$0) { + function scheduleWorkImpl(fiber, expirationTime) { for (; null !== fiber; ) { - if ( - 0 === fiber.expirationTime || - fiber.expirationTime > expirationTime$jscomp$0 - ) - fiber.expirationTime = expirationTime$jscomp$0; + if (0 === fiber.expirationTime || fiber.expirationTime > expirationTime) + fiber.expirationTime = expirationTime; null !== fiber.alternate && (0 === fiber.alternate.expirationTime || - fiber.alternate.expirationTime > expirationTime$jscomp$0) && - (fiber.alternate.expirationTime = expirationTime$jscomp$0); + fiber.alternate.expirationTime > expirationTime) && + (fiber.alternate.expirationTime = expirationTime); if (null === fiber["return"]) if (3 === fiber.tag) { var root = fiber.stateNode; !isWorking && root === nextRoot && - expirationTime$jscomp$0 <= nextRenderExpirationTime && + expirationTime < nextRenderExpirationTime && + ((nextUnitOfWork = nextRoot = null), + (nextRenderExpirationTime = 0)); + requestWork(root, expirationTime); + !isWorking && + root === nextRoot && + expirationTime < nextRenderExpirationTime && ((nextUnitOfWork = nextRoot = null), (nextRenderExpirationTime = 0)); - var expirationTime = expirationTime$jscomp$0; - nestedUpdateCount > NESTED_UPDATE_LIMIT && - invariant( - !1, - "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." - ); - if (null === root.nextScheduledRoot) - (root.remainingExpirationTime = expirationTime), - null === lastScheduledRoot - ? ((firstScheduledRoot = lastScheduledRoot = root), - (root.nextScheduledRoot = root)) - : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = root), - (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); - else { - var remainingExpirationTime = root.remainingExpirationTime; - if ( - 0 === remainingExpirationTime || - expirationTime < remainingExpirationTime - ) - root.remainingExpirationTime = expirationTime; - } - isRendering || - (isBatchingUpdates - ? isUnbatchingUpdates && performWorkOnRoot(root, 1) - : 1 === expirationTime - ? performWork(1, null) - : isCallbackScheduled || - ((isCallbackScheduled = !0), - scheduleDeferredCallback(performAsyncWork))); } else break; fiber = fiber["return"]; } @@ -4879,6 +4665,48 @@ function ReactFiberScheduler(config) { function recalculateCurrentTime() { return (mostRecentCurrentTime = (((now() - startTime) / 10) | 0) + 2); } + function scheduleCallbackWithExpiration(expirationTime) { + if (0 !== callbackExpirationTime) { + if (expirationTime > callbackExpirationTime) return; + cancelDeferredCallback(callbackID); + } + var currentMs = now() - startTime; + callbackExpirationTime = expirationTime; + callbackID = scheduleDeferredCallback(performAsyncWork, { + timeout: 10 * (expirationTime - 2) - currentMs + }); + } + function requestWork(root, expirationTime) { + nestedUpdateCount > NESTED_UPDATE_LIMIT && + invariant( + !1, + "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." + ); + if (null === root.nextScheduledRoot) + (root.remainingExpirationTime = expirationTime), + null === lastScheduledRoot + ? ((firstScheduledRoot = lastScheduledRoot = root), + (root.nextScheduledRoot = root)) + : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = root), + (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); + else { + var remainingExpirationTime = root.remainingExpirationTime; + if ( + 0 === remainingExpirationTime || + expirationTime < remainingExpirationTime + ) + root.remainingExpirationTime = expirationTime; + } + isRendering || + (isBatchingUpdates + ? isUnbatchingUpdates && + ((nextFlushedRoot = root), + (nextFlushedExpirationTime = 1), + performWorkOnRoot(root, 1, recalculateCurrentTime())) + : 1 === expirationTime + ? performWork(1, null) + : scheduleCallbackWithExpiration(expirationTime)); + } function findHighestPriorityRoot() { var highestPriorityWork = 0, highestPriorityRoot = null; @@ -4946,49 +4774,207 @@ function ReactFiberScheduler(config) { !deadlineDidExpire; ) - performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime), + performWorkOnRoot( + nextFlushedRoot, + nextFlushedExpirationTime, + recalculateCurrentTime() + ), findHighestPriorityRoot(); - null !== deadline && (isCallbackScheduled = !1); - null === nextFlushedRoot || - isCallbackScheduled || - ((isCallbackScheduled = !0), scheduleDeferredCallback(performAsyncWork)); + null !== deadline && ((callbackExpirationTime = 0), (callbackID = -1)); + 0 !== nextFlushedExpirationTime && + scheduleCallbackWithExpiration(nextFlushedExpirationTime); deadline = null; deadlineDidExpire = !1; nestedUpdateCount = 0; + finishRendering(); + } + function finishRendering() { + if (null !== completedBatches) { + var batches = completedBatches; + completedBatches = null; + for (var i = 0; i < batches.length; i++) { + var batch = batches[i]; + try { + batch._onComplete(); + } catch (error) { + hasUnhandledError || + ((hasUnhandledError = !0), (unhandledError = error)); + } + } + } if (hasUnhandledError) - throw ((minExpirationTime = unhandledError), + throw ((batches = unhandledError), (unhandledError = null), (hasUnhandledError = !1), - minExpirationTime); + batches); } - function performWorkOnRoot(root, expirationTime) { + function performWorkOnRoot(root, expirationTime, currentTime) { invariant( !isRendering, "performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue." ); isRendering = !0; - if (expirationTime <= recalculateCurrentTime()) { - var finishedWork = root.finishedWork; - null !== finishedWork - ? ((root.finishedWork = null), - (root.remainingExpirationTime = commitRoot(finishedWork))) - : ((root.finishedWork = null), - (finishedWork = renderRoot(root, expirationTime)), - null !== finishedWork && - (root.remainingExpirationTime = commitRoot(finishedWork))); - } else - (finishedWork = root.finishedWork), - null !== finishedWork - ? ((root.finishedWork = null), - (root.remainingExpirationTime = commitRoot(finishedWork))) + expirationTime <= currentTime + ? ((currentTime = root.finishedWork), + null !== currentTime + ? completeRoot(root, currentTime, expirationTime) : ((root.finishedWork = null), - (finishedWork = renderRoot(root, expirationTime)), - null !== finishedWork && + (currentTime = renderRoot(root, expirationTime)), + null !== currentTime && + completeRoot(root, currentTime, expirationTime))) + : ((currentTime = root.finishedWork), + null !== currentTime + ? completeRoot(root, currentTime, expirationTime) + : ((root.finishedWork = null), + (currentTime = renderRoot(root, expirationTime)), + null !== currentTime && (shouldYield() - ? (root.finishedWork = finishedWork) - : (root.remainingExpirationTime = commitRoot(finishedWork)))); + ? (root.finishedWork = currentTime) + : completeRoot(root, currentTime, expirationTime)))); isRendering = !1; } + function completeRoot(root, finishedWork, expirationTime) { + var firstBatch = root.firstBatch; + if ( + null !== firstBatch && + firstBatch._expirationTime <= expirationTime && + (null === completedBatches + ? (completedBatches = [firstBatch]) + : completedBatches.push(firstBatch), + firstBatch._defer) + ) { + root.finishedWork = finishedWork; + root.remainingExpirationTime = 0; + return; + } + root.finishedWork = null; + isCommitting = isWorking = !0; + expirationTime = finishedWork.stateNode; + invariant( + expirationTime.current !== finishedWork, + "Cannot commit the same tree as before. This is probably a bug related to the return field. This error is likely caused by a bug in React. Please file an issue." + ); + expirationTime.isReadyForCommit = !1; + ReactCurrentOwner.current = null; + 1 < finishedWork.effectTag + ? null !== finishedWork.lastEffect + ? ((finishedWork.lastEffect.nextEffect = finishedWork), + (firstBatch = finishedWork.firstEffect)) + : (firstBatch = finishedWork) + : (firstBatch = finishedWork.firstEffect); + prepareForCommit(); + for (nextEffect = firstBatch; null !== nextEffect; ) { + var didError = !1, + _error = void 0; + try { + for (; null !== nextEffect; ) { + var effectTag = nextEffect.effectTag; + effectTag & 16 && commitResetTextContent(nextEffect); + if (effectTag & 128) { + var current = nextEffect.alternate; + null !== current && commitDetachRef(current); + } + switch (effectTag & -242) { + case 2: + commitPlacement(nextEffect); + nextEffect.effectTag &= -3; + break; + case 6: + commitPlacement(nextEffect); + nextEffect.effectTag &= -3; + commitWork(nextEffect.alternate, nextEffect); + break; + case 4: + commitWork(nextEffect.alternate, nextEffect); + break; + case 8: + (isUnmounting = !0), + commitDeletion(nextEffect), + (isUnmounting = !1); + } + 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." + ), + captureError(nextEffect, _error), + null !== nextEffect && (nextEffect = nextEffect.nextEffect)); + } + resetAfterCommit(); + expirationTime.current = finishedWork; + for (nextEffect = firstBatch; null !== nextEffect; ) { + effectTag = !1; + current = void 0; + try { + for (; null !== nextEffect; ) { + var effectTag$jscomp$0 = nextEffect.effectTag; + effectTag$jscomp$0 & 36 && + commitLifeCycles(nextEffect.alternate, nextEffect); + effectTag$jscomp$0 & 128 && commitAttachRef(nextEffect); + if (effectTag$jscomp$0 & 64) + switch (((firstBatch = nextEffect), + (didError = void 0), + null !== capturedErrors && + ((didError = capturedErrors.get(firstBatch)), + capturedErrors["delete"](firstBatch), + null == didError && + null !== firstBatch.alternate && + ((firstBatch = firstBatch.alternate), + (didError = capturedErrors.get(firstBatch)), + capturedErrors["delete"](firstBatch))), + invariant( + null != didError, + "No error for given unit of work. This error is likely caused by a bug in React. Please file an issue." + ), + firstBatch.tag)) { + case 2: + firstBatch.stateNode.componentDidCatch(didError.error, { + componentStack: didError.componentStack + }); + break; + case 3: + null === firstUncaughtError && + (firstUncaughtError = didError.error); + break; + default: + invariant( + !1, + "Invalid type of work. This error is likely caused by a bug in React. Please file an issue." + ); + } + var next = nextEffect.nextEffect; + nextEffect.nextEffect = null; + nextEffect = next; + } + } catch (e) { + (effectTag = !0), (current = e); + } + effectTag && + (invariant( + null !== nextEffect, + "Should have next effect. This error is likely caused by a bug in React. Please file an issue." + ), + captureError(nextEffect, current), + null !== nextEffect && (nextEffect = nextEffect.nextEffect)); + } + isWorking = isCommitting = !1; + "function" === typeof onCommitRoot && onCommitRoot(finishedWork.stateNode); + commitPhaseBoundaries && + (commitPhaseBoundaries.forEach(scheduleErrorRecovery), + (commitPhaseBoundaries = null)); + null !== firstUncaughtError && + ((finishedWork = firstUncaughtError), + (firstUncaughtError = null), + onUncaughtError(finishedWork)); + finishedWork = expirationTime.current.expirationTime; + 0 === finishedWork && (failedBoundaries = capturedErrors = null); + root.remainingExpirationTime = finishedWork; + } function shouldYield() { return null === deadline || deadline.timeRemaining() > timeHeuristicForUnitOfWork @@ -5029,11 +5015,13 @@ function ReactFiberScheduler(config) { commitDetachRef = hostContext.commitDetachRef, now = config.now, scheduleDeferredCallback = config.scheduleDeferredCallback, + cancelDeferredCallback = config.cancelDeferredCallback, useSyncScheduling = config.useSyncScheduling, prepareForCommit = config.prepareForCommit, resetAfterCommit = config.resetAfterCommit, startTime = now(), mostRecentCurrentTime = 2, + lastUniqueAsyncExpiration = 0, expirationContext = 0, isWorking = !1, nextUnitOfWork = null, @@ -5049,7 +5037,8 @@ function ReactFiberScheduler(config) { isUnmounting = !1, firstScheduledRoot = null, lastScheduledRoot = null, - isCallbackScheduled = !1, + callbackExpirationTime = 0, + callbackID = -1, isRendering = !1, nextFlushedRoot = null, nextFlushedExpirationTime = 0, @@ -5059,6 +5048,7 @@ function ReactFiberScheduler(config) { deadline = null, isBatchingUpdates = !1, isUnbatchingUpdates = !1, + completedBatches = null, NESTED_UPDATE_LIMIT = 1e3, nestedUpdateCount = 0, timeHeuristicForUnitOfWork = 1; @@ -5066,6 +5056,15 @@ function ReactFiberScheduler(config) { computeAsyncExpiration: computeAsyncExpiration, computeExpirationForFiber: computeExpirationForFiber, scheduleWork: scheduleWork, + requestWork: requestWork, + flushRoot: function(root, expirationTime) { + invariant( + !isRendering, + "work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method." + ); + performWorkOnRoot(root, expirationTime, expirationTime); + finishRendering(); + }, batchedUpdates: function(fn, a) { var previousIsBatchingUpdates = isBatchingUpdates; isBatchingUpdates = !0; @@ -5121,10 +5120,66 @@ function ReactFiberScheduler(config) { } finally { expirationContext = previousExpirationContext; } + }, + computeUniqueAsyncExpiration: function() { + var result = computeAsyncExpiration(); + result <= lastUniqueAsyncExpiration && + (result = lastUniqueAsyncExpiration + 1); + return (lastUniqueAsyncExpiration = result); } }; } function ReactFiberReconciler$1(config) { + function updateContainerAtExpirationTime( + element, + container, + parentComponent, + expirationTime, + callback + ) { + var current = 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; + } + parentComponent = isContextProvider(parentComponent) + ? processChildContext(parentComponent, parentContext) + : parentContext; + } else parentComponent = emptyObject; + null === container.context + ? (container.context = parentComponent) + : (container.pendingContext = parentComponent); + container = callback; + insertUpdateIntoFiber(current, { + expirationTime: expirationTime, + partialState: { element: element }, + callback: void 0 === container ? null : container, + isReplace: !1, + isForced: !1, + next: null + }); + scheduleWork(current, expirationTime); + return expirationTime; + } function findHostInstance(fiber) { fiber = findCurrentHostFiber(fiber); return null === fiber ? null : fiber.stateNode; @@ -5136,7 +5191,7 @@ function ReactFiberReconciler$1(config) { scheduleWork = config.scheduleWork; return { createContainer: function(containerInfo, hydrate) { - var uninitializedFiber = new FiberNode(3, null, 0); + var uninitializedFiber = createFiber(3, null, 0); containerInfo = { current: uninitializedFiber, containerInfo: containerInfo, @@ -5147,63 +5202,32 @@ function ReactFiberReconciler$1(config) { context: null, pendingContext: null, hydrate: hydrate, + firstBatch: null, nextScheduledRoot: null }; return (uninitializedFiber.stateNode = containerInfo); }, updateContainer: function(element, container, parentComponent, callback) { var current = 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; - } - parentComponent = isContextProvider(parentComponent) - ? processChildContext(parentComponent, parentContext) - : parentContext; - } else parentComponent = emptyObject; - null === container.context - ? (container.context = parentComponent) - : (container.pendingContext = parentComponent); - container = callback; - container = void 0 === container ? null : container; - callback = + current = null != element && null != element.type && null != element.type.prototype && !0 === element.type.prototype.unstable_isAsyncReactComponent ? computeAsyncExpiration() : computeExpirationForFiber(current); - insertUpdateIntoFiber(current, { - expirationTime: callback, - partialState: { element: element }, - callback: container, - isReplace: !1, - isForced: !1, - nextCallback: null, - next: null - }); - scheduleWork(current, callback); + return updateContainerAtExpirationTime( + element, + container, + parentComponent, + current, + callback + ); }, + updateContainerAtExpirationTime: updateContainerAtExpirationTime, + flushRoot: config.flushRoot, + requestWork: config.requestWork, + computeUniqueAsyncExpiration: config.computeUniqueAsyncExpiration, batchedUpdates: config.batchedUpdates, unbatchedUpdates: config.unbatchedUpdates, deferredUpdates: config.deferredUpdates, @@ -5303,9 +5327,8 @@ var ReactFiberReconciler$2 = Object.freeze({ default: ReactFiberReconciler$1 }), ); }; return ReactNativeFiberHostComponent; - })(); -ReactNativeFiberHostComponent.prototype; -var now = + })(), + now = "object" === typeof performance && "function" === typeof performance.now ? function() { return performance.now(); @@ -5313,7 +5336,6 @@ var now = : function() { return Date.now(); }, - isCallbackScheduled = !1, scheduledCallback = null, frameDeadline = 0, frameDeadlineObject = { @@ -5322,7 +5344,6 @@ var now = } }; function setTimeoutCallback() { - isCallbackScheduled = !1; frameDeadline = now() + 5; var callback = scheduledCallback; scheduledCallback = null; @@ -5417,9 +5438,11 @@ var NativeRenderer = reactReconciler({ resetAfterCommit: function() {}, scheduleDeferredCallback: function(callback) { scheduledCallback = callback; - isCallbackScheduled || - ((isCallbackScheduled = !0), setTimeout(setTimeoutCallback, 1)); - return 0; + return setTimeout(setTimeoutCallback, 1); + }, + cancelDeferredCallback: function(callbackID) { + scheduledCallback = null; + clearTimeout(callbackID); }, shouldDeprioritizeSubtree: function() { return !1; @@ -5585,80 +5608,79 @@ function _inherits(subClass, superClass) { : (subClass.__proto__ = superClass)); } var ReactNativeComponent = (function(_React$Component) { - function ReactNativeComponent() { - if (!(this instanceof ReactNativeComponent)) - throw new TypeError("Cannot call a class as a function"); - var call = _React$Component.apply(this, arguments); - if (!this) - throw new ReferenceError( - "this hasn't been initialised - super() hasn't been called" - ); - return !call || ("object" !== typeof call && "function" !== typeof call) - ? this - : call; - } - _inherits(ReactNativeComponent, _React$Component); - ReactNativeComponent.prototype.blur = function() { - TextInputState.blurTextInput(findNumericNodeHandleFiber(this)); - }; - ReactNativeComponent.prototype.focus = function() { - TextInputState.focusTextInput(findNumericNodeHandleFiber(this)); - }; - ReactNativeComponent.prototype.measure = function(callback) { - UIManager.measure( - findNumericNodeHandleFiber(this), - mountSafeCallback(this, callback) - ); - }; - ReactNativeComponent.prototype.measureInWindow = function(callback) { - UIManager.measureInWindow( - findNumericNodeHandleFiber(this), - mountSafeCallback(this, callback) - ); - }; - ReactNativeComponent.prototype.measureLayout = function( - relativeToNativeNode, - onSuccess, - onFail - ) { - UIManager.measureLayout( - findNumericNodeHandleFiber(this), - relativeToNativeNode, - mountSafeCallback(this, onFail), - mountSafeCallback(this, onSuccess) - ); - }; - ReactNativeComponent.prototype.setNativeProps = function(nativeProps) { - var maybeInstance = void 0; - try { - maybeInstance = findNodeHandle(this); - } catch (error) {} - if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig; - nativeProps = diffProperties( - null, - emptyObject$1, - nativeProps, - viewConfig.validAttributes - ); - null != nativeProps && - UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, - nativeProps + function ReactNativeComponent() { + if (!(this instanceof ReactNativeComponent)) + throw new TypeError("Cannot call a class as a function"); + var call = _React$Component.apply(this, arguments); + if (!this) + throw new ReferenceError( + "this hasn't been initialised - super() hasn't been called" ); + return !call || ("object" !== typeof call && "function" !== typeof call) + ? this + : call; } - }; - return ReactNativeComponent; -})(React.Component); -ReactNativeComponent.prototype; -var getInspectorDataForViewTag = void 0; + _inherits(ReactNativeComponent, _React$Component); + ReactNativeComponent.prototype.blur = function() { + TextInputState.blurTextInput(findNumericNodeHandleFiber(this)); + }; + ReactNativeComponent.prototype.focus = function() { + TextInputState.focusTextInput(findNumericNodeHandleFiber(this)); + }; + ReactNativeComponent.prototype.measure = function(callback) { + UIManager.measure( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }; + ReactNativeComponent.prototype.measureInWindow = function(callback) { + UIManager.measureInWindow( + findNumericNodeHandleFiber(this), + mountSafeCallback(this, callback) + ); + }; + ReactNativeComponent.prototype.measureLayout = function( + relativeToNativeNode, + onSuccess, + onFail + ) { + UIManager.measureLayout( + findNumericNodeHandleFiber(this), + relativeToNativeNode, + mountSafeCallback(this, onFail), + mountSafeCallback(this, onSuccess) + ); + }; + ReactNativeComponent.prototype.setNativeProps = function(nativeProps) { + var maybeInstance = void 0; + try { + maybeInstance = findNodeHandle(this); + } catch (error) {} + if (null != maybeInstance) { + var viewConfig = maybeInstance.viewConfig; + nativeProps = diffProperties( + null, + emptyObject$1, + nativeProps, + viewConfig.validAttributes + ); + null != nativeProps && + UIManager.updateView( + maybeInstance._nativeTag, + viewConfig.uiViewClassName, + nativeProps + ); + } + }; + return ReactNativeComponent; + })(React.Component), + getInspectorDataForViewTag = void 0; getInspectorDataForViewTag = function() { invariant(!1, "getInspectorDataForViewTag() is not available in production"); }; fiberBatchedUpdates = NativeRenderer.batchedUpdates; var roots = new Map(); -function fn$jscomp$inline_601(capturedError) { +function fn$jscomp$inline_616(capturedError) { var componentStack = capturedError.componentStack, error = capturedError.error; if (error instanceof Error) { @@ -5683,10 +5705,10 @@ invariant( "The custom dialog was already injected." ); invariant( - "function" === typeof fn$jscomp$inline_601, + "function" === typeof fn$jscomp$inline_616, "Injected showDialog() must be a function." ); -showDialog = fn$jscomp$inline_601; +showDialog = fn$jscomp$inline_616; var ReactNativeRenderer = { NativeComponent: ReactNativeComponent, findNodeHandle: findNumericNodeHandleFiber, @@ -5795,7 +5817,7 @@ NativeRenderer.injectIntoDevTools({ findFiberByHostInstance: getInstanceFromTag, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.1.1", + version: "16.2.0", rendererPackageName: "react-native-renderer" }); var ReactNativeRenderer$2 = Object.freeze({ default: ReactNativeRenderer }), diff --git a/Libraries/Renderer/shims/ReactFeatureFlags.js b/Libraries/Renderer/shims/ReactFeatureFlags.js new file mode 100644 index 000000000..276dc9142 --- /dev/null +++ b/Libraries/Renderer/shims/ReactFeatureFlags.js @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @providesModule ReactFeatureFlags + */ + +'use strict'; + +var ReactFeatureFlags = { + debugRenderPhaseSideEffects: false, +}; + +module.exports = ReactFeatureFlags; diff --git a/package.json b/package.json index f0931a2fd..43d493cb0 100644 --- a/package.json +++ b/package.json @@ -142,7 +142,7 @@ "react-native": "local-cli/wrong-react-native.js" }, "peerDependencies": { - "react": "16.1.1" + "react": "16.2.0" }, "dependencies": { "absolute-path": "^0.0.0", @@ -211,8 +211,8 @@ "flow-bin": "^0.59.0", "jest": "21.3.0-beta.8", "prettier": "1.7.0", - "react": "16.1.1", - "react-test-renderer": "16.1.1", + "react": "16.2.0", + "react-test-renderer": "16.2.0", "shelljs": "^0.7.8", "sinon": "^2.2.0" }