From 19c8164e367acecfe16bf55d2a2c588607cf02e5 Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 12 Oct 2018 17:42:51 -0700 Subject: [PATCH] React sync for revisions d836010...4773fdf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public This sync includes the following changes: - **[4773fdf7c](https://github.com/facebook/react/commit/4773fdf7c)**: Deprecate findDOMNode in StrictMode (#13841) //// - **[c9be16f5b](https://github.com/facebook/react/commit/c9be16f5b)**: [scheduler] Rename priority levels (#13842) //// - **[3b7ee2692](https://github.com/facebook/react/commit/3b7ee2692)**: Deprecate context object as a consumer and add a warning message (#13829) //// - **[8ca8a594e](https://github.com/facebook/react/commit/8ca8a594e)**: Error gracefully for unsupported SSR features (#13839) //// - **[4a635785f](https://github.com/facebook/react/commit/4a635785f)**: Fix User Timing oddities with Suspense, pure, and lazy (#13833) //// - **[a165cf747](https://github.com/facebook/react/commit/a165cf747)**: Renamed 4 Internal React Modules //// - **[a68ca9a5b](https://github.com/facebook/react/commit/a68ca9a5b)**: React.pure automatically forwards ref (#13822) //// - **[c73497c3c](https://github.com/facebook/react/commit/c73497c3c)**: Update bundle sizes for 16.6.0-alpha.8af6728 release //// - **[1a57dc668](https://github.com/facebook/react/commit/1a57dc668)**: Updating dependencies for react-noop-renderer //// - **[77f8dfd81](https://github.com/facebook/react/commit/77f8dfd81)**: Updating package versions for release 16.6.0-alpha.8af6728 //// - **[8af6728c6](https://github.com/facebook/react/commit/8af6728c6)**: Enable Suspense + rename Placeholder (#13799) //// - **[f47a958ea](https://github.com/facebook/react/commit/f47a958ea)**: Don’t add onclick listener to React root (#13778) //// - **[b2cea9078](https://github.com/facebook/react/commit/b2cea9078)**: [scheduler] Eagerly schedule rAF at beginning of frame (#13785) //// - **[e2e7cb9f4](https://github.com/facebook/react/commit/e2e7cb9f4)**: [scheduler] add a test documenting current behavior (#13687) //// Release Notes: [GENERAL] [FEATURE] [React] - React sync for revisions d836010...4773fdf Reviewed By: acdlite Differential Revision: D10350869 fbshipit-source-id: ea8ad4b5d914c870be1fc80aa1005b224d37f5e5 --- Libraries/Renderer/REVISION | 2 +- Libraries/Renderer/oss/ReactFabric-dev.js | 400 +++++++++------ Libraries/Renderer/oss/ReactFabric-prod.js | 484 ++++++++++++++---- .../Renderer/oss/ReactFabric-profiling.js | 346 ++++++++++--- .../Renderer/oss/ReactNativeRenderer-dev.js | 400 +++++++++------ .../Renderer/oss/ReactNativeRenderer-prod.js | 484 ++++++++++++++---- .../oss/ReactNativeRenderer-profiling.js | 346 ++++++++++--- 7 files changed, 1795 insertions(+), 667 deletions(-) diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index d655480ee26935..21b691427f48aa 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -d83601080a7c913cedcfbad86044702d008039c7 \ No newline at end of file +4773fdf7cdf5d6d775ad0960f23ee1a830e7b82b \ No newline at end of file diff --git a/Libraries/Renderer/oss/ReactFabric-dev.js b/Libraries/Renderer/oss/ReactFabric-dev.js index 1e886eebc5a936..de566d72b49386 100644 --- a/Libraries/Renderer/oss/ReactFabric-dev.js +++ b/Libraries/Renderer/oss/ReactFabric-dev.js @@ -1148,7 +1148,7 @@ var ContextProvider = 12; var ForwardRef = 13; var ForwardRefLazy = 14; var Profiler = 15; -var PlaceholderComponent = 16; +var SuspenseComponent = 16; var PureComponent = 17; var PureComponentLazy = 18; @@ -2656,9 +2656,7 @@ var REACT_CONCURRENT_MODE_TYPE = hasSymbol var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 0xead0; -var REACT_PLACEHOLDER_TYPE = hasSymbol - ? Symbol.for("react.placeholder") - : 0xead1; +var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 0xead1; var REACT_PURE_TYPE = hasSymbol ? Symbol.for("react.pure") : 0xead3; var MAYBE_ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; @@ -2689,6 +2687,14 @@ function refineResolvedThenable(thenable) { return thenable._reactStatus === Resolved ? thenable._reactResult : null; } +function getWrappedName(outerType, innerType, wrapperName) { + var functionName = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) + ); +} + function getComponentName(type) { if (type == null) { // Host root, text node or just invalid type. @@ -2720,8 +2726,8 @@ function getComponentName(type) { return "Profiler"; case REACT_STRICT_MODE_TYPE: return "StrictMode"; - case REACT_PLACEHOLDER_TYPE: - return "Placeholder"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; } if (typeof type === "object") { switch (type.$$typeof) { @@ -2730,14 +2736,9 @@ function getComponentName(type) { case REACT_PROVIDER_TYPE: return "Context.Provider"; case REACT_FORWARD_REF_TYPE: - var renderFn = type.render; - var functionName = renderFn.displayName || renderFn.name || ""; - return ( - type.displayName || - (functionName !== "" - ? "ForwardRef(" + functionName + ")" - : "ForwardRef") - ); + return getWrappedName(type, type.render, "ForwardRef"); + case REACT_PURE_TYPE: + return getWrappedName(type, type.render, "Pure"); } if (typeof type.then === "function") { var thenable = type; @@ -4144,7 +4145,6 @@ function setCurrentPhase(lifeCyclePhase) { var debugRenderPhaseSideEffects = false; var debugRenderPhaseSideEffectsForStrictMode = false; var enableUserTimingAPI = true; -var enableSuspense = false; var warnAboutDeprecatedLifecycles = false; var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; var enableProfilerTimer = true; @@ -4422,7 +4422,10 @@ function stopFailedWorkTimer(fiber) { return; } fiber._debugIsCurrentlyTiming = false; - var warning = "An error was thrown inside this error boundary"; + var warning = + fiber.tag === SuspenseComponent + ? "Rendering was suspended" + : "An error was thrown inside this error boundary"; endFiberMark(fiber, null, warning); } } @@ -5344,8 +5347,8 @@ function createFiberFromElement(element, mode, expirationTime) { break; case REACT_PROFILER_TYPE: return createFiberFromProfiler(pendingProps, mode, expirationTime, key); - case REACT_PLACEHOLDER_TYPE: - fiberTag = PlaceholderComponent; + case REACT_SUSPENSE_TYPE: + fiberTag = SuspenseComponent; break; default: { if (typeof type === "object" && type !== null) { @@ -10224,6 +10227,7 @@ function updatePureComponent( renderExpirationTime ) { var render = Component.render; + var ref = workInProgress.ref; if ( current$$1 !== null && @@ -10234,7 +10238,10 @@ function updatePureComponent( // Default to shallow comparison var compare = Component.compare; compare = compare !== null ? compare : shallowEqual; - if (compare(prevProps, nextProps)) { + if ( + workInProgress.ref === current$$1.ref && + compare(prevProps, nextProps) + ) { return bailoutOnAlreadyFinishedWork( current$$1, workInProgress, @@ -10249,7 +10256,7 @@ function updatePureComponent( { ReactCurrentOwner$3.current = workInProgress; setCurrentPhase("render"); - nextChildren = render(nextProps); + nextChildren = render(nextProps, ref); setCurrentPhase(null); } @@ -10689,11 +10696,15 @@ function mountIndeterminateComponent( Component !== null && typeof Component.then === "function" ) { + // We can't start a User Timing measurement with correct label yet. + // Cancel and resume right after we know the tag. + cancelWorkTimer(workInProgress); Component = readLazyComponentType(Component); var resolvedTag = (workInProgress.tag = resolveLazyComponentTag( workInProgress, Component )); + startWorkTimer(workInProgress); var resolvedProps = resolveDefaultProps(Component, props); var child = void 0; switch (resolvedTag) { @@ -10904,79 +10915,72 @@ function mountIndeterminateComponent( } } -function updatePlaceholderComponent( +function updateSuspenseComponent( current$$1, workInProgress, renderExpirationTime ) { - if (enableSuspense) { - var nextProps = workInProgress.pendingProps; - - // Check if we already attempted to render the normal state. If we did, - // and we timed out, render the placeholder state. - var alreadyCaptured = (workInProgress.effectTag & DidCapture) === NoEffect; - - var nextDidTimeout = void 0; - if (current$$1 !== null && workInProgress.updateQueue !== null) { - // We're outside strict mode. Something inside this Placeholder boundary - // suspended during the last commit. Switch to the placholder. - workInProgress.updateQueue = null; - nextDidTimeout = true; - } else { - nextDidTimeout = !alreadyCaptured; - } + var nextProps = workInProgress.pendingProps; - if ((workInProgress.mode & StrictMode) !== NoEffect) { - if (nextDidTimeout) { - // If the timed-out view commits, schedule an update effect to record - // the committed time. - workInProgress.effectTag |= Update; - } else { - // The state node points to the time at which placeholder timed out. - // We can clear it once we switch back to the normal children. - workInProgress.stateNode = null; - } - } + // Check if we already attempted to render the normal state. If we did, + // and we timed out, render the placeholder state. + var alreadyCaptured = (workInProgress.effectTag & DidCapture) === NoEffect; - // If the `children` prop is a function, treat it like a render prop. - // TODO: This is temporary until we finalize a lower level API. - var children = nextProps.children; - var nextChildren = void 0; - if (typeof children === "function") { - nextChildren = children(nextDidTimeout); - } else { - nextChildren = nextDidTimeout ? nextProps.fallback : children; - } + var nextDidTimeout = void 0; + if (current$$1 !== null && workInProgress.updateQueue !== null) { + // We're outside strict mode. Something inside this Placeholder boundary + // suspended during the last commit. Switch to the placholder. + workInProgress.updateQueue = null; + nextDidTimeout = true; + } else { + nextDidTimeout = !alreadyCaptured; + } - if ( - current$$1 !== null && - nextDidTimeout !== workInProgress.memoizedState - ) { - // We're about to switch from the placeholder children to the normal - // children, or vice versa. These are two different conceptual sets that - // happen to be stored in the same set. Call this special function to - // force the new set not to match with the current set. - // TODO: The proper way to model this is by storing each set separately. - forceUnmountCurrentAndReconcile( - current$$1, - workInProgress, - nextChildren, - renderExpirationTime - ); + if ((workInProgress.mode & StrictMode) !== NoEffect) { + if (nextDidTimeout) { + // If the timed-out view commits, schedule an update effect to record + // the committed time. + workInProgress.effectTag |= Update; } else { - reconcileChildren( - current$$1, - workInProgress, - nextChildren, - renderExpirationTime - ); + // The state node points to the time at which placeholder timed out. + // We can clear it once we switch back to the normal children. + workInProgress.stateNode = null; } - workInProgress.memoizedProps = nextProps; - workInProgress.memoizedState = nextDidTimeout; - return workInProgress.child; + } + + // If the `children` prop is a function, treat it like a render prop. + // TODO: This is temporary until we finalize a lower level API. + var children = nextProps.children; + var nextChildren = void 0; + if (typeof children === "function") { + nextChildren = children(nextDidTimeout); } else { - return null; + nextChildren = nextDidTimeout ? nextProps.fallback : children; + } + + if (current$$1 !== null && nextDidTimeout !== workInProgress.memoizedState) { + // We're about to switch from the placeholder children to the normal + // children, or vice versa. These are two different conceptual sets that + // happen to be stored in the same set. Call this special function to + // force the new set not to match with the current set. + // TODO: The proper way to model this is by storing each set separately. + forceUnmountCurrentAndReconcile( + current$$1, + workInProgress, + nextChildren, + renderExpirationTime + ); + } else { + reconcileChildren( + current$$1, + workInProgress, + nextChildren, + renderExpirationTime + ); } + workInProgress.memoizedProps = nextProps; + workInProgress.memoizedState = nextDidTimeout; + return workInProgress.child; } function updatePortalComponent( @@ -11075,12 +11079,35 @@ function updateContextProvider( return workInProgress.child; } +var hasWarnedAboutUsingContextAsConsumer = false; + function updateContextConsumer( current$$1, workInProgress, renderExpirationTime ) { var context = workInProgress.type; + // The logic below for Context differs depending on PROD or DEV mode. In + // DEV mode, we create a separate object for Context.Consumer that acts + // like a proxy to Context. This proxy object adds unnecessary code in PROD + // so we use the old behaviour (Context.Consumer references Context) to + // reduce size and overhead. The separate object references context via + // a property called "_context", which also gives us the ability to check + // in DEV mode if this property exists or not and warn if it does not. + { + if (context._context === undefined) { + if (!hasWarnedAboutUsingContextAsConsumer) { + hasWarnedAboutUsingContextAsConsumer = true; + warning$1( + false, + "Rendering directly is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } + } else { + context = context._context; + } + } var newProps = workInProgress.pendingProps; var render = newProps.children; @@ -11320,8 +11347,8 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { ); case HostText: return updateHostText(current$$1, workInProgress); - case PlaceholderComponent: - return updatePlaceholderComponent( + case SuspenseComponent: + return updateSuspenseComponent( current$$1, workInProgress, renderExpirationTime @@ -11820,7 +11847,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { case ForwardRef: case ForwardRefLazy: break; - case PlaceholderComponent: + case SuspenseComponent: break; case Fragment: break; @@ -12228,22 +12255,20 @@ function commitLifeCycles( } return; } - case PlaceholderComponent: { - if (enableSuspense) { - if ((finishedWork.mode & StrictMode) === NoEffect) { - // In loose mode, a placeholder times out by scheduling a synchronous - // update in the commit phase. Use `updateQueue` field to signal that - // the Timeout needs to switch to the placeholder. We don't need an - // entire queue. Any non-null value works. - // $FlowFixMe - Intentionally using a value other than an UpdateQueue. - finishedWork.updateQueue = emptyObject$1; - scheduleWork(finishedWork, Sync); - } else { - // In strict mode, the Update effect is used to record the time at - // which the placeholder timed out. - var currentTime = requestCurrentTime(); - finishedWork.stateNode = { timedOutAt: currentTime }; - } + case SuspenseComponent: { + if ((finishedWork.mode & StrictMode) === NoEffect) { + // In loose mode, a placeholder times out by scheduling a synchronous + // update in the commit phase. Use `updateQueue` field to signal that + // the Timeout needs to switch to the placeholder. We don't need an + // entire queue. Any non-null value works. + // $FlowFixMe - Intentionally using a value other than an UpdateQueue. + finishedWork.updateQueue = emptyObject$1; + scheduleWork(finishedWork, Sync); + } else { + // In strict mode, the Update effect is used to record the time at + // which the placeholder timed out. + var currentTime = requestCurrentTime(); + finishedWork.stateNode = { timedOutAt: currentTime }; } return; } @@ -12732,7 +12757,7 @@ function commitWork(current$$1, finishedWork) { case Profiler: { return; } - case PlaceholderComponent: { + case SuspenseComponent: { return; } default: { @@ -12832,7 +12857,6 @@ function throwException( sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( - enableSuspense && value !== null && typeof value === "object" && typeof value.then === "function" @@ -12849,7 +12873,7 @@ function throwException( var earliestTimeoutMs = -1; var startTimeMs = -1; do { - if (_workInProgress.tag === PlaceholderComponent) { + if (_workInProgress.tag === SuspenseComponent) { var current = _workInProgress.alternate; if ( current !== null && @@ -12867,7 +12891,7 @@ function throwException( // Do not search any further. break; } - var timeoutPropMs = _workInProgress.pendingProps.delayMs; + var timeoutPropMs = _workInProgress.pendingProps.maxDuration; if (typeof timeoutPropMs === "number") { if (timeoutPropMs <= 0) { earliestTimeoutMs = 0; @@ -12882,10 +12906,10 @@ function throwException( _workInProgress = _workInProgress.return; } while (_workInProgress !== null); - // Schedule the nearest Placeholder to re-render the timed out view. + // Schedule the nearest Suspense to re-render the timed out view. _workInProgress = returnFiber; do { - if (_workInProgress.tag === PlaceholderComponent) { + if (_workInProgress.tag === SuspenseComponent) { var didTimeout = _workInProgress.memoizedState; if (!didTimeout) { // Found the nearest boundary. @@ -12912,10 +12936,10 @@ function throwException( // If the boundary is outside of strict mode, we should *not* suspend // the commit. Pretend as if the suspended component rendered null and // keep rendering. In the commit phase, we'll schedule a subsequent - // synchronous update to re-render the Placeholder. + // synchronous update to re-render the Suspense. // // Note: It doesn't matter whether the component that suspended was - // inside a strict mode tree. If the Placeholder is outside of it, we + // inside a strict mode tree. If the Suspense is outside of it, we // should *not* suspend the commit. if ((_workInProgress.mode & StrictMode) === NoEffect) { _workInProgress.effectTag |= Update; @@ -13105,7 +13129,7 @@ function unwindWork(workInProgress, renderExpirationTime) { popHostContext(workInProgress); return null; } - case PlaceholderComponent: { + case SuspenseComponent: { var _effectTag3 = workInProgress.effectTag; if (_effectTag3 & ShouldCapture) { workInProgress.effectTag = (_effectTag3 & ~ShouldCapture) | DidCapture; @@ -14343,7 +14367,7 @@ function renderRoot(root, isYieldy, isExpired) { } } - if (enableSuspense && !isExpired && nextLatestAbsoluteTimeoutMs !== -1) { + if (!isExpired && nextLatestAbsoluteTimeoutMs !== -1) { // The tree was suspended. var _suspendedExpirationTime2 = expirationTime; markSuspendedPriorityLevel(root, _suspendedExpirationTime2); @@ -14507,41 +14531,39 @@ function renderDidError() { } function retrySuspendedRoot(root, fiber, suspendedTime) { - if (enableSuspense) { - var retryTime = void 0; + var retryTime = void 0; - if (isPriorityLevelSuspended(root, suspendedTime)) { - // Ping at the original level - retryTime = suspendedTime; + if (isPriorityLevelSuspended(root, suspendedTime)) { + // Ping at the original level + retryTime = suspendedTime; - markPingedPriorityLevel(root, retryTime); - } else { - // Placeholder already timed out. Compute a new expiration time - var currentTime = requestCurrentTime(); - retryTime = computeExpirationForFiber(currentTime, fiber); - markPendingPriorityLevel(root, retryTime); - } + markPingedPriorityLevel(root, retryTime); + } else { + // Suspense already timed out. Compute a new expiration time + var currentTime = requestCurrentTime(); + retryTime = computeExpirationForFiber(currentTime, fiber); + markPendingPriorityLevel(root, retryTime); + } - // TODO: If the placeholder fiber has already rendered the primary children - // without suspending (that is, all of the promises have already resolved), - // we should not trigger another update here. One case this happens is when - // we are in sync mode and a single promise is thrown both on initial render - // and on update; we attach two .then(retrySuspendedRoot) callbacks and each - // one performs Sync work, rerendering the Placeholder. + // TODO: If the placeholder fiber has already rendered the primary children + // without suspending (that is, all of the promises have already resolved), + // we should not trigger another update here. One case this happens is when + // we are in sync mode and a single promise is thrown both on initial render + // and on update; we attach two .then(retrySuspendedRoot) callbacks and each + // one performs Sync work, rerendering the Suspense. - if ((fiber.mode & ConcurrentMode) !== NoContext) { - if (root === nextRoot && nextRenderExpirationTime === suspendedTime) { - // Received a ping at the same priority level at which we're currently - // rendering. Restart from the root. - nextRoot = null; - } + if ((fiber.mode & ConcurrentMode) !== NoContext) { + if (root === nextRoot && nextRenderExpirationTime === suspendedTime) { + // Received a ping at the same priority level at which we're currently + // rendering. Restart from the root. + nextRoot = null; } + } - scheduleWorkToRoot(fiber, retryTime); - var rootExpirationTime = root.expirationTime; - if (rootExpirationTime !== NoWork) { - requestWork(root, rootExpirationTime); - } + scheduleWorkToRoot(fiber, retryTime); + var rootExpirationTime = root.expirationTime; + if (rootExpirationTime !== NoWork) { + requestWork(root, rootExpirationTime); } } @@ -14778,7 +14800,7 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - if (enableSuspense && msUntilTimeout === 0 && !shouldYield()) { + if (msUntilTimeout === 0 && !shouldYield()) { // Don't wait an additional tick. Commit the tree immediately. root.pendingCommitExpirationTime = suspendedExpirationTime; root.finishedWork = finishedWork; @@ -14796,17 +14818,15 @@ function onYield(root) { } function onTimeout(root, finishedWork, suspendedExpirationTime) { - if (enableSuspense) { - // The root timed out. Commit it. - root.pendingCommitExpirationTime = suspendedExpirationTime; - root.finishedWork = finishedWork; - // Read the current time before entering the commit phase. We can be - // certain this won't cause tearing related to batching of event updates - // because we're at the top of a timer event. - recomputeCurrentRendererTime(); - currentSchedulerTime = currentRendererTime; - flushRoot(root, suspendedExpirationTime); - } + // The root timed out. Commit it. + root.pendingCommitExpirationTime = suspendedExpirationTime; + root.finishedWork = finishedWork; + // Read the current time before entering the commit phase. We can be + // certain this won't cause tearing related to batching of event updates + // because we're at the top of a timer event. + recomputeCurrentRendererTime(); + currentSchedulerTime = currentRendererTime; + flushRoot(root, suspendedExpirationTime); } function onCommit(root, expirationTime) { @@ -15144,7 +15164,7 @@ function performWorkOnRoot(root, expirationTime, isExpired) { // If this root previously suspended, clear its existing timeout, since // we're about to try rendering again. var timeoutHandle = root.timeoutHandle; - if (enableSuspense && timeoutHandle !== noTimeout) { + if (timeoutHandle !== noTimeout) { root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above cancelTimeout(timeoutHandle); @@ -15168,7 +15188,7 @@ function performWorkOnRoot(root, expirationTime, isExpired) { // If this root previously suspended, clear its existing timeout, since // we're about to try rendering again. var _timeoutHandle = root.timeoutHandle; - if (enableSuspense && _timeoutHandle !== noTimeout) { + if (_timeoutHandle !== noTimeout) { root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above cancelTimeout(_timeoutHandle); @@ -15324,9 +15344,11 @@ function flushInteractiveUpdates$1() { // Might add PROFILE later. var didWarnAboutNestedUpdates = void 0; +var didWarnAboutFindNodeInStrictMode = void 0; { didWarnAboutNestedUpdates = false; + didWarnAboutFindNodeInStrictMode = {}; } function getContextForSubtree(parentComponent) { @@ -15442,6 +15464,64 @@ function findHostInstance$1(component) { return hostFiber.stateNode; } +function findHostInstanceWithWarning$1(component, methodName) { + { + var fiber = get$1(component); + if (fiber === undefined) { + if (typeof component.render === "function") { + invariant(false, "Unable to find node on an unmounted component."); + } else { + invariant( + false, + "Argument appears to not be a ReactComponent. Keys: %s", + Object.keys(component) + ); + } + } + var hostFiber = findCurrentHostFiber(fiber); + if (hostFiber === null) { + return null; + } + if (hostFiber.mode & StrictMode) { + var componentName = getComponentName(fiber.type) || "Component"; + if (!didWarnAboutFindNodeInStrictMode[componentName]) { + didWarnAboutFindNodeInStrictMode[componentName] = true; + if (fiber.mode & StrictMode) { + warningWithoutStack$1( + false, + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which is inside StrictMode. " + + "Instead, add a ref directly to the element you want to reference." + + "\n%s" + + "\n\nLearn more about using refs safely here:" + + "\nhttps://fb.me/react-strict-mode-find-node", + methodName, + methodName, + componentName, + getStackByFiberInDevAndProd(hostFiber) + ); + } else { + warningWithoutStack$1( + false, + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which renders StrictMode children. " + + "Instead, add a ref directly to the element you want to reference." + + "\n%s" + + "\n\nLearn more about using refs safely here:" + + "\nhttps://fb.me/react-strict-mode-find-node", + methodName, + methodName, + componentName, + getStackByFiberInDevAndProd(hostFiber) + ); + } + } + } + return hostFiber.stateNode; + } + return findHostInstance$1(component); +} + function createContainer(containerInfo, isConcurrent, hydrate) { return createFiberRoot(containerInfo, isConcurrent, hydrate); } @@ -15519,7 +15599,7 @@ function createPortal( // TODO: this is special because it gets imported during build. -var ReactVersion = "16.5.2"; +var ReactVersion = "16.6.0-alpha.8af6728"; // Modules provided by RN: var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { @@ -16029,6 +16109,7 @@ var getInspectorDataForViewTag = void 0; var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; var findHostInstance = findHostInstance$1; +var findHostInstanceWithWarning = findHostInstanceWithWarning$1; function findNodeHandle(componentOrHandle) { { @@ -16062,7 +16143,14 @@ function findNodeHandle(componentOrHandle) { if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { return componentOrHandle.canonical._nativeTag; } - var hostInstance = findHostInstance(componentOrHandle); + var hostInstance = void 0; + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findNodeHandle" + ); + } + if (hostInstance == null) { return hostInstance; } diff --git a/Libraries/Renderer/oss/ReactFabric-prod.js b/Libraries/Renderer/oss/ReactFabric-prod.js index 3cee2cbcae1788..9bd0a470b98875 100644 --- a/Libraries/Renderer/oss/ReactFabric-prod.js +++ b/Libraries/Renderer/oss/ReactFabric-prod.js @@ -1033,7 +1033,7 @@ var ReactSharedInternals = ? Symbol.for("react.concurrent_mode") : 60111, REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112, - REACT_PLACEHOLDER_TYPE = hasSymbol ? Symbol.for("react.placeholder") : 60113, + REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113, REACT_PURE_TYPE = hasSymbol ? Symbol.for("react.pure") : 60115, MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { @@ -1043,6 +1043,13 @@ function getIteratorFn(maybeIterable) { maybeIterable["@@iterator"]; return "function" === typeof maybeIterable ? maybeIterable : null; } +function getWrappedName(outerType, innerType, wrapperName) { + innerType = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + ("" !== innerType ? wrapperName + "(" + innerType + ")" : wrapperName) + ); +} function getComponentName(type) { if (null == type) return null; if ("function" === typeof type) return type.displayName || type.name || null; @@ -1058,8 +1065,8 @@ function getComponentName(type) { return "Profiler"; case REACT_STRICT_MODE_TYPE: return "StrictMode"; - case REACT_PLACEHOLDER_TYPE: - return "Placeholder"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; } if ("object" === typeof type) { switch (type.$$typeof) { @@ -1068,12 +1075,9 @@ function getComponentName(type) { case REACT_PROVIDER_TYPE: return "Context.Provider"; case REACT_FORWARD_REF_TYPE: - var renderFn = type.render; - renderFn = renderFn.displayName || renderFn.name || ""; - return ( - type.displayName || - ("" !== renderFn ? "ForwardRef(" + renderFn + ")" : "ForwardRef") - ); + return getWrappedName(type, type.render, "ForwardRef"); + case REACT_PURE_TYPE: + return getWrappedName(type, type.render, "Pure"); } if ( "function" === typeof type.then && @@ -1592,7 +1596,9 @@ function createTextInstance( ) }; } -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; +var scheduleTimeout = setTimeout, + cancelTimeout = clearTimeout, + BEFORE_SLASH_RE = /^(.*)[\\\/]/; function getStackByFiberInDevAndProd(workInProgress) { var info = ""; do { @@ -1840,7 +1846,7 @@ function createFiberFromElement(element, mode, expirationTime) { (type.expirationTime = expirationTime), type ); - case REACT_PLACEHOLDER_TYPE: + case REACT_SUSPENSE_TYPE: fiberTag = 16; break; default: @@ -1912,6 +1918,43 @@ function markPendingPriorityLevel(root, expirationTime) { (root.latestPendingTime = expirationTime); findNextExpirationTimeToWorkOn(expirationTime, root); } +function markSuspendedPriorityLevel(root, suspendedTime) { + root.didError = !1; + var latestPingedTime = root.latestPingedTime; + 0 !== latestPingedTime && + latestPingedTime <= suspendedTime && + (root.latestPingedTime = 0); + latestPingedTime = root.earliestPendingTime; + var latestPendingTime = root.latestPendingTime; + latestPingedTime === suspendedTime + ? (root.earliestPendingTime = + latestPendingTime === suspendedTime + ? (root.latestPendingTime = 0) + : latestPendingTime) + : latestPendingTime === suspendedTime && + (root.latestPendingTime = latestPingedTime); + latestPingedTime = root.earliestSuspendedTime; + latestPendingTime = root.latestSuspendedTime; + 0 === latestPingedTime + ? (root.earliestSuspendedTime = root.latestSuspendedTime = suspendedTime) + : latestPingedTime > suspendedTime + ? (root.earliestSuspendedTime = suspendedTime) + : latestPendingTime < suspendedTime && + (root.latestSuspendedTime = suspendedTime); + findNextExpirationTimeToWorkOn(suspendedTime, root); +} +function findEarliestOutstandingPriorityLevel(root, renderExpirationTime) { + var earliestPendingTime = root.earliestPendingTime; + root = root.earliestSuspendedTime; + if ( + 0 === renderExpirationTime || + (0 !== earliestPendingTime && earliestPendingTime < renderExpirationTime) + ) + renderExpirationTime = earliestPendingTime; + if (0 === renderExpirationTime || (0 !== root && root < renderExpirationTime)) + renderExpirationTime = root; + return renderExpirationTime; +} function findNextExpirationTimeToWorkOn(completedExpirationTime, root) { var earliestSuspendedTime = root.earliestSuspendedTime, latestSuspendedTime = root.latestSuspendedTime, @@ -3265,7 +3308,8 @@ function updatePureComponent( updateExpirationTime, renderExpirationTime ) { - var render = Component.render; + var render = Component.render, + ref = workInProgress.ref; if ( null !== current$$1 && (0 === updateExpirationTime || @@ -3273,7 +3317,8 @@ function updatePureComponent( ((updateExpirationTime = current$$1.memoizedProps), (Component = Component.compare), (Component = null !== Component ? Component : shallowEqual), - Component(updateExpirationTime, nextProps)) + workInProgress.ref === current$$1.ref && + Component(updateExpirationTime, nextProps)) ) return bailoutOnAlreadyFinishedWork( current$$1, @@ -3281,7 +3326,7 @@ function updatePureComponent( renderExpirationTime ); prepareToReadContext(workInProgress, renderExpirationTime); - render = render(nextProps); + render = render(nextProps, ref); workInProgress.effectTag |= 1; reconcileChildren(current$$1, workInProgress, render, renderExpirationTime); workInProgress.memoizedProps = nextProps; @@ -3938,7 +3983,46 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { null ); case 16: - return null; + return ( + (Component = workInProgress.pendingProps), + (props = 0 === (workInProgress.effectTag & 64)), + null !== current$$1 && null !== workInProgress.updateQueue + ? ((workInProgress.updateQueue = null), (props = !0)) + : (props = !props), + 0 !== (workInProgress.mode & 2) && + (props + ? (workInProgress.effectTag |= 4) + : (workInProgress.stateNode = null)), + (updateExpirationTime = Component.children), + (updateExpirationTime = + "function" === typeof updateExpirationTime + ? updateExpirationTime(props) + : props + ? Component.fallback + : updateExpirationTime), + null !== current$$1 && props !== workInProgress.memoizedState + ? ((workInProgress.child = reconcileChildFibers( + workInProgress, + current$$1.child, + null, + renderExpirationTime + )), + (workInProgress.child = reconcileChildFibers( + workInProgress, + null, + updateExpirationTime, + renderExpirationTime + ))) + : reconcileChildren( + current$$1, + workInProgress, + updateExpirationTime, + renderExpirationTime + ), + (workInProgress.memoizedProps = Component), + (workInProgress.memoizedState = props), + workInProgress.child + ); case 6: return ( pushHostContainer( @@ -4317,6 +4401,7 @@ function logCapturedError(capturedError) { : Error("Unspecified error at:" + componentStack); ExceptionsManager.handleException(error, !1); } +var emptyObject$1 = {}; function logError(boundary, errorInfo) { var source = errorInfo.source, stack = errorInfo.stack; @@ -4376,6 +4461,9 @@ function commitWork(current$$1, finishedWork) { ); } } +function NoopComponent() { + return null; +} function createRootErrorUpdate(fiber, errorInfo, expirationTime) { expirationTime = createUpdate(expirationTime); expirationTime.tag = 3; @@ -4469,6 +4557,7 @@ var Dispatcher = { readContext: readContext }, nextUnitOfWork = null, nextRoot = null, nextRenderExpirationTime = 0, + nextLatestAbsoluteTimeoutMs = -1, nextRenderDidError = !1, nextEffect = null, isCommitting$1 = !1, @@ -4513,6 +4602,7 @@ function resetStack() { } nextRoot = null; nextRenderExpirationTime = 0; + nextLatestAbsoluteTimeoutMs = -1; nextRenderDidError = !1; nextUnitOfWork = null; } @@ -4719,28 +4809,28 @@ function performUnitOfWork(workInProgress) { ReactCurrentOwner$2.current = null; return next; } -function renderRoot(root, isYieldy, isExpired) { +function renderRoot(root$jscomp$0, isYieldy, isExpired) { invariant( !isWorking, "renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue." ); isWorking = !0; ReactCurrentOwner$2.currentDispatcher = Dispatcher; - var expirationTime = root.nextExpirationTimeToWorkOn; + var expirationTime = root$jscomp$0.nextExpirationTimeToWorkOn; if ( expirationTime !== nextRenderExpirationTime || - root !== nextRoot || + root$jscomp$0 !== nextRoot || null === nextUnitOfWork ) resetStack(), - (nextRoot = root), + (nextRoot = root$jscomp$0), (nextRenderExpirationTime = expirationTime), (nextUnitOfWork = createWorkInProgress( nextRoot.current, null, nextRenderExpirationTime )), - (root.pendingCommitExpirationTime = 0); + (root$jscomp$0.pendingCommitExpirationTime = 0); var didFatal = !1; do { try { @@ -4763,54 +4853,145 @@ function renderRoot(root, isYieldy, isExpired) { if (null === returnFiber) (didFatal = !0), onUncaughtError(thrownValue); else { a: { - var returnFiber$jscomp$0 = returnFiber, + var root = root$jscomp$0, + returnFiber$jscomp$0 = returnFiber, sourceFiber$jscomp$0 = sourceFiber, value = thrownValue; returnFiber = nextRenderExpirationTime; sourceFiber$jscomp$0.effectTag |= 512; sourceFiber$jscomp$0.firstEffect = sourceFiber$jscomp$0.lastEffect = null; + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var thenable = value; + value = returnFiber$jscomp$0; + var earliestTimeoutMs = -1, + startTimeMs = -1; + do { + if (16 === value.tag) { + var current = value.alternate; + if ( + null !== current && + !0 === current.memoizedState && + null !== current.stateNode + ) { + startTimeMs = 10 * (current.stateNode.timedOutAt - 2); + break; + } + current = value.pendingProps.maxDuration; + if ("number" === typeof current) + if (0 >= current) earliestTimeoutMs = 0; + else if ( + -1 === earliestTimeoutMs || + current < earliestTimeoutMs + ) + earliestTimeoutMs = current; + } + value = value.return; + } while (null !== value); + value = returnFiber$jscomp$0; + do { + if (16 === value.tag && !value.memoizedState) { + returnFiber$jscomp$0 = retrySuspendedRoot.bind( + null, + root, + value, + 0 === (value.mode & 1) ? 1 : returnFiber + ); + thenable.then(returnFiber$jscomp$0, returnFiber$jscomp$0); + if (0 === (value.mode & 2)) { + value.effectTag |= 4; + reconcileChildren( + sourceFiber$jscomp$0.alternate, + sourceFiber$jscomp$0, + null, + returnFiber + ); + sourceFiber$jscomp$0.effectTag &= -513; + 4 === sourceFiber$jscomp$0.tag && + (sourceFiber$jscomp$0.tag = 0); + if ( + 2 === sourceFiber$jscomp$0.tag || + 3 === sourceFiber$jscomp$0.tag + ) + (sourceFiber$jscomp$0.effectTag &= -421), + null === sourceFiber$jscomp$0.alternate && + ((sourceFiber$jscomp$0.tag = 0), + (sourceFiber$jscomp$0.type = NoopComponent)); + break a; + } + -1 === earliestTimeoutMs + ? (root = 1073741823) + : (-1 === startTimeMs && + (startTimeMs = + 10 * + (findEarliestOutstandingPriorityLevel( + root, + returnFiber + ) - + 2) - + 5e3), + (root = startTimeMs + earliestTimeoutMs)); + 0 <= root && + nextLatestAbsoluteTimeoutMs < root && + (nextLatestAbsoluteTimeoutMs = root); + value.effectTag |= 1024; + value.expirationTime = returnFiber; + break a; + } + value = value.return; + } while (null !== value); + value = Error( + "An update was suspended, but no placeholder UI was provided." + ); + } nextRenderDidError = !0; value = createCapturedValue(value, sourceFiber$jscomp$0); + root = returnFiber$jscomp$0; do { - switch (returnFiber$jscomp$0.tag) { + switch (root.tag) { case 5: - returnFiber$jscomp$0.effectTag |= 1024; - returnFiber$jscomp$0.expirationTime = returnFiber; + sourceFiber$jscomp$0 = value; + root.effectTag |= 1024; + root.expirationTime = returnFiber; returnFiber = createRootErrorUpdate( - returnFiber$jscomp$0, - value, + root, + sourceFiber$jscomp$0, returnFiber ); - enqueueCapturedUpdate(returnFiber$jscomp$0, returnFiber); + enqueueCapturedUpdate(root, returnFiber); break a; case 2: case 3: - sourceFiber$jscomp$0 = value; - var ctor = returnFiber$jscomp$0.type, - instance = returnFiber$jscomp$0.stateNode; if ( - 0 === (returnFiber$jscomp$0.effectTag & 64) && - ("function" === typeof ctor.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has( - instance - )))) + ((sourceFiber$jscomp$0 = value), + (returnFiber$jscomp$0 = root.type), + (thenable = root.stateNode), + 0 === (root.effectTag & 64) && + ("function" === + typeof returnFiber$jscomp$0.getDerivedStateFromError || + (null !== thenable && + "function" === typeof thenable.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has( + thenable + ))))) ) { - returnFiber$jscomp$0.effectTag |= 1024; - returnFiber$jscomp$0.expirationTime = returnFiber; + root.effectTag |= 1024; + root.expirationTime = returnFiber; returnFiber = createClassErrorUpdate( - returnFiber$jscomp$0, + root, sourceFiber$jscomp$0, returnFiber ); - enqueueCapturedUpdate(returnFiber$jscomp$0, returnFiber); + enqueueCapturedUpdate(root, returnFiber); break a; } } - returnFiber$jscomp$0 = returnFiber$jscomp$0.return; - } while (null !== returnFiber$jscomp$0); + root = root.return; + } while (null !== root); } nextUnitOfWork = completeUnitOfWork(sourceFiber); continue; @@ -4821,58 +5002,61 @@ function renderRoot(root, isYieldy, isExpired) { } while (1); isWorking = !1; lastContextWithAllBitsObserved = lastContextDependency = currentlyRenderingFiber = ReactCurrentOwner$2.currentDispatcher = null; - if (didFatal) (nextRoot = null), (root.finishedWork = null); - else if (null !== nextUnitOfWork) root.finishedWork = null; + if (didFatal) (nextRoot = null), (root$jscomp$0.finishedWork = null); + else if (null !== nextUnitOfWork) root$jscomp$0.finishedWork = null; else { - isYieldy = root.current.alternate; + isYieldy = root$jscomp$0.current.alternate; invariant( null !== isYieldy, "Finished root should have a work-in-progress. This error is likely caused by a bug in React. Please file an issue." ); nextRoot = null; if (nextRenderDidError) { - didFatal = root.latestPendingTime; - sourceFiber = root.latestSuspendedTime; - returnFiber = root.latestPingedTime; + didFatal = root$jscomp$0.latestPendingTime; + sourceFiber = root$jscomp$0.latestSuspendedTime; + returnFiber = root$jscomp$0.latestPingedTime; if ( (0 !== didFatal && didFatal > expirationTime) || (0 !== sourceFiber && sourceFiber > expirationTime) || (0 !== returnFiber && returnFiber > expirationTime) ) { - root.didError = !1; - isExpired = root.latestPingedTime; - 0 !== isExpired && - isExpired <= expirationTime && - (root.latestPingedTime = 0); - isExpired = root.earliestPendingTime; - isYieldy = root.latestPendingTime; - isExpired === expirationTime - ? (root.earliestPendingTime = - isYieldy === expirationTime - ? (root.latestPendingTime = 0) - : isYieldy) - : isYieldy === expirationTime && (root.latestPendingTime = isExpired); - isExpired = root.earliestSuspendedTime; - isYieldy = root.latestSuspendedTime; - 0 === isExpired - ? (root.earliestSuspendedTime = root.latestSuspendedTime = expirationTime) - : isExpired > expirationTime - ? (root.earliestSuspendedTime = expirationTime) - : isYieldy < expirationTime && - (root.latestSuspendedTime = expirationTime); - findNextExpirationTimeToWorkOn(expirationTime, root); - root.expirationTime = root.expirationTime; + markSuspendedPriorityLevel(root$jscomp$0, expirationTime); + onSuspend( + root$jscomp$0, + isYieldy, + expirationTime, + root$jscomp$0.expirationTime, + -1 + ); return; } - if (!root.didError && !isExpired) { - root.didError = !0; - root.nextExpirationTimeToWorkOn = expirationTime; - root.expirationTime = 1; + if (!root$jscomp$0.didError && !isExpired) { + root$jscomp$0.didError = !0; + expirationTime = root$jscomp$0.nextExpirationTimeToWorkOn = expirationTime; + isExpired = root$jscomp$0.expirationTime = 1; + onSuspend(root$jscomp$0, isYieldy, expirationTime, isExpired, -1); return; } } - root.pendingCommitExpirationTime = expirationTime; - root.finishedWork = isYieldy; + isExpired || -1 === nextLatestAbsoluteTimeoutMs + ? ((root$jscomp$0.pendingCommitExpirationTime = expirationTime), + (root$jscomp$0.finishedWork = isYieldy)) + : (markSuspendedPriorityLevel(root$jscomp$0, expirationTime), + (isExpired = + 10 * + (findEarliestOutstandingPriorityLevel(root$jscomp$0, expirationTime) - + 2)), + isExpired < nextLatestAbsoluteTimeoutMs && + (nextLatestAbsoluteTimeoutMs = isExpired), + (isExpired = 10 * (requestCurrentTime() - 2)), + (isExpired = nextLatestAbsoluteTimeoutMs - isExpired), + onSuspend( + root$jscomp$0, + isYieldy, + expirationTime, + root$jscomp$0.expirationTime, + 0 > isExpired ? 0 : isExpired + )); } } function captureCommitPhaseError(fiber, error) { @@ -4945,7 +5129,33 @@ function computeExpirationForFiber(currentTime, fiber) { (lowestPriorityPendingInteractiveExpirationTime = currentTime); return currentTime; } -function scheduleWork(fiber, expirationTime) { +function retrySuspendedRoot(root, fiber, suspendedTime) { + var retryTime = root.earliestSuspendedTime; + var latestSuspendedTime = root.latestSuspendedTime; + if ( + 0 !== retryTime && + suspendedTime >= retryTime && + suspendedTime <= latestSuspendedTime + ) { + latestSuspendedTime = retryTime = suspendedTime; + root.didError = !1; + var latestPingedTime = root.latestPingedTime; + if (0 === latestPingedTime || latestPingedTime < latestSuspendedTime) + root.latestPingedTime = latestSuspendedTime; + findNextExpirationTimeToWorkOn(latestSuspendedTime, root); + } else + (retryTime = requestCurrentTime()), + (retryTime = computeExpirationForFiber(retryTime, fiber)), + markPendingPriorityLevel(root, retryTime); + 0 !== (fiber.mode & 1) && + root === nextRoot && + nextRenderExpirationTime === suspendedTime && + (nextRoot = null); + scheduleWorkToRoot(fiber, retryTime); + fiber = root.expirationTime; + 0 !== fiber && requestWork(root, fiber); +} +function scheduleWorkToRoot(fiber, expirationTime) { if (0 === fiber.expirationTime || fiber.expirationTime > expirationTime) fiber.expirationTime = expirationTime; var alternate = fiber.alternate; @@ -4974,44 +5184,24 @@ function scheduleWork(fiber, expirationTime) { } node = node.return; } - fiber = null === root ? null : root; - if (null !== fiber) { - !isWorking && + return null === root ? null : root; +} +function scheduleWork(fiber, expirationTime) { + fiber = scheduleWorkToRoot(fiber, expirationTime); + null !== fiber && + (!isWorking && 0 !== nextRenderExpirationTime && expirationTime < nextRenderExpirationTime && - resetStack(); - markPendingPriorityLevel(fiber, expirationTime); - if (!isWorking || isCommitting$1 || nextRoot !== fiber) { - expirationTime = fiber.expirationTime; - if (null === fiber.nextScheduledRoot) - (fiber.expirationTime = expirationTime), - null === lastScheduledRoot - ? ((firstScheduledRoot = lastScheduledRoot = fiber), - (fiber.nextScheduledRoot = fiber)) - : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = fiber), - (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); - else if ( - ((alternate = fiber.expirationTime), - 0 === alternate || expirationTime < alternate) - ) - fiber.expirationTime = expirationTime; - isRendering || - (isBatchingUpdates - ? isUnbatchingUpdates && - ((nextFlushedRoot = fiber), - (nextFlushedExpirationTime = 1), - performWorkOnRoot(fiber, 1, !0)) - : 1 === expirationTime - ? performWork(1, null) - : scheduleCallbackWithExpirationTime(fiber, expirationTime)); - } + resetStack(), + markPendingPriorityLevel(fiber, expirationTime), + (isWorking && !isCommitting$1 && nextRoot === fiber) || + requestWork(fiber, fiber.expirationTime), nestedUpdateCount > NESTED_UPDATE_LIMIT && ((nestedUpdateCount = 0), 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." - )); - } + ))); } var firstScheduledRoot = null, lastScheduledRoot = null, @@ -5050,6 +5240,37 @@ function scheduleCallbackWithExpirationTime(root, expirationTime) { scheduledCallback = performAsyncWork; callbackID = setTimeout(setTimeoutCallback, 1); } +function onSuspend( + root, + finishedWork, + suspendedExpirationTime, + rootExpirationTime, + msUntilTimeout +) { + root.expirationTime = rootExpirationTime; + 0 !== msUntilTimeout || shouldYield() + ? 0 < msUntilTimeout && + (root.timeoutHandle = scheduleTimeout( + onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), + msUntilTimeout + )) + : ((root.pendingCommitExpirationTime = suspendedExpirationTime), + (root.finishedWork = finishedWork)); +} +function onTimeout(root, finishedWork, suspendedExpirationTime) { + root.pendingCommitExpirationTime = suspendedExpirationTime; + root.finishedWork = finishedWork; + recomputeCurrentRendererTime(); + currentSchedulerTime = currentRendererTime; + invariant( + !isRendering, + "work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method." + ); + nextFlushedRoot = root; + nextFlushedExpirationTime = suspendedExpirationTime; + performWorkOnRoot(root, suspendedExpirationTime, !0); + performWork(1, null); +} function requestCurrentTime() { if (isRendering) return currentSchedulerTime; findHighestPriorityRoot(); @@ -5061,6 +5282,32 @@ function requestCurrentTime() { (currentSchedulerTime = currentRendererTime); return currentSchedulerTime; } +function requestWork(root, expirationTime) { + if (null === root.nextScheduledRoot) + (root.expirationTime = expirationTime), + null === lastScheduledRoot + ? ((firstScheduledRoot = lastScheduledRoot = root), + (root.nextScheduledRoot = root)) + : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = root), + (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); + else { + var remainingExpirationTime = root.expirationTime; + if ( + 0 === remainingExpirationTime || + expirationTime < remainingExpirationTime + ) + root.expirationTime = expirationTime; + } + isRendering || + (isBatchingUpdates + ? isUnbatchingUpdates && + ((nextFlushedRoot = root), + (nextFlushedExpirationTime = 1), + performWorkOnRoot(root, 1, !0)) + : 1 === expirationTime + ? performWork(1, null) + : scheduleCallbackWithExpirationTime(root, expirationTime)); +} function findHighestPriorityRoot() { var highestPriorityWork = 0, highestPriorityRoot = null; @@ -5197,6 +5444,9 @@ function performWorkOnRoot(root, expirationTime, isExpired) { null !== finishedWork ? completeRoot$1(root, finishedWork, expirationTime) : ((root.finishedWork = null), + (finishedWork = root.timeoutHandle), + -1 !== finishedWork && + ((root.timeoutHandle = -1), cancelTimeout(finishedWork)), renderRoot(root, !1, isExpired), (finishedWork = root.finishedWork), null !== finishedWork && @@ -5206,6 +5456,9 @@ function performWorkOnRoot(root, expirationTime, isExpired) { null !== finishedWork ? completeRoot$1(root, finishedWork, expirationTime) : ((root.finishedWork = null), + (finishedWork = root.timeoutHandle), + -1 !== finishedWork && + ((root.timeoutHandle = -1), cancelTimeout(finishedWork)), renderRoot(root, !0, isExpired), (finishedWork = root.finishedWork), null !== finishedWork && @@ -5507,6 +5760,13 @@ function completeRoot$1(root, finishedWork$jscomp$0, expirationTime) { case 15: break; case 16: + if (0 === (instance$jscomp$0.mode & 2)) + (instance$jscomp$0.updateQueue = emptyObject$1), + scheduleWork(instance$jscomp$0, 1); + else { + var currentTime = requestCurrentTime(); + instance$jscomp$0.stateNode = { timedOutAt: currentTime }; + } break; default: invariant( @@ -5922,7 +6182,7 @@ var roots = new Map(), findFiberByHostInstance: getInstanceFromInstance, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.5.2", + version: "16.6.0-alpha.8af6728", rendererPackageName: "react-native-renderer" }); var ReactFabric$2 = { default: ReactFabric }, diff --git a/Libraries/Renderer/oss/ReactFabric-profiling.js b/Libraries/Renderer/oss/ReactFabric-profiling.js index 1723349f630569..0ca23993737641 100644 --- a/Libraries/Renderer/oss/ReactFabric-profiling.js +++ b/Libraries/Renderer/oss/ReactFabric-profiling.js @@ -1034,7 +1034,7 @@ var ReactSharedInternals = ? Symbol.for("react.concurrent_mode") : 60111, REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112, - REACT_PLACEHOLDER_TYPE = hasSymbol ? Symbol.for("react.placeholder") : 60113, + REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113, REACT_PURE_TYPE = hasSymbol ? Symbol.for("react.pure") : 60115, MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { @@ -1044,6 +1044,13 @@ function getIteratorFn(maybeIterable) { maybeIterable["@@iterator"]; return "function" === typeof maybeIterable ? maybeIterable : null; } +function getWrappedName(outerType, innerType, wrapperName) { + innerType = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + ("" !== innerType ? wrapperName + "(" + innerType + ")" : wrapperName) + ); +} function getComponentName(type) { if (null == type) return null; if ("function" === typeof type) return type.displayName || type.name || null; @@ -1059,8 +1066,8 @@ function getComponentName(type) { return "Profiler"; case REACT_STRICT_MODE_TYPE: return "StrictMode"; - case REACT_PLACEHOLDER_TYPE: - return "Placeholder"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; } if ("object" === typeof type) { switch (type.$$typeof) { @@ -1069,12 +1076,9 @@ function getComponentName(type) { case REACT_PROVIDER_TYPE: return "Context.Provider"; case REACT_FORWARD_REF_TYPE: - var renderFn = type.render; - renderFn = renderFn.displayName || renderFn.name || ""; - return ( - type.displayName || - ("" !== renderFn ? "ForwardRef(" + renderFn + ")" : "ForwardRef") - ); + return getWrappedName(type, type.render, "ForwardRef"); + case REACT_PURE_TYPE: + return getWrappedName(type, type.render, "Pure"); } if ( "function" === typeof type.then && @@ -1594,6 +1598,7 @@ function createTextInstance( }; } var scheduleTimeout = setTimeout, + cancelTimeout = clearTimeout, BEFORE_SLASH_RE = /^(.*)[\\\/]/; function getStackByFiberInDevAndProd(workInProgress) { var info = ""; @@ -1850,7 +1855,7 @@ function createFiberFromElement(element, mode, expirationTime) { (type.expirationTime = expirationTime), type ); - case REACT_PLACEHOLDER_TYPE: + case REACT_SUSPENSE_TYPE: fiberTag = 16; break; default: @@ -1986,6 +1991,18 @@ function markSuspendedPriorityLevel(root, suspendedTime) { (root.latestSuspendedTime = suspendedTime); findNextExpirationTimeToWorkOn(suspendedTime, root); } +function findEarliestOutstandingPriorityLevel(root, renderExpirationTime) { + var earliestPendingTime = root.earliestPendingTime; + root = root.earliestSuspendedTime; + if ( + 0 === renderExpirationTime || + (0 !== earliestPendingTime && earliestPendingTime < renderExpirationTime) + ) + renderExpirationTime = earliestPendingTime; + if (0 === renderExpirationTime || (0 !== root && root < renderExpirationTime)) + renderExpirationTime = root; + return renderExpirationTime; +} function findNextExpirationTimeToWorkOn(completedExpirationTime, root) { var earliestSuspendedTime = root.earliestSuspendedTime, latestSuspendedTime = root.latestSuspendedTime, @@ -3349,7 +3366,8 @@ function updatePureComponent( updateExpirationTime, renderExpirationTime ) { - var render = Component.render; + var render = Component.render, + ref = workInProgress.ref; if ( null !== current$$1 && (0 === updateExpirationTime || @@ -3357,7 +3375,8 @@ function updatePureComponent( ((updateExpirationTime = current$$1.memoizedProps), (Component = Component.compare), (Component = null !== Component ? Component : shallowEqual), - Component(updateExpirationTime, nextProps)) + workInProgress.ref === current$$1.ref && + Component(updateExpirationTime, nextProps)) ) return bailoutOnAlreadyFinishedWork( current$$1, @@ -3365,7 +3384,7 @@ function updatePureComponent( renderExpirationTime ); prepareToReadContext(workInProgress, renderExpirationTime); - render = render(nextProps); + render = render(nextProps, ref); workInProgress.effectTag |= 1; reconcileChildren(current$$1, workInProgress, render, renderExpirationTime); workInProgress.memoizedProps = nextProps; @@ -4030,7 +4049,46 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { null ); case 16: - return null; + return ( + (Component = workInProgress.pendingProps), + (props = 0 === (workInProgress.effectTag & 64)), + null !== current$$1 && null !== workInProgress.updateQueue + ? ((workInProgress.updateQueue = null), (props = !0)) + : (props = !props), + 0 !== (workInProgress.mode & 2) && + (props + ? (workInProgress.effectTag |= 4) + : (workInProgress.stateNode = null)), + (updateExpirationTime = Component.children), + (updateExpirationTime = + "function" === typeof updateExpirationTime + ? updateExpirationTime(props) + : props + ? Component.fallback + : updateExpirationTime), + null !== current$$1 && props !== workInProgress.memoizedState + ? ((workInProgress.child = reconcileChildFibers( + workInProgress, + current$$1.child, + null, + renderExpirationTime + )), + (workInProgress.child = reconcileChildFibers( + workInProgress, + null, + updateExpirationTime, + renderExpirationTime + ))) + : reconcileChildren( + current$$1, + workInProgress, + updateExpirationTime, + renderExpirationTime + ), + (workInProgress.memoizedProps = Component), + (workInProgress.memoizedState = props), + workInProgress.child + ); case 6: return ( pushHostContainer( @@ -4410,6 +4468,7 @@ function logCapturedError(capturedError) { : Error("Unspecified error at:" + componentStack); ExceptionsManager.handleException(error, !1); } +var emptyObject$1 = {}; function logError(boundary, errorInfo) { var source = errorInfo.source, stack = errorInfo.stack; @@ -4469,6 +4528,9 @@ function commitWork(current$$1, finishedWork) { ); } } +function NoopComponent() { + return null; +} function createRootErrorUpdate(fiber, errorInfo, expirationTime) { expirationTime = createUpdate(expirationTime); expirationTime.tag = 3; @@ -4516,39 +4578,120 @@ function throwException( ) { sourceFiber.effectTag |= 512; sourceFiber.firstEffect = sourceFiber.lastEffect = null; + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var thenable = value; + value = returnFiber; + var earliestTimeoutMs = -1, + startTimeMs = -1; + do { + if (16 === value.tag) { + var current = value.alternate; + if ( + null !== current && + !0 === current.memoizedState && + null !== current.stateNode + ) { + startTimeMs = 10 * (current.stateNode.timedOutAt - 2); + break; + } + current = value.pendingProps.maxDuration; + if ("number" === typeof current) + if (0 >= current) earliestTimeoutMs = 0; + else if (-1 === earliestTimeoutMs || current < earliestTimeoutMs) + earliestTimeoutMs = current; + } + value = value.return; + } while (null !== value); + value = returnFiber; + do { + if (16 === value.tag && !value.memoizedState) { + returnFiber = retrySuspendedRoot.bind( + null, + root, + value, + 0 === (value.mode & 1) ? 1 : renderExpirationTime + ); + returnFiber = tracing.unstable_wrap(returnFiber); + thenable.then(returnFiber, returnFiber); + if (0 === (value.mode & 2)) { + value.effectTag |= 4; + reconcileChildren( + sourceFiber.alternate, + sourceFiber, + null, + renderExpirationTime + ); + sourceFiber.effectTag &= -513; + 4 === sourceFiber.tag && (sourceFiber.tag = 0); + if (2 === sourceFiber.tag || 3 === sourceFiber.tag) + (sourceFiber.effectTag &= -421), + null === sourceFiber.alternate && + ((sourceFiber.tag = 0), (sourceFiber.type = NoopComponent)); + return; + } + -1 === earliestTimeoutMs + ? (root = 1073741823) + : (-1 === startTimeMs && + (startTimeMs = + 10 * + (findEarliestOutstandingPriorityLevel( + root, + renderExpirationTime + ) - + 2) - + 5e3), + (root = startTimeMs + earliestTimeoutMs)); + 0 <= root && + nextLatestAbsoluteTimeoutMs < root && + (nextLatestAbsoluteTimeoutMs = root); + value.effectTag |= 1024; + value.expirationTime = renderExpirationTime; + return; + } + value = value.return; + } while (null !== value); + value = Error( + "An update was suspended, but no placeholder UI was provided." + ); + } nextRenderDidError = !0; value = createCapturedValue(value, sourceFiber); root = returnFiber; do { switch (root.tag) { case 5: + sourceFiber = value; root.effectTag |= 1024; root.expirationTime = renderExpirationTime; renderExpirationTime = createRootErrorUpdate( root, - value, + sourceFiber, renderExpirationTime ); enqueueCapturedUpdate(root, renderExpirationTime); return; case 2: case 3: - returnFiber = value; - sourceFiber = root.type; - var instance = root.stateNode; if ( + ((sourceFiber = value), + (returnFiber = root.type), + (thenable = root.stateNode), 0 === (root.effectTag & 64) && - ("function" === typeof sourceFiber.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) + ("function" === typeof returnFiber.getDerivedStateFromError || + (null !== thenable && + "function" === typeof thenable.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(thenable))))) ) { root.effectTag |= 1024; root.expirationTime = renderExpirationTime; renderExpirationTime = createClassErrorUpdate( root, - returnFiber, + sourceFiber, renderExpirationTime ); enqueueCapturedUpdate(root, renderExpirationTime); @@ -4618,6 +4761,7 @@ var isWorking = !1, nextUnitOfWork = null, nextRoot = null, nextRenderExpirationTime = 0, + nextLatestAbsoluteTimeoutMs = -1, nextRenderDidError = !1, nextEffect = null, isCommitting$1 = !1, @@ -4662,6 +4806,7 @@ function resetStack() { } nextRoot = null; nextRenderExpirationTime = 0; + nextLatestAbsoluteTimeoutMs = -1; nextRenderDidError = !1; nextUnitOfWork = null; } @@ -4863,6 +5008,13 @@ function commitAllLifeCycles( ); break; case 16: + 0 === (finishedWork.mode & 2) + ? ((finishedWork.updateQueue = emptyObject$1), + scheduleWork(finishedWork, 1)) + : ((committedExpirationTime = requestCurrentTime()), + (finishedWork.stateNode = { + timedOutAt: committedExpirationTime + })); break; default: invariant( @@ -5375,7 +5527,23 @@ function renderRoot(root, isYieldy, isExpired) { return; } } - onComplete(root, isYieldy, expirationTime); + isExpired || -1 === nextLatestAbsoluteTimeoutMs + ? onComplete(root, isYieldy, expirationTime) + : (markSuspendedPriorityLevel(root, expirationTime), + (isExpired = + 10 * + (findEarliestOutstandingPriorityLevel(root, expirationTime) - 2)), + isExpired < nextLatestAbsoluteTimeoutMs && + (nextLatestAbsoluteTimeoutMs = isExpired), + (isExpired = 10 * (requestCurrentTime() - 2)), + (isExpired = nextLatestAbsoluteTimeoutMs - isExpired), + onSuspend( + root, + isYieldy, + expirationTime, + root.expirationTime, + 0 > isExpired ? 0 : isExpired + )); } } function captureCommitPhaseError(fiber, error) { @@ -5448,6 +5616,32 @@ function computeExpirationForFiber(currentTime, fiber) { (lowestPriorityPendingInteractiveExpirationTime = currentTime); return currentTime; } +function retrySuspendedRoot(root, fiber, suspendedTime) { + var retryTime = root.earliestSuspendedTime; + var latestSuspendedTime = root.latestSuspendedTime; + if ( + 0 !== retryTime && + suspendedTime >= retryTime && + suspendedTime <= latestSuspendedTime + ) { + latestSuspendedTime = retryTime = suspendedTime; + root.didError = !1; + var latestPingedTime = root.latestPingedTime; + if (0 === latestPingedTime || latestPingedTime < latestSuspendedTime) + root.latestPingedTime = latestSuspendedTime; + findNextExpirationTimeToWorkOn(latestSuspendedTime, root); + } else + (retryTime = requestCurrentTime()), + (retryTime = computeExpirationForFiber(retryTime, fiber)), + markPendingPriorityLevel(root, retryTime); + 0 !== (fiber.mode & 1) && + root === nextRoot && + nextRenderExpirationTime === suspendedTime && + (nextRoot = null); + scheduleWorkToRoot(fiber, retryTime); + fiber = root.expirationTime; + 0 !== fiber && requestWork(root, fiber); +} function scheduleWorkToRoot(fiber, expirationTime) { if (0 === fiber.expirationTime || fiber.expirationTime > expirationTime) fiber.expirationTime = expirationTime; @@ -5502,46 +5696,20 @@ function scheduleWorkToRoot(fiber, expirationTime) { } function scheduleWork(fiber, expirationTime) { fiber = scheduleWorkToRoot(fiber, expirationTime); - if (null !== fiber) { - !isWorking && + null !== fiber && + (!isWorking && 0 !== nextRenderExpirationTime && expirationTime < nextRenderExpirationTime && - resetStack(); - markPendingPriorityLevel(fiber, expirationTime); - if (!isWorking || isCommitting$1 || nextRoot !== fiber) { - expirationTime = fiber.expirationTime; - if (null === fiber.nextScheduledRoot) - (fiber.expirationTime = expirationTime), - null === lastScheduledRoot - ? ((firstScheduledRoot = lastScheduledRoot = fiber), - (fiber.nextScheduledRoot = fiber)) - : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = fiber), - (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); - else { - var remainingExpirationTime = fiber.expirationTime; - if ( - 0 === remainingExpirationTime || - expirationTime < remainingExpirationTime - ) - fiber.expirationTime = expirationTime; - } - isRendering || - (isBatchingUpdates - ? isUnbatchingUpdates && - ((nextFlushedRoot = fiber), - (nextFlushedExpirationTime = 1), - performWorkOnRoot(fiber, 1, !0)) - : 1 === expirationTime - ? performWork(1, null) - : scheduleCallbackWithExpirationTime(fiber, expirationTime)); - } + resetStack(), + markPendingPriorityLevel(fiber, expirationTime), + (isWorking && !isCommitting$1 && nextRoot === fiber) || + requestWork(fiber, fiber.expirationTime), nestedUpdateCount > NESTED_UPDATE_LIMIT && ((nestedUpdateCount = 0), 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." - )); - } + ))); } var firstScheduledRoot = null, lastScheduledRoot = null, @@ -5592,13 +5760,29 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - 0 < msUntilTimeout && - (root.timeoutHandle = scheduleTimeout( - onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), - msUntilTimeout - )); + 0 !== msUntilTimeout || shouldYield() + ? 0 < msUntilTimeout && + (root.timeoutHandle = scheduleTimeout( + onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), + msUntilTimeout + )) + : ((root.pendingCommitExpirationTime = suspendedExpirationTime), + (root.finishedWork = finishedWork)); +} +function onTimeout(root, finishedWork, suspendedExpirationTime) { + root.pendingCommitExpirationTime = suspendedExpirationTime; + root.finishedWork = finishedWork; + recomputeCurrentRendererTime(); + currentSchedulerTime = currentRendererTime; + invariant( + !isRendering, + "work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method." + ); + nextFlushedRoot = root; + nextFlushedExpirationTime = suspendedExpirationTime; + performWorkOnRoot(root, suspendedExpirationTime, !0); + performWork(1, null); } -function onTimeout() {} function onCommit(root, expirationTime) { root.expirationTime = expirationTime; root.finishedWork = null; @@ -5614,6 +5798,32 @@ function requestCurrentTime() { (currentSchedulerTime = currentRendererTime); return currentSchedulerTime; } +function requestWork(root, expirationTime) { + if (null === root.nextScheduledRoot) + (root.expirationTime = expirationTime), + null === lastScheduledRoot + ? ((firstScheduledRoot = lastScheduledRoot = root), + (root.nextScheduledRoot = root)) + : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = root), + (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); + else { + var remainingExpirationTime = root.expirationTime; + if ( + 0 === remainingExpirationTime || + expirationTime < remainingExpirationTime + ) + root.expirationTime = expirationTime; + } + isRendering || + (isBatchingUpdates + ? isUnbatchingUpdates && + ((nextFlushedRoot = root), + (nextFlushedExpirationTime = 1), + performWorkOnRoot(root, 1, !0)) + : 1 === expirationTime + ? performWork(1, null) + : scheduleCallbackWithExpirationTime(root, expirationTime)); +} function findHighestPriorityRoot() { var highestPriorityWork = 0, highestPriorityRoot = null; @@ -5750,6 +5960,9 @@ function performWorkOnRoot(root, expirationTime, isExpired) { null !== finishedWork ? completeRoot$1(root, finishedWork, expirationTime) : ((root.finishedWork = null), + (finishedWork = root.timeoutHandle), + -1 !== finishedWork && + ((root.timeoutHandle = -1), cancelTimeout(finishedWork)), renderRoot(root, !1, isExpired), (finishedWork = root.finishedWork), null !== finishedWork && @@ -5759,6 +5972,9 @@ function performWorkOnRoot(root, expirationTime, isExpired) { null !== finishedWork ? completeRoot$1(root, finishedWork, expirationTime) : ((root.finishedWork = null), + (finishedWork = root.timeoutHandle), + -1 !== finishedWork && + ((root.timeoutHandle = -1), cancelTimeout(finishedWork)), renderRoot(root, !0, isExpired), (finishedWork = root.finishedWork), null !== finishedWork && @@ -6153,7 +6369,7 @@ var roots = new Map(), findFiberByHostInstance: getInstanceFromInstance, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.5.2", + version: "16.6.0-alpha.8af6728", rendererPackageName: "react-native-renderer" }); var ReactFabric$2 = { default: ReactFabric }, diff --git a/Libraries/Renderer/oss/ReactNativeRenderer-dev.js b/Libraries/Renderer/oss/ReactNativeRenderer-dev.js index 4108f0d42c519c..e77e96de3e20ea 100644 --- a/Libraries/Renderer/oss/ReactNativeRenderer-dev.js +++ b/Libraries/Renderer/oss/ReactNativeRenderer-dev.js @@ -1148,7 +1148,7 @@ var ContextProvider = 12; var ForwardRef = 13; var ForwardRefLazy = 14; var Profiler = 15; -var PlaceholderComponent = 16; +var SuspenseComponent = 16; var PureComponent = 17; var PureComponentLazy = 18; @@ -2929,9 +2929,7 @@ var REACT_CONCURRENT_MODE_TYPE = hasSymbol var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 0xead0; -var REACT_PLACEHOLDER_TYPE = hasSymbol - ? Symbol.for("react.placeholder") - : 0xead1; +var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 0xead1; var REACT_PURE_TYPE = hasSymbol ? Symbol.for("react.pure") : 0xead3; var MAYBE_ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; @@ -2962,6 +2960,14 @@ function refineResolvedThenable(thenable) { return thenable._reactStatus === Resolved ? thenable._reactResult : null; } +function getWrappedName(outerType, innerType, wrapperName) { + var functionName = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) + ); +} + function getComponentName(type) { if (type == null) { // Host root, text node or just invalid type. @@ -2993,8 +2999,8 @@ function getComponentName(type) { return "Profiler"; case REACT_STRICT_MODE_TYPE: return "StrictMode"; - case REACT_PLACEHOLDER_TYPE: - return "Placeholder"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; } if (typeof type === "object") { switch (type.$$typeof) { @@ -3003,14 +3009,9 @@ function getComponentName(type) { case REACT_PROVIDER_TYPE: return "Context.Provider"; case REACT_FORWARD_REF_TYPE: - var renderFn = type.render; - var functionName = renderFn.displayName || renderFn.name || ""; - return ( - type.displayName || - (functionName !== "" - ? "ForwardRef(" + functionName + ")" - : "ForwardRef") - ); + return getWrappedName(type, type.render, "ForwardRef"); + case REACT_PURE_TYPE: + return getWrappedName(type, type.render, "Pure"); } if (typeof type.then === "function") { var thenable = type; @@ -4441,7 +4442,6 @@ function setCurrentPhase(lifeCyclePhase) { var debugRenderPhaseSideEffects = false; var debugRenderPhaseSideEffectsForStrictMode = false; -var enableSuspense = false; var enableUserTimingAPI = true; var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; var warnAboutDeprecatedLifecycles = false; @@ -4720,7 +4720,10 @@ function stopFailedWorkTimer(fiber) { return; } fiber._debugIsCurrentlyTiming = false; - var warning = "An error was thrown inside this error boundary"; + var warning = + fiber.tag === SuspenseComponent + ? "Rendering was suspended" + : "An error was thrown inside this error boundary"; endFiberMark(fiber, null, warning); } } @@ -5642,8 +5645,8 @@ function createFiberFromElement(element, mode, expirationTime) { break; case REACT_PROFILER_TYPE: return createFiberFromProfiler(pendingProps, mode, expirationTime, key); - case REACT_PLACEHOLDER_TYPE: - fiberTag = PlaceholderComponent; + case REACT_SUSPENSE_TYPE: + fiberTag = SuspenseComponent; break; default: { if (typeof type === "object" && type !== null) { @@ -10522,6 +10525,7 @@ function updatePureComponent( renderExpirationTime ) { var render = Component.render; + var ref = workInProgress.ref; if ( current$$1 !== null && @@ -10532,7 +10536,10 @@ function updatePureComponent( // Default to shallow comparison var compare = Component.compare; compare = compare !== null ? compare : shallowEqual; - if (compare(prevProps, nextProps)) { + if ( + workInProgress.ref === current$$1.ref && + compare(prevProps, nextProps) + ) { return bailoutOnAlreadyFinishedWork( current$$1, workInProgress, @@ -10547,7 +10554,7 @@ function updatePureComponent( { ReactCurrentOwner$3.current = workInProgress; setCurrentPhase("render"); - nextChildren = render(nextProps); + nextChildren = render(nextProps, ref); setCurrentPhase(null); } @@ -10987,11 +10994,15 @@ function mountIndeterminateComponent( Component !== null && typeof Component.then === "function" ) { + // We can't start a User Timing measurement with correct label yet. + // Cancel and resume right after we know the tag. + cancelWorkTimer(workInProgress); Component = readLazyComponentType(Component); var resolvedTag = (workInProgress.tag = resolveLazyComponentTag( workInProgress, Component )); + startWorkTimer(workInProgress); var resolvedProps = resolveDefaultProps(Component, props); var child = void 0; switch (resolvedTag) { @@ -11202,79 +11213,72 @@ function mountIndeterminateComponent( } } -function updatePlaceholderComponent( +function updateSuspenseComponent( current$$1, workInProgress, renderExpirationTime ) { - if (enableSuspense) { - var nextProps = workInProgress.pendingProps; - - // Check if we already attempted to render the normal state. If we did, - // and we timed out, render the placeholder state. - var alreadyCaptured = (workInProgress.effectTag & DidCapture) === NoEffect; - - var nextDidTimeout = void 0; - if (current$$1 !== null && workInProgress.updateQueue !== null) { - // We're outside strict mode. Something inside this Placeholder boundary - // suspended during the last commit. Switch to the placholder. - workInProgress.updateQueue = null; - nextDidTimeout = true; - } else { - nextDidTimeout = !alreadyCaptured; - } + var nextProps = workInProgress.pendingProps; - if ((workInProgress.mode & StrictMode) !== NoEffect) { - if (nextDidTimeout) { - // If the timed-out view commits, schedule an update effect to record - // the committed time. - workInProgress.effectTag |= Update; - } else { - // The state node points to the time at which placeholder timed out. - // We can clear it once we switch back to the normal children. - workInProgress.stateNode = null; - } - } + // Check if we already attempted to render the normal state. If we did, + // and we timed out, render the placeholder state. + var alreadyCaptured = (workInProgress.effectTag & DidCapture) === NoEffect; - // If the `children` prop is a function, treat it like a render prop. - // TODO: This is temporary until we finalize a lower level API. - var children = nextProps.children; - var nextChildren = void 0; - if (typeof children === "function") { - nextChildren = children(nextDidTimeout); - } else { - nextChildren = nextDidTimeout ? nextProps.fallback : children; - } + var nextDidTimeout = void 0; + if (current$$1 !== null && workInProgress.updateQueue !== null) { + // We're outside strict mode. Something inside this Placeholder boundary + // suspended during the last commit. Switch to the placholder. + workInProgress.updateQueue = null; + nextDidTimeout = true; + } else { + nextDidTimeout = !alreadyCaptured; + } - if ( - current$$1 !== null && - nextDidTimeout !== workInProgress.memoizedState - ) { - // We're about to switch from the placeholder children to the normal - // children, or vice versa. These are two different conceptual sets that - // happen to be stored in the same set. Call this special function to - // force the new set not to match with the current set. - // TODO: The proper way to model this is by storing each set separately. - forceUnmountCurrentAndReconcile( - current$$1, - workInProgress, - nextChildren, - renderExpirationTime - ); + if ((workInProgress.mode & StrictMode) !== NoEffect) { + if (nextDidTimeout) { + // If the timed-out view commits, schedule an update effect to record + // the committed time. + workInProgress.effectTag |= Update; } else { - reconcileChildren( - current$$1, - workInProgress, - nextChildren, - renderExpirationTime - ); + // The state node points to the time at which placeholder timed out. + // We can clear it once we switch back to the normal children. + workInProgress.stateNode = null; } - workInProgress.memoizedProps = nextProps; - workInProgress.memoizedState = nextDidTimeout; - return workInProgress.child; + } + + // If the `children` prop is a function, treat it like a render prop. + // TODO: This is temporary until we finalize a lower level API. + var children = nextProps.children; + var nextChildren = void 0; + if (typeof children === "function") { + nextChildren = children(nextDidTimeout); } else { - return null; + nextChildren = nextDidTimeout ? nextProps.fallback : children; + } + + if (current$$1 !== null && nextDidTimeout !== workInProgress.memoizedState) { + // We're about to switch from the placeholder children to the normal + // children, or vice versa. These are two different conceptual sets that + // happen to be stored in the same set. Call this special function to + // force the new set not to match with the current set. + // TODO: The proper way to model this is by storing each set separately. + forceUnmountCurrentAndReconcile( + current$$1, + workInProgress, + nextChildren, + renderExpirationTime + ); + } else { + reconcileChildren( + current$$1, + workInProgress, + nextChildren, + renderExpirationTime + ); } + workInProgress.memoizedProps = nextProps; + workInProgress.memoizedState = nextDidTimeout; + return workInProgress.child; } function updatePortalComponent( @@ -11373,12 +11377,35 @@ function updateContextProvider( return workInProgress.child; } +var hasWarnedAboutUsingContextAsConsumer = false; + function updateContextConsumer( current$$1, workInProgress, renderExpirationTime ) { var context = workInProgress.type; + // The logic below for Context differs depending on PROD or DEV mode. In + // DEV mode, we create a separate object for Context.Consumer that acts + // like a proxy to Context. This proxy object adds unnecessary code in PROD + // so we use the old behaviour (Context.Consumer references Context) to + // reduce size and overhead. The separate object references context via + // a property called "_context", which also gives us the ability to check + // in DEV mode if this property exists or not and warn if it does not. + { + if (context._context === undefined) { + if (!hasWarnedAboutUsingContextAsConsumer) { + hasWarnedAboutUsingContextAsConsumer = true; + warning$1( + false, + "Rendering directly is not supported and will be removed in " + + "a future major release. Did you mean to render instead?" + ); + } + } else { + context = context._context; + } + } var newProps = workInProgress.pendingProps; var render = newProps.children; @@ -11618,8 +11645,8 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { ); case HostText: return updateHostText(current$$1, workInProgress); - case PlaceholderComponent: - return updatePlaceholderComponent( + case SuspenseComponent: + return updateSuspenseComponent( current$$1, workInProgress, renderExpirationTime @@ -12118,7 +12145,7 @@ function completeWork(current, workInProgress, renderExpirationTime) { case ForwardRef: case ForwardRefLazy: break; - case PlaceholderComponent: + case SuspenseComponent: break; case Fragment: break; @@ -12525,22 +12552,20 @@ function commitLifeCycles( } return; } - case PlaceholderComponent: { - if (enableSuspense) { - if ((finishedWork.mode & StrictMode) === NoEffect) { - // In loose mode, a placeholder times out by scheduling a synchronous - // update in the commit phase. Use `updateQueue` field to signal that - // the Timeout needs to switch to the placeholder. We don't need an - // entire queue. Any non-null value works. - // $FlowFixMe - Intentionally using a value other than an UpdateQueue. - finishedWork.updateQueue = emptyObject$1; - scheduleWork(finishedWork, Sync); - } else { - // In strict mode, the Update effect is used to record the time at - // which the placeholder timed out. - var currentTime = requestCurrentTime(); - finishedWork.stateNode = { timedOutAt: currentTime }; - } + case SuspenseComponent: { + if ((finishedWork.mode & StrictMode) === NoEffect) { + // In loose mode, a placeholder times out by scheduling a synchronous + // update in the commit phase. Use `updateQueue` field to signal that + // the Timeout needs to switch to the placeholder. We don't need an + // entire queue. Any non-null value works. + // $FlowFixMe - Intentionally using a value other than an UpdateQueue. + finishedWork.updateQueue = emptyObject$1; + scheduleWork(finishedWork, Sync); + } else { + // In strict mode, the Update effect is used to record the time at + // which the placeholder timed out. + var currentTime = requestCurrentTime(); + finishedWork.stateNode = { timedOutAt: currentTime }; } return; } @@ -13029,7 +13054,7 @@ function commitWork(current$$1, finishedWork) { case Profiler: { return; } - case PlaceholderComponent: { + case SuspenseComponent: { return; } default: { @@ -13129,7 +13154,6 @@ function throwException( sourceFiber.firstEffect = sourceFiber.lastEffect = null; if ( - enableSuspense && value !== null && typeof value === "object" && typeof value.then === "function" @@ -13146,7 +13170,7 @@ function throwException( var earliestTimeoutMs = -1; var startTimeMs = -1; do { - if (_workInProgress.tag === PlaceholderComponent) { + if (_workInProgress.tag === SuspenseComponent) { var current = _workInProgress.alternate; if ( current !== null && @@ -13164,7 +13188,7 @@ function throwException( // Do not search any further. break; } - var timeoutPropMs = _workInProgress.pendingProps.delayMs; + var timeoutPropMs = _workInProgress.pendingProps.maxDuration; if (typeof timeoutPropMs === "number") { if (timeoutPropMs <= 0) { earliestTimeoutMs = 0; @@ -13179,10 +13203,10 @@ function throwException( _workInProgress = _workInProgress.return; } while (_workInProgress !== null); - // Schedule the nearest Placeholder to re-render the timed out view. + // Schedule the nearest Suspense to re-render the timed out view. _workInProgress = returnFiber; do { - if (_workInProgress.tag === PlaceholderComponent) { + if (_workInProgress.tag === SuspenseComponent) { var didTimeout = _workInProgress.memoizedState; if (!didTimeout) { // Found the nearest boundary. @@ -13209,10 +13233,10 @@ function throwException( // If the boundary is outside of strict mode, we should *not* suspend // the commit. Pretend as if the suspended component rendered null and // keep rendering. In the commit phase, we'll schedule a subsequent - // synchronous update to re-render the Placeholder. + // synchronous update to re-render the Suspense. // // Note: It doesn't matter whether the component that suspended was - // inside a strict mode tree. If the Placeholder is outside of it, we + // inside a strict mode tree. If the Suspense is outside of it, we // should *not* suspend the commit. if ((_workInProgress.mode & StrictMode) === NoEffect) { _workInProgress.effectTag |= Update; @@ -13402,7 +13426,7 @@ function unwindWork(workInProgress, renderExpirationTime) { popHostContext(workInProgress); return null; } - case PlaceholderComponent: { + case SuspenseComponent: { var _effectTag3 = workInProgress.effectTag; if (_effectTag3 & ShouldCapture) { workInProgress.effectTag = (_effectTag3 & ~ShouldCapture) | DidCapture; @@ -14640,7 +14664,7 @@ function renderRoot(root, isYieldy, isExpired) { } } - if (enableSuspense && !isExpired && nextLatestAbsoluteTimeoutMs !== -1) { + if (!isExpired && nextLatestAbsoluteTimeoutMs !== -1) { // The tree was suspended. var _suspendedExpirationTime2 = expirationTime; markSuspendedPriorityLevel(root, _suspendedExpirationTime2); @@ -14804,41 +14828,39 @@ function renderDidError() { } function retrySuspendedRoot(root, fiber, suspendedTime) { - if (enableSuspense) { - var retryTime = void 0; + var retryTime = void 0; - if (isPriorityLevelSuspended(root, suspendedTime)) { - // Ping at the original level - retryTime = suspendedTime; + if (isPriorityLevelSuspended(root, suspendedTime)) { + // Ping at the original level + retryTime = suspendedTime; - markPingedPriorityLevel(root, retryTime); - } else { - // Placeholder already timed out. Compute a new expiration time - var currentTime = requestCurrentTime(); - retryTime = computeExpirationForFiber(currentTime, fiber); - markPendingPriorityLevel(root, retryTime); - } + markPingedPriorityLevel(root, retryTime); + } else { + // Suspense already timed out. Compute a new expiration time + var currentTime = requestCurrentTime(); + retryTime = computeExpirationForFiber(currentTime, fiber); + markPendingPriorityLevel(root, retryTime); + } - // TODO: If the placeholder fiber has already rendered the primary children - // without suspending (that is, all of the promises have already resolved), - // we should not trigger another update here. One case this happens is when - // we are in sync mode and a single promise is thrown both on initial render - // and on update; we attach two .then(retrySuspendedRoot) callbacks and each - // one performs Sync work, rerendering the Placeholder. + // TODO: If the placeholder fiber has already rendered the primary children + // without suspending (that is, all of the promises have already resolved), + // we should not trigger another update here. One case this happens is when + // we are in sync mode and a single promise is thrown both on initial render + // and on update; we attach two .then(retrySuspendedRoot) callbacks and each + // one performs Sync work, rerendering the Suspense. - if ((fiber.mode & ConcurrentMode) !== NoContext) { - if (root === nextRoot && nextRenderExpirationTime === suspendedTime) { - // Received a ping at the same priority level at which we're currently - // rendering. Restart from the root. - nextRoot = null; - } + if ((fiber.mode & ConcurrentMode) !== NoContext) { + if (root === nextRoot && nextRenderExpirationTime === suspendedTime) { + // Received a ping at the same priority level at which we're currently + // rendering. Restart from the root. + nextRoot = null; } + } - scheduleWorkToRoot(fiber, retryTime); - var rootExpirationTime = root.expirationTime; - if (rootExpirationTime !== NoWork) { - requestWork(root, rootExpirationTime); - } + scheduleWorkToRoot(fiber, retryTime); + var rootExpirationTime = root.expirationTime; + if (rootExpirationTime !== NoWork) { + requestWork(root, rootExpirationTime); } } @@ -15075,7 +15097,7 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - if (enableSuspense && msUntilTimeout === 0 && !shouldYield()) { + if (msUntilTimeout === 0 && !shouldYield()) { // Don't wait an additional tick. Commit the tree immediately. root.pendingCommitExpirationTime = suspendedExpirationTime; root.finishedWork = finishedWork; @@ -15093,17 +15115,15 @@ function onYield(root) { } function onTimeout(root, finishedWork, suspendedExpirationTime) { - if (enableSuspense) { - // The root timed out. Commit it. - root.pendingCommitExpirationTime = suspendedExpirationTime; - root.finishedWork = finishedWork; - // Read the current time before entering the commit phase. We can be - // certain this won't cause tearing related to batching of event updates - // because we're at the top of a timer event. - recomputeCurrentRendererTime(); - currentSchedulerTime = currentRendererTime; - flushRoot(root, suspendedExpirationTime); - } + // The root timed out. Commit it. + root.pendingCommitExpirationTime = suspendedExpirationTime; + root.finishedWork = finishedWork; + // Read the current time before entering the commit phase. We can be + // certain this won't cause tearing related to batching of event updates + // because we're at the top of a timer event. + recomputeCurrentRendererTime(); + currentSchedulerTime = currentRendererTime; + flushRoot(root, suspendedExpirationTime); } function onCommit(root, expirationTime) { @@ -15441,7 +15461,7 @@ function performWorkOnRoot(root, expirationTime, isExpired) { // If this root previously suspended, clear its existing timeout, since // we're about to try rendering again. var timeoutHandle = root.timeoutHandle; - if (enableSuspense && timeoutHandle !== noTimeout) { + if (timeoutHandle !== noTimeout) { root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above cancelTimeout(timeoutHandle); @@ -15465,7 +15485,7 @@ function performWorkOnRoot(root, expirationTime, isExpired) { // If this root previously suspended, clear its existing timeout, since // we're about to try rendering again. var _timeoutHandle = root.timeoutHandle; - if (enableSuspense && _timeoutHandle !== noTimeout) { + if (_timeoutHandle !== noTimeout) { root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above cancelTimeout(_timeoutHandle); @@ -15621,9 +15641,11 @@ function flushInteractiveUpdates$1() { // Might add PROFILE later. var didWarnAboutNestedUpdates = void 0; +var didWarnAboutFindNodeInStrictMode = void 0; { didWarnAboutNestedUpdates = false; + didWarnAboutFindNodeInStrictMode = {}; } function getContextForSubtree(parentComponent) { @@ -15739,6 +15761,64 @@ function findHostInstance$1(component) { return hostFiber.stateNode; } +function findHostInstanceWithWarning$1(component, methodName) { + { + var fiber = get$1(component); + if (fiber === undefined) { + if (typeof component.render === "function") { + invariant(false, "Unable to find node on an unmounted component."); + } else { + invariant( + false, + "Argument appears to not be a ReactComponent. Keys: %s", + Object.keys(component) + ); + } + } + var hostFiber = findCurrentHostFiber(fiber); + if (hostFiber === null) { + return null; + } + if (hostFiber.mode & StrictMode) { + var componentName = getComponentName(fiber.type) || "Component"; + if (!didWarnAboutFindNodeInStrictMode[componentName]) { + didWarnAboutFindNodeInStrictMode[componentName] = true; + if (fiber.mode & StrictMode) { + warningWithoutStack$1( + false, + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which is inside StrictMode. " + + "Instead, add a ref directly to the element you want to reference." + + "\n%s" + + "\n\nLearn more about using refs safely here:" + + "\nhttps://fb.me/react-strict-mode-find-node", + methodName, + methodName, + componentName, + getStackByFiberInDevAndProd(hostFiber) + ); + } else { + warningWithoutStack$1( + false, + "%s is deprecated in StrictMode. " + + "%s was passed an instance of %s which renders StrictMode children. " + + "Instead, add a ref directly to the element you want to reference." + + "\n%s" + + "\n\nLearn more about using refs safely here:" + + "\nhttps://fb.me/react-strict-mode-find-node", + methodName, + methodName, + componentName, + getStackByFiberInDevAndProd(hostFiber) + ); + } + } + } + return hostFiber.stateNode; + } + return findHostInstance$1(component); +} + function createContainer(containerInfo, isConcurrent, hydrate) { return createFiberRoot(containerInfo, isConcurrent, hydrate); } @@ -15816,7 +15896,7 @@ function createPortal( // TODO: this is special because it gets imported during build. -var ReactVersion = "16.5.2"; +var ReactVersion = "16.6.0-alpha.8af6728"; // Modules provided by RN: var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { @@ -16322,6 +16402,7 @@ var getInspectorDataForViewTag = void 0; // Module provided by RN: var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; var findHostInstance = findHostInstance$1; +var findHostInstanceWithWarning = findHostInstanceWithWarning$1; function findNodeHandle(componentOrHandle) { { @@ -16355,7 +16436,14 @@ function findNodeHandle(componentOrHandle) { if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag) { return componentOrHandle.canonical._nativeTag; } - var hostInstance = findHostInstance(componentOrHandle); + var hostInstance = void 0; + { + hostInstance = findHostInstanceWithWarning( + componentOrHandle, + "findNodeHandle" + ); + } + if (hostInstance == null) { return hostInstance; } diff --git a/Libraries/Renderer/oss/ReactNativeRenderer-prod.js b/Libraries/Renderer/oss/ReactNativeRenderer-prod.js index d0c3a268e3d018..3fcf1033033884 100644 --- a/Libraries/Renderer/oss/ReactNativeRenderer-prod.js +++ b/Libraries/Renderer/oss/ReactNativeRenderer-prod.js @@ -1146,7 +1146,7 @@ var ReactSharedInternals = ? Symbol.for("react.concurrent_mode") : 60111, REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112, - REACT_PLACEHOLDER_TYPE = hasSymbol ? Symbol.for("react.placeholder") : 60113, + REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113, REACT_PURE_TYPE = hasSymbol ? Symbol.for("react.pure") : 60115, MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { @@ -1156,6 +1156,13 @@ function getIteratorFn(maybeIterable) { maybeIterable["@@iterator"]; return "function" === typeof maybeIterable ? maybeIterable : null; } +function getWrappedName(outerType, innerType, wrapperName) { + innerType = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + ("" !== innerType ? wrapperName + "(" + innerType + ")" : wrapperName) + ); +} function getComponentName(type) { if (null == type) return null; if ("function" === typeof type) return type.displayName || type.name || null; @@ -1171,8 +1178,8 @@ function getComponentName(type) { return "Profiler"; case REACT_STRICT_MODE_TYPE: return "StrictMode"; - case REACT_PLACEHOLDER_TYPE: - return "Placeholder"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; } if ("object" === typeof type) { switch (type.$$typeof) { @@ -1181,12 +1188,9 @@ function getComponentName(type) { case REACT_PROVIDER_TYPE: return "Context.Provider"; case REACT_FORWARD_REF_TYPE: - var renderFn = type.render; - renderFn = renderFn.displayName || renderFn.name || ""; - return ( - type.displayName || - ("" !== renderFn ? "ForwardRef(" + renderFn + ")" : "ForwardRef") - ); + return getWrappedName(type, type.render, "ForwardRef"); + case REACT_PURE_TYPE: + return getWrappedName(type, type.render, "Pure"); } if ( "function" === typeof type.then && @@ -1640,7 +1644,9 @@ function finalizeInitialChildren(parentInstance) { UIManager.setChildren(parentInstance._nativeTag, nativeTags); return !1; } -var BEFORE_SLASH_RE = /^(.*)[\\\/]/; +var scheduleTimeout = setTimeout, + cancelTimeout = clearTimeout, + BEFORE_SLASH_RE = /^(.*)[\\\/]/; function getStackByFiberInDevAndProd(workInProgress) { var info = ""; do { @@ -1888,7 +1894,7 @@ function createFiberFromElement(element, mode, expirationTime) { (type.expirationTime = expirationTime), type ); - case REACT_PLACEHOLDER_TYPE: + case REACT_SUSPENSE_TYPE: fiberTag = 16; break; default: @@ -1960,6 +1966,43 @@ function markPendingPriorityLevel(root, expirationTime) { (root.latestPendingTime = expirationTime); findNextExpirationTimeToWorkOn(expirationTime, root); } +function markSuspendedPriorityLevel(root, suspendedTime) { + root.didError = !1; + var latestPingedTime = root.latestPingedTime; + 0 !== latestPingedTime && + latestPingedTime <= suspendedTime && + (root.latestPingedTime = 0); + latestPingedTime = root.earliestPendingTime; + var latestPendingTime = root.latestPendingTime; + latestPingedTime === suspendedTime + ? (root.earliestPendingTime = + latestPendingTime === suspendedTime + ? (root.latestPendingTime = 0) + : latestPendingTime) + : latestPendingTime === suspendedTime && + (root.latestPendingTime = latestPingedTime); + latestPingedTime = root.earliestSuspendedTime; + latestPendingTime = root.latestSuspendedTime; + 0 === latestPingedTime + ? (root.earliestSuspendedTime = root.latestSuspendedTime = suspendedTime) + : latestPingedTime > suspendedTime + ? (root.earliestSuspendedTime = suspendedTime) + : latestPendingTime < suspendedTime && + (root.latestSuspendedTime = suspendedTime); + findNextExpirationTimeToWorkOn(suspendedTime, root); +} +function findEarliestOutstandingPriorityLevel(root, renderExpirationTime) { + var earliestPendingTime = root.earliestPendingTime; + root = root.earliestSuspendedTime; + if ( + 0 === renderExpirationTime || + (0 !== earliestPendingTime && earliestPendingTime < renderExpirationTime) + ) + renderExpirationTime = earliestPendingTime; + if (0 === renderExpirationTime || (0 !== root && root < renderExpirationTime)) + renderExpirationTime = root; + return renderExpirationTime; +} function findNextExpirationTimeToWorkOn(completedExpirationTime, root) { var earliestSuspendedTime = root.earliestSuspendedTime, latestSuspendedTime = root.latestSuspendedTime, @@ -3313,7 +3356,8 @@ function updatePureComponent( updateExpirationTime, renderExpirationTime ) { - var render = Component.render; + var render = Component.render, + ref = workInProgress.ref; if ( null !== current$$1 && (0 === updateExpirationTime || @@ -3321,7 +3365,8 @@ function updatePureComponent( ((updateExpirationTime = current$$1.memoizedProps), (Component = Component.compare), (Component = null !== Component ? Component : shallowEqual), - Component(updateExpirationTime, nextProps)) + workInProgress.ref === current$$1.ref && + Component(updateExpirationTime, nextProps)) ) return bailoutOnAlreadyFinishedWork( current$$1, @@ -3329,7 +3374,7 @@ function updatePureComponent( renderExpirationTime ); prepareToReadContext(workInProgress, renderExpirationTime); - render = render(nextProps); + render = render(nextProps, ref); workInProgress.effectTag |= 1; reconcileChildren(current$$1, workInProgress, render, renderExpirationTime); workInProgress.memoizedProps = nextProps; @@ -3986,7 +4031,46 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { null ); case 16: - return null; + return ( + (Component = workInProgress.pendingProps), + (props = 0 === (workInProgress.effectTag & 64)), + null !== current$$1 && null !== workInProgress.updateQueue + ? ((workInProgress.updateQueue = null), (props = !0)) + : (props = !props), + 0 !== (workInProgress.mode & 2) && + (props + ? (workInProgress.effectTag |= 4) + : (workInProgress.stateNode = null)), + (updateExpirationTime = Component.children), + (updateExpirationTime = + "function" === typeof updateExpirationTime + ? updateExpirationTime(props) + : props + ? Component.fallback + : updateExpirationTime), + null !== current$$1 && props !== workInProgress.memoizedState + ? ((workInProgress.child = reconcileChildFibers( + workInProgress, + current$$1.child, + null, + renderExpirationTime + )), + (workInProgress.child = reconcileChildFibers( + workInProgress, + null, + updateExpirationTime, + renderExpirationTime + ))) + : reconcileChildren( + current$$1, + workInProgress, + updateExpirationTime, + renderExpirationTime + ), + (workInProgress.memoizedProps = Component), + (workInProgress.memoizedState = props), + workInProgress.child + ); case 6: return ( pushHostContainer( @@ -4275,6 +4359,7 @@ function logCapturedError(capturedError) { : Error("Unspecified error at:" + componentStack); ExceptionsManager.handleException(error, !1); } +var emptyObject$1 = {}; function logError(boundary, errorInfo) { var source = errorInfo.source, stack = errorInfo.stack; @@ -4624,6 +4709,9 @@ function commitWork(current$$1, finishedWork) { ); } } +function NoopComponent() { + return null; +} function createRootErrorUpdate(fiber, errorInfo, expirationTime) { expirationTime = createUpdate(expirationTime); expirationTime.tag = 3; @@ -4717,6 +4805,7 @@ var Dispatcher = { readContext: readContext }, nextUnitOfWork = null, nextRoot = null, nextRenderExpirationTime = 0, + nextLatestAbsoluteTimeoutMs = -1, nextRenderDidError = !1, nextEffect = null, isCommitting$1 = !1, @@ -4761,6 +4850,7 @@ function resetStack() { } nextRoot = null; nextRenderExpirationTime = 0; + nextLatestAbsoluteTimeoutMs = -1; nextRenderDidError = !1; nextUnitOfWork = null; } @@ -4998,28 +5088,28 @@ function performUnitOfWork(workInProgress) { ReactCurrentOwner$2.current = null; return next; } -function renderRoot(root, isYieldy, isExpired) { +function renderRoot(root$jscomp$0, isYieldy, isExpired) { invariant( !isWorking, "renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue." ); isWorking = !0; ReactCurrentOwner$2.currentDispatcher = Dispatcher; - var expirationTime = root.nextExpirationTimeToWorkOn; + var expirationTime = root$jscomp$0.nextExpirationTimeToWorkOn; if ( expirationTime !== nextRenderExpirationTime || - root !== nextRoot || + root$jscomp$0 !== nextRoot || null === nextUnitOfWork ) resetStack(), - (nextRoot = root), + (nextRoot = root$jscomp$0), (nextRenderExpirationTime = expirationTime), (nextUnitOfWork = createWorkInProgress( nextRoot.current, null, nextRenderExpirationTime )), - (root.pendingCommitExpirationTime = 0); + (root$jscomp$0.pendingCommitExpirationTime = 0); var didFatal = !1; do { try { @@ -5042,54 +5132,145 @@ function renderRoot(root, isYieldy, isExpired) { if (null === returnFiber) (didFatal = !0), onUncaughtError(thrownValue); else { a: { - var returnFiber$jscomp$0 = returnFiber, + var root = root$jscomp$0, + returnFiber$jscomp$0 = returnFiber, sourceFiber$jscomp$0 = sourceFiber, value = thrownValue; returnFiber = nextRenderExpirationTime; sourceFiber$jscomp$0.effectTag |= 512; sourceFiber$jscomp$0.firstEffect = sourceFiber$jscomp$0.lastEffect = null; + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var thenable = value; + value = returnFiber$jscomp$0; + var earliestTimeoutMs = -1, + startTimeMs = -1; + do { + if (16 === value.tag) { + var current = value.alternate; + if ( + null !== current && + !0 === current.memoizedState && + null !== current.stateNode + ) { + startTimeMs = 10 * (current.stateNode.timedOutAt - 2); + break; + } + current = value.pendingProps.maxDuration; + if ("number" === typeof current) + if (0 >= current) earliestTimeoutMs = 0; + else if ( + -1 === earliestTimeoutMs || + current < earliestTimeoutMs + ) + earliestTimeoutMs = current; + } + value = value.return; + } while (null !== value); + value = returnFiber$jscomp$0; + do { + if (16 === value.tag && !value.memoizedState) { + returnFiber$jscomp$0 = retrySuspendedRoot.bind( + null, + root, + value, + 0 === (value.mode & 1) ? 1 : returnFiber + ); + thenable.then(returnFiber$jscomp$0, returnFiber$jscomp$0); + if (0 === (value.mode & 2)) { + value.effectTag |= 4; + reconcileChildren( + sourceFiber$jscomp$0.alternate, + sourceFiber$jscomp$0, + null, + returnFiber + ); + sourceFiber$jscomp$0.effectTag &= -513; + 4 === sourceFiber$jscomp$0.tag && + (sourceFiber$jscomp$0.tag = 0); + if ( + 2 === sourceFiber$jscomp$0.tag || + 3 === sourceFiber$jscomp$0.tag + ) + (sourceFiber$jscomp$0.effectTag &= -421), + null === sourceFiber$jscomp$0.alternate && + ((sourceFiber$jscomp$0.tag = 0), + (sourceFiber$jscomp$0.type = NoopComponent)); + break a; + } + -1 === earliestTimeoutMs + ? (root = 1073741823) + : (-1 === startTimeMs && + (startTimeMs = + 10 * + (findEarliestOutstandingPriorityLevel( + root, + returnFiber + ) - + 2) - + 5e3), + (root = startTimeMs + earliestTimeoutMs)); + 0 <= root && + nextLatestAbsoluteTimeoutMs < root && + (nextLatestAbsoluteTimeoutMs = root); + value.effectTag |= 1024; + value.expirationTime = returnFiber; + break a; + } + value = value.return; + } while (null !== value); + value = Error( + "An update was suspended, but no placeholder UI was provided." + ); + } nextRenderDidError = !0; value = createCapturedValue(value, sourceFiber$jscomp$0); + root = returnFiber$jscomp$0; do { - switch (returnFiber$jscomp$0.tag) { + switch (root.tag) { case 5: - returnFiber$jscomp$0.effectTag |= 1024; - returnFiber$jscomp$0.expirationTime = returnFiber; + sourceFiber$jscomp$0 = value; + root.effectTag |= 1024; + root.expirationTime = returnFiber; returnFiber = createRootErrorUpdate( - returnFiber$jscomp$0, - value, + root, + sourceFiber$jscomp$0, returnFiber ); - enqueueCapturedUpdate(returnFiber$jscomp$0, returnFiber); + enqueueCapturedUpdate(root, returnFiber); break a; case 2: case 3: - sourceFiber$jscomp$0 = value; - var ctor = returnFiber$jscomp$0.type, - instance = returnFiber$jscomp$0.stateNode; if ( - 0 === (returnFiber$jscomp$0.effectTag & 64) && - ("function" === typeof ctor.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has( - instance - )))) + ((sourceFiber$jscomp$0 = value), + (returnFiber$jscomp$0 = root.type), + (thenable = root.stateNode), + 0 === (root.effectTag & 64) && + ("function" === + typeof returnFiber$jscomp$0.getDerivedStateFromError || + (null !== thenable && + "function" === typeof thenable.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has( + thenable + ))))) ) { - returnFiber$jscomp$0.effectTag |= 1024; - returnFiber$jscomp$0.expirationTime = returnFiber; + root.effectTag |= 1024; + root.expirationTime = returnFiber; returnFiber = createClassErrorUpdate( - returnFiber$jscomp$0, + root, sourceFiber$jscomp$0, returnFiber ); - enqueueCapturedUpdate(returnFiber$jscomp$0, returnFiber); + enqueueCapturedUpdate(root, returnFiber); break a; } } - returnFiber$jscomp$0 = returnFiber$jscomp$0.return; - } while (null !== returnFiber$jscomp$0); + root = root.return; + } while (null !== root); } nextUnitOfWork = completeUnitOfWork(sourceFiber); continue; @@ -5100,58 +5281,61 @@ function renderRoot(root, isYieldy, isExpired) { } while (1); isWorking = !1; lastContextWithAllBitsObserved = lastContextDependency = currentlyRenderingFiber = ReactCurrentOwner$2.currentDispatcher = null; - if (didFatal) (nextRoot = null), (root.finishedWork = null); - else if (null !== nextUnitOfWork) root.finishedWork = null; + if (didFatal) (nextRoot = null), (root$jscomp$0.finishedWork = null); + else if (null !== nextUnitOfWork) root$jscomp$0.finishedWork = null; else { - isYieldy = root.current.alternate; + isYieldy = root$jscomp$0.current.alternate; invariant( null !== isYieldy, "Finished root should have a work-in-progress. This error is likely caused by a bug in React. Please file an issue." ); nextRoot = null; if (nextRenderDidError) { - didFatal = root.latestPendingTime; - sourceFiber = root.latestSuspendedTime; - returnFiber = root.latestPingedTime; + didFatal = root$jscomp$0.latestPendingTime; + sourceFiber = root$jscomp$0.latestSuspendedTime; + returnFiber = root$jscomp$0.latestPingedTime; if ( (0 !== didFatal && didFatal > expirationTime) || (0 !== sourceFiber && sourceFiber > expirationTime) || (0 !== returnFiber && returnFiber > expirationTime) ) { - root.didError = !1; - isExpired = root.latestPingedTime; - 0 !== isExpired && - isExpired <= expirationTime && - (root.latestPingedTime = 0); - isExpired = root.earliestPendingTime; - isYieldy = root.latestPendingTime; - isExpired === expirationTime - ? (root.earliestPendingTime = - isYieldy === expirationTime - ? (root.latestPendingTime = 0) - : isYieldy) - : isYieldy === expirationTime && (root.latestPendingTime = isExpired); - isExpired = root.earliestSuspendedTime; - isYieldy = root.latestSuspendedTime; - 0 === isExpired - ? (root.earliestSuspendedTime = root.latestSuspendedTime = expirationTime) - : isExpired > expirationTime - ? (root.earliestSuspendedTime = expirationTime) - : isYieldy < expirationTime && - (root.latestSuspendedTime = expirationTime); - findNextExpirationTimeToWorkOn(expirationTime, root); - root.expirationTime = root.expirationTime; + markSuspendedPriorityLevel(root$jscomp$0, expirationTime); + onSuspend( + root$jscomp$0, + isYieldy, + expirationTime, + root$jscomp$0.expirationTime, + -1 + ); return; } - if (!root.didError && !isExpired) { - root.didError = !0; - root.nextExpirationTimeToWorkOn = expirationTime; - root.expirationTime = 1; + if (!root$jscomp$0.didError && !isExpired) { + root$jscomp$0.didError = !0; + expirationTime = root$jscomp$0.nextExpirationTimeToWorkOn = expirationTime; + isExpired = root$jscomp$0.expirationTime = 1; + onSuspend(root$jscomp$0, isYieldy, expirationTime, isExpired, -1); return; } } - root.pendingCommitExpirationTime = expirationTime; - root.finishedWork = isYieldy; + isExpired || -1 === nextLatestAbsoluteTimeoutMs + ? ((root$jscomp$0.pendingCommitExpirationTime = expirationTime), + (root$jscomp$0.finishedWork = isYieldy)) + : (markSuspendedPriorityLevel(root$jscomp$0, expirationTime), + (isExpired = + 10 * + (findEarliestOutstandingPriorityLevel(root$jscomp$0, expirationTime) - + 2)), + isExpired < nextLatestAbsoluteTimeoutMs && + (nextLatestAbsoluteTimeoutMs = isExpired), + (isExpired = 10 * (requestCurrentTime() - 2)), + (isExpired = nextLatestAbsoluteTimeoutMs - isExpired), + onSuspend( + root$jscomp$0, + isYieldy, + expirationTime, + root$jscomp$0.expirationTime, + 0 > isExpired ? 0 : isExpired + )); } } function captureCommitPhaseError(fiber, error) { @@ -5224,7 +5408,33 @@ function computeExpirationForFiber(currentTime, fiber) { (lowestPriorityPendingInteractiveExpirationTime = currentTime); return currentTime; } -function scheduleWork(fiber, expirationTime) { +function retrySuspendedRoot(root, fiber, suspendedTime) { + var retryTime = root.earliestSuspendedTime; + var latestSuspendedTime = root.latestSuspendedTime; + if ( + 0 !== retryTime && + suspendedTime >= retryTime && + suspendedTime <= latestSuspendedTime + ) { + latestSuspendedTime = retryTime = suspendedTime; + root.didError = !1; + var latestPingedTime = root.latestPingedTime; + if (0 === latestPingedTime || latestPingedTime < latestSuspendedTime) + root.latestPingedTime = latestSuspendedTime; + findNextExpirationTimeToWorkOn(latestSuspendedTime, root); + } else + (retryTime = requestCurrentTime()), + (retryTime = computeExpirationForFiber(retryTime, fiber)), + markPendingPriorityLevel(root, retryTime); + 0 !== (fiber.mode & 1) && + root === nextRoot && + nextRenderExpirationTime === suspendedTime && + (nextRoot = null); + scheduleWorkToRoot(fiber, retryTime); + fiber = root.expirationTime; + 0 !== fiber && requestWork(root, fiber); +} +function scheduleWorkToRoot(fiber, expirationTime) { if (0 === fiber.expirationTime || fiber.expirationTime > expirationTime) fiber.expirationTime = expirationTime; var alternate = fiber.alternate; @@ -5253,44 +5463,24 @@ function scheduleWork(fiber, expirationTime) { } node = node.return; } - fiber = null === root ? null : root; - if (null !== fiber) { - !isWorking && + return null === root ? null : root; +} +function scheduleWork(fiber, expirationTime) { + fiber = scheduleWorkToRoot(fiber, expirationTime); + null !== fiber && + (!isWorking && 0 !== nextRenderExpirationTime && expirationTime < nextRenderExpirationTime && - resetStack(); - markPendingPriorityLevel(fiber, expirationTime); - if (!isWorking || isCommitting$1 || nextRoot !== fiber) { - expirationTime = fiber.expirationTime; - if (null === fiber.nextScheduledRoot) - (fiber.expirationTime = expirationTime), - null === lastScheduledRoot - ? ((firstScheduledRoot = lastScheduledRoot = fiber), - (fiber.nextScheduledRoot = fiber)) - : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = fiber), - (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); - else if ( - ((alternate = fiber.expirationTime), - 0 === alternate || expirationTime < alternate) - ) - fiber.expirationTime = expirationTime; - isRendering || - (isBatchingUpdates - ? isUnbatchingUpdates && - ((nextFlushedRoot = fiber), - (nextFlushedExpirationTime = 1), - performWorkOnRoot(fiber, 1, !0)) - : 1 === expirationTime - ? performWork(1, null) - : scheduleCallbackWithExpirationTime(fiber, expirationTime)); - } + resetStack(), + markPendingPriorityLevel(fiber, expirationTime), + (isWorking && !isCommitting$1 && nextRoot === fiber) || + requestWork(fiber, fiber.expirationTime), nestedUpdateCount > NESTED_UPDATE_LIMIT && ((nestedUpdateCount = 0), 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." - )); - } + ))); } var firstScheduledRoot = null, lastScheduledRoot = null, @@ -5329,6 +5519,37 @@ function scheduleCallbackWithExpirationTime(root, expirationTime) { scheduledCallback = performAsyncWork; callbackID = setTimeout(setTimeoutCallback, 1); } +function onSuspend( + root, + finishedWork, + suspendedExpirationTime, + rootExpirationTime, + msUntilTimeout +) { + root.expirationTime = rootExpirationTime; + 0 !== msUntilTimeout || shouldYield() + ? 0 < msUntilTimeout && + (root.timeoutHandle = scheduleTimeout( + onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), + msUntilTimeout + )) + : ((root.pendingCommitExpirationTime = suspendedExpirationTime), + (root.finishedWork = finishedWork)); +} +function onTimeout(root, finishedWork, suspendedExpirationTime) { + root.pendingCommitExpirationTime = suspendedExpirationTime; + root.finishedWork = finishedWork; + recomputeCurrentRendererTime(); + currentSchedulerTime = currentRendererTime; + invariant( + !isRendering, + "work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method." + ); + nextFlushedRoot = root; + nextFlushedExpirationTime = suspendedExpirationTime; + performWorkOnRoot(root, suspendedExpirationTime, !0); + performWork(1, null); +} function requestCurrentTime() { if (isRendering) return currentSchedulerTime; findHighestPriorityRoot(); @@ -5340,6 +5561,32 @@ function requestCurrentTime() { (currentSchedulerTime = currentRendererTime); return currentSchedulerTime; } +function requestWork(root, expirationTime) { + if (null === root.nextScheduledRoot) + (root.expirationTime = expirationTime), + null === lastScheduledRoot + ? ((firstScheduledRoot = lastScheduledRoot = root), + (root.nextScheduledRoot = root)) + : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = root), + (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); + else { + var remainingExpirationTime = root.expirationTime; + if ( + 0 === remainingExpirationTime || + expirationTime < remainingExpirationTime + ) + root.expirationTime = expirationTime; + } + isRendering || + (isBatchingUpdates + ? isUnbatchingUpdates && + ((nextFlushedRoot = root), + (nextFlushedExpirationTime = 1), + performWorkOnRoot(root, 1, !0)) + : 1 === expirationTime + ? performWork(1, null) + : scheduleCallbackWithExpirationTime(root, expirationTime)); +} function findHighestPriorityRoot() { var highestPriorityWork = 0, highestPriorityRoot = null; @@ -5476,6 +5723,9 @@ function performWorkOnRoot(root, expirationTime, isExpired) { null !== finishedWork ? completeRoot(root, finishedWork, expirationTime) : ((root.finishedWork = null), + (finishedWork = root.timeoutHandle), + -1 !== finishedWork && + ((root.timeoutHandle = -1), cancelTimeout(finishedWork)), renderRoot(root, !1, isExpired), (finishedWork = root.finishedWork), null !== finishedWork && @@ -5485,6 +5735,9 @@ function performWorkOnRoot(root, expirationTime, isExpired) { null !== finishedWork ? completeRoot(root, finishedWork, expirationTime) : ((root.finishedWork = null), + (finishedWork = root.timeoutHandle), + -1 !== finishedWork && + ((root.timeoutHandle = -1), cancelTimeout(finishedWork)), renderRoot(root, !0, isExpired), (finishedWork = root.finishedWork), null !== finishedWork && @@ -5736,6 +5989,13 @@ function completeRoot(root, finishedWork$jscomp$0, expirationTime) { case 15: break; case 16: + if (0 === (current$$1.mode & 2)) + (current$$1.updateQueue = emptyObject$1), + scheduleWork(current$$1, 1); + else { + var currentTime = requestCurrentTime(); + current$$1.stateNode = { timedOutAt: currentTime }; + } break; default: invariant( @@ -6161,7 +6421,7 @@ var roots = new Map(), findFiberByHostInstance: getInstanceFromTag, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.5.2", + version: "16.6.0-alpha.8af6728", rendererPackageName: "react-native-renderer" }); var ReactNativeRenderer$2 = { default: ReactNativeRenderer }, diff --git a/Libraries/Renderer/oss/ReactNativeRenderer-profiling.js b/Libraries/Renderer/oss/ReactNativeRenderer-profiling.js index a8566250cae58a..3a9645d82e6bb4 100644 --- a/Libraries/Renderer/oss/ReactNativeRenderer-profiling.js +++ b/Libraries/Renderer/oss/ReactNativeRenderer-profiling.js @@ -1147,7 +1147,7 @@ var ReactSharedInternals = ? Symbol.for("react.concurrent_mode") : 60111, REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112, - REACT_PLACEHOLDER_TYPE = hasSymbol ? Symbol.for("react.placeholder") : 60113, + REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113, REACT_PURE_TYPE = hasSymbol ? Symbol.for("react.pure") : 60115, MAYBE_ITERATOR_SYMBOL = "function" === typeof Symbol && Symbol.iterator; function getIteratorFn(maybeIterable) { @@ -1157,6 +1157,13 @@ function getIteratorFn(maybeIterable) { maybeIterable["@@iterator"]; return "function" === typeof maybeIterable ? maybeIterable : null; } +function getWrappedName(outerType, innerType, wrapperName) { + innerType = innerType.displayName || innerType.name || ""; + return ( + outerType.displayName || + ("" !== innerType ? wrapperName + "(" + innerType + ")" : wrapperName) + ); +} function getComponentName(type) { if (null == type) return null; if ("function" === typeof type) return type.displayName || type.name || null; @@ -1172,8 +1179,8 @@ function getComponentName(type) { return "Profiler"; case REACT_STRICT_MODE_TYPE: return "StrictMode"; - case REACT_PLACEHOLDER_TYPE: - return "Placeholder"; + case REACT_SUSPENSE_TYPE: + return "Suspense"; } if ("object" === typeof type) { switch (type.$$typeof) { @@ -1182,12 +1189,9 @@ function getComponentName(type) { case REACT_PROVIDER_TYPE: return "Context.Provider"; case REACT_FORWARD_REF_TYPE: - var renderFn = type.render; - renderFn = renderFn.displayName || renderFn.name || ""; - return ( - type.displayName || - ("" !== renderFn ? "ForwardRef(" + renderFn + ")" : "ForwardRef") - ); + return getWrappedName(type, type.render, "ForwardRef"); + case REACT_PURE_TYPE: + return getWrappedName(type, type.render, "Pure"); } if ( "function" === typeof type.then && @@ -1642,6 +1646,7 @@ function finalizeInitialChildren(parentInstance) { return !1; } var scheduleTimeout = setTimeout, + cancelTimeout = clearTimeout, BEFORE_SLASH_RE = /^(.*)[\\\/]/; function getStackByFiberInDevAndProd(workInProgress) { var info = ""; @@ -1898,7 +1903,7 @@ function createFiberFromElement(element, mode, expirationTime) { (type.expirationTime = expirationTime), type ); - case REACT_PLACEHOLDER_TYPE: + case REACT_SUSPENSE_TYPE: fiberTag = 16; break; default: @@ -2034,6 +2039,18 @@ function markSuspendedPriorityLevel(root, suspendedTime) { (root.latestSuspendedTime = suspendedTime); findNextExpirationTimeToWorkOn(suspendedTime, root); } +function findEarliestOutstandingPriorityLevel(root, renderExpirationTime) { + var earliestPendingTime = root.earliestPendingTime; + root = root.earliestSuspendedTime; + if ( + 0 === renderExpirationTime || + (0 !== earliestPendingTime && earliestPendingTime < renderExpirationTime) + ) + renderExpirationTime = earliestPendingTime; + if (0 === renderExpirationTime || (0 !== root && root < renderExpirationTime)) + renderExpirationTime = root; + return renderExpirationTime; +} function findNextExpirationTimeToWorkOn(completedExpirationTime, root) { var earliestSuspendedTime = root.earliestSuspendedTime, latestSuspendedTime = root.latestSuspendedTime, @@ -3397,7 +3414,8 @@ function updatePureComponent( updateExpirationTime, renderExpirationTime ) { - var render = Component.render; + var render = Component.render, + ref = workInProgress.ref; if ( null !== current$$1 && (0 === updateExpirationTime || @@ -3405,7 +3423,8 @@ function updatePureComponent( ((updateExpirationTime = current$$1.memoizedProps), (Component = Component.compare), (Component = null !== Component ? Component : shallowEqual), - Component(updateExpirationTime, nextProps)) + workInProgress.ref === current$$1.ref && + Component(updateExpirationTime, nextProps)) ) return bailoutOnAlreadyFinishedWork( current$$1, @@ -3413,7 +3432,7 @@ function updatePureComponent( renderExpirationTime ); prepareToReadContext(workInProgress, renderExpirationTime); - render = render(nextProps); + render = render(nextProps, ref); workInProgress.effectTag |= 1; reconcileChildren(current$$1, workInProgress, render, renderExpirationTime); workInProgress.memoizedProps = nextProps; @@ -4078,7 +4097,46 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { null ); case 16: - return null; + return ( + (Component = workInProgress.pendingProps), + (props = 0 === (workInProgress.effectTag & 64)), + null !== current$$1 && null !== workInProgress.updateQueue + ? ((workInProgress.updateQueue = null), (props = !0)) + : (props = !props), + 0 !== (workInProgress.mode & 2) && + (props + ? (workInProgress.effectTag |= 4) + : (workInProgress.stateNode = null)), + (updateExpirationTime = Component.children), + (updateExpirationTime = + "function" === typeof updateExpirationTime + ? updateExpirationTime(props) + : props + ? Component.fallback + : updateExpirationTime), + null !== current$$1 && props !== workInProgress.memoizedState + ? ((workInProgress.child = reconcileChildFibers( + workInProgress, + current$$1.child, + null, + renderExpirationTime + )), + (workInProgress.child = reconcileChildFibers( + workInProgress, + null, + updateExpirationTime, + renderExpirationTime + ))) + : reconcileChildren( + current$$1, + workInProgress, + updateExpirationTime, + renderExpirationTime + ), + (workInProgress.memoizedProps = Component), + (workInProgress.memoizedState = props), + workInProgress.child + ); case 6: return ( pushHostContainer( @@ -4368,6 +4426,7 @@ function logCapturedError(capturedError) { : Error("Unspecified error at:" + componentStack); ExceptionsManager.handleException(error, !1); } +var emptyObject$1 = {}; function logError(boundary, errorInfo) { var source = errorInfo.source, stack = errorInfo.stack; @@ -4717,6 +4776,9 @@ function commitWork(current$$1, finishedWork) { ); } } +function NoopComponent() { + return null; +} function createRootErrorUpdate(fiber, errorInfo, expirationTime) { expirationTime = createUpdate(expirationTime); expirationTime.tag = 3; @@ -4764,39 +4826,120 @@ function throwException( ) { sourceFiber.effectTag |= 512; sourceFiber.firstEffect = sourceFiber.lastEffect = null; + if ( + null !== value && + "object" === typeof value && + "function" === typeof value.then + ) { + var thenable = value; + value = returnFiber; + var earliestTimeoutMs = -1, + startTimeMs = -1; + do { + if (16 === value.tag) { + var current = value.alternate; + if ( + null !== current && + !0 === current.memoizedState && + null !== current.stateNode + ) { + startTimeMs = 10 * (current.stateNode.timedOutAt - 2); + break; + } + current = value.pendingProps.maxDuration; + if ("number" === typeof current) + if (0 >= current) earliestTimeoutMs = 0; + else if (-1 === earliestTimeoutMs || current < earliestTimeoutMs) + earliestTimeoutMs = current; + } + value = value.return; + } while (null !== value); + value = returnFiber; + do { + if (16 === value.tag && !value.memoizedState) { + returnFiber = retrySuspendedRoot.bind( + null, + root, + value, + 0 === (value.mode & 1) ? 1 : renderExpirationTime + ); + returnFiber = tracing.unstable_wrap(returnFiber); + thenable.then(returnFiber, returnFiber); + if (0 === (value.mode & 2)) { + value.effectTag |= 4; + reconcileChildren( + sourceFiber.alternate, + sourceFiber, + null, + renderExpirationTime + ); + sourceFiber.effectTag &= -513; + 4 === sourceFiber.tag && (sourceFiber.tag = 0); + if (2 === sourceFiber.tag || 3 === sourceFiber.tag) + (sourceFiber.effectTag &= -421), + null === sourceFiber.alternate && + ((sourceFiber.tag = 0), (sourceFiber.type = NoopComponent)); + return; + } + -1 === earliestTimeoutMs + ? (root = 1073741823) + : (-1 === startTimeMs && + (startTimeMs = + 10 * + (findEarliestOutstandingPriorityLevel( + root, + renderExpirationTime + ) - + 2) - + 5e3), + (root = startTimeMs + earliestTimeoutMs)); + 0 <= root && + nextLatestAbsoluteTimeoutMs < root && + (nextLatestAbsoluteTimeoutMs = root); + value.effectTag |= 1024; + value.expirationTime = renderExpirationTime; + return; + } + value = value.return; + } while (null !== value); + value = Error( + "An update was suspended, but no placeholder UI was provided." + ); + } nextRenderDidError = !0; value = createCapturedValue(value, sourceFiber); root = returnFiber; do { switch (root.tag) { case 5: + sourceFiber = value; root.effectTag |= 1024; root.expirationTime = renderExpirationTime; renderExpirationTime = createRootErrorUpdate( root, - value, + sourceFiber, renderExpirationTime ); enqueueCapturedUpdate(root, renderExpirationTime); return; case 2: case 3: - returnFiber = value; - sourceFiber = root.type; - var instance = root.stateNode; if ( + ((sourceFiber = value), + (returnFiber = root.type), + (thenable = root.stateNode), 0 === (root.effectTag & 64) && - ("function" === typeof sourceFiber.getDerivedStateFromError || - (null !== instance && - "function" === typeof instance.componentDidCatch && - (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(instance)))) + ("function" === typeof returnFiber.getDerivedStateFromError || + (null !== thenable && + "function" === typeof thenable.componentDidCatch && + (null === legacyErrorBoundariesThatAlreadyFailed || + !legacyErrorBoundariesThatAlreadyFailed.has(thenable))))) ) { root.effectTag |= 1024; root.expirationTime = renderExpirationTime; renderExpirationTime = createClassErrorUpdate( root, - returnFiber, + sourceFiber, renderExpirationTime ); enqueueCapturedUpdate(root, renderExpirationTime); @@ -4866,6 +5009,7 @@ var isWorking = !1, nextUnitOfWork = null, nextRoot = null, nextRenderExpirationTime = 0, + nextLatestAbsoluteTimeoutMs = -1, nextRenderDidError = !1, nextEffect = null, isCommitting$1 = !1, @@ -4910,6 +5054,7 @@ function resetStack() { } nextRoot = null; nextRenderExpirationTime = 0; + nextLatestAbsoluteTimeoutMs = -1; nextRenderDidError = !1; nextUnitOfWork = null; } @@ -5070,6 +5215,13 @@ function commitAllLifeCycles( ); break; case 16: + 0 === (finishedWork.mode & 2) + ? ((finishedWork.updateQueue = emptyObject$1), + scheduleWork(finishedWork, 1)) + : ((committedExpirationTime = requestCurrentTime()), + (finishedWork.stateNode = { + timedOutAt: committedExpirationTime + })); break; default: invariant( @@ -5609,7 +5761,23 @@ function renderRoot(root, isYieldy, isExpired) { return; } } - onComplete(root, isYieldy, expirationTime); + isExpired || -1 === nextLatestAbsoluteTimeoutMs + ? onComplete(root, isYieldy, expirationTime) + : (markSuspendedPriorityLevel(root, expirationTime), + (isExpired = + 10 * + (findEarliestOutstandingPriorityLevel(root, expirationTime) - 2)), + isExpired < nextLatestAbsoluteTimeoutMs && + (nextLatestAbsoluteTimeoutMs = isExpired), + (isExpired = 10 * (requestCurrentTime() - 2)), + (isExpired = nextLatestAbsoluteTimeoutMs - isExpired), + onSuspend( + root, + isYieldy, + expirationTime, + root.expirationTime, + 0 > isExpired ? 0 : isExpired + )); } } function captureCommitPhaseError(fiber, error) { @@ -5682,6 +5850,32 @@ function computeExpirationForFiber(currentTime, fiber) { (lowestPriorityPendingInteractiveExpirationTime = currentTime); return currentTime; } +function retrySuspendedRoot(root, fiber, suspendedTime) { + var retryTime = root.earliestSuspendedTime; + var latestSuspendedTime = root.latestSuspendedTime; + if ( + 0 !== retryTime && + suspendedTime >= retryTime && + suspendedTime <= latestSuspendedTime + ) { + latestSuspendedTime = retryTime = suspendedTime; + root.didError = !1; + var latestPingedTime = root.latestPingedTime; + if (0 === latestPingedTime || latestPingedTime < latestSuspendedTime) + root.latestPingedTime = latestSuspendedTime; + findNextExpirationTimeToWorkOn(latestSuspendedTime, root); + } else + (retryTime = requestCurrentTime()), + (retryTime = computeExpirationForFiber(retryTime, fiber)), + markPendingPriorityLevel(root, retryTime); + 0 !== (fiber.mode & 1) && + root === nextRoot && + nextRenderExpirationTime === suspendedTime && + (nextRoot = null); + scheduleWorkToRoot(fiber, retryTime); + fiber = root.expirationTime; + 0 !== fiber && requestWork(root, fiber); +} function scheduleWorkToRoot(fiber, expirationTime) { if (0 === fiber.expirationTime || fiber.expirationTime > expirationTime) fiber.expirationTime = expirationTime; @@ -5736,46 +5930,20 @@ function scheduleWorkToRoot(fiber, expirationTime) { } function scheduleWork(fiber, expirationTime) { fiber = scheduleWorkToRoot(fiber, expirationTime); - if (null !== fiber) { - !isWorking && + null !== fiber && + (!isWorking && 0 !== nextRenderExpirationTime && expirationTime < nextRenderExpirationTime && - resetStack(); - markPendingPriorityLevel(fiber, expirationTime); - if (!isWorking || isCommitting$1 || nextRoot !== fiber) { - expirationTime = fiber.expirationTime; - if (null === fiber.nextScheduledRoot) - (fiber.expirationTime = expirationTime), - null === lastScheduledRoot - ? ((firstScheduledRoot = lastScheduledRoot = fiber), - (fiber.nextScheduledRoot = fiber)) - : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = fiber), - (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); - else { - var remainingExpirationTime = fiber.expirationTime; - if ( - 0 === remainingExpirationTime || - expirationTime < remainingExpirationTime - ) - fiber.expirationTime = expirationTime; - } - isRendering || - (isBatchingUpdates - ? isUnbatchingUpdates && - ((nextFlushedRoot = fiber), - (nextFlushedExpirationTime = 1), - performWorkOnRoot(fiber, 1, !0)) - : 1 === expirationTime - ? performWork(1, null) - : scheduleCallbackWithExpirationTime(fiber, expirationTime)); - } + resetStack(), + markPendingPriorityLevel(fiber, expirationTime), + (isWorking && !isCommitting$1 && nextRoot === fiber) || + requestWork(fiber, fiber.expirationTime), nestedUpdateCount > NESTED_UPDATE_LIMIT && ((nestedUpdateCount = 0), 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." - )); - } + ))); } var firstScheduledRoot = null, lastScheduledRoot = null, @@ -5826,13 +5994,29 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - 0 < msUntilTimeout && - (root.timeoutHandle = scheduleTimeout( - onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), - msUntilTimeout - )); + 0 !== msUntilTimeout || shouldYield() + ? 0 < msUntilTimeout && + (root.timeoutHandle = scheduleTimeout( + onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), + msUntilTimeout + )) + : ((root.pendingCommitExpirationTime = suspendedExpirationTime), + (root.finishedWork = finishedWork)); +} +function onTimeout(root, finishedWork, suspendedExpirationTime) { + root.pendingCommitExpirationTime = suspendedExpirationTime; + root.finishedWork = finishedWork; + recomputeCurrentRendererTime(); + currentSchedulerTime = currentRendererTime; + invariant( + !isRendering, + "work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method." + ); + nextFlushedRoot = root; + nextFlushedExpirationTime = suspendedExpirationTime; + performWorkOnRoot(root, suspendedExpirationTime, !0); + performWork(1, null); } -function onTimeout() {} function onCommit(root, expirationTime) { root.expirationTime = expirationTime; root.finishedWork = null; @@ -5848,6 +6032,32 @@ function requestCurrentTime() { (currentSchedulerTime = currentRendererTime); return currentSchedulerTime; } +function requestWork(root, expirationTime) { + if (null === root.nextScheduledRoot) + (root.expirationTime = expirationTime), + null === lastScheduledRoot + ? ((firstScheduledRoot = lastScheduledRoot = root), + (root.nextScheduledRoot = root)) + : ((lastScheduledRoot = lastScheduledRoot.nextScheduledRoot = root), + (lastScheduledRoot.nextScheduledRoot = firstScheduledRoot)); + else { + var remainingExpirationTime = root.expirationTime; + if ( + 0 === remainingExpirationTime || + expirationTime < remainingExpirationTime + ) + root.expirationTime = expirationTime; + } + isRendering || + (isBatchingUpdates + ? isUnbatchingUpdates && + ((nextFlushedRoot = root), + (nextFlushedExpirationTime = 1), + performWorkOnRoot(root, 1, !0)) + : 1 === expirationTime + ? performWork(1, null) + : scheduleCallbackWithExpirationTime(root, expirationTime)); +} function findHighestPriorityRoot() { var highestPriorityWork = 0, highestPriorityRoot = null; @@ -5984,6 +6194,9 @@ function performWorkOnRoot(root, expirationTime, isExpired) { null !== finishedWork ? completeRoot(root, finishedWork, expirationTime) : ((root.finishedWork = null), + (finishedWork = root.timeoutHandle), + -1 !== finishedWork && + ((root.timeoutHandle = -1), cancelTimeout(finishedWork)), renderRoot(root, !1, isExpired), (finishedWork = root.finishedWork), null !== finishedWork && @@ -5993,6 +6206,9 @@ function performWorkOnRoot(root, expirationTime, isExpired) { null !== finishedWork ? completeRoot(root, finishedWork, expirationTime) : ((root.finishedWork = null), + (finishedWork = root.timeoutHandle), + -1 !== finishedWork && + ((root.timeoutHandle = -1), cancelTimeout(finishedWork)), renderRoot(root, !0, isExpired), (finishedWork = root.finishedWork), null !== finishedWork && @@ -6397,7 +6613,7 @@ var roots = new Map(), findFiberByHostInstance: getInstanceFromTag, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.5.2", + version: "16.6.0-alpha.8af6728", rendererPackageName: "react-native-renderer" }); var ReactNativeRenderer$2 = { default: ReactNativeRenderer },