diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index afe4ebf1265..b51f74404e8 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -f24a0da6e0f59484e5aafd0825bb1a6ed27d7182 \ No newline at end of file +8e25ed20bd27d126f670d04680db85209f779056 \ No newline at end of file diff --git a/Libraries/Renderer/oss/ReactFabric-dev.js b/Libraries/Renderer/oss/ReactFabric-dev.js index 147df8bf432..3dbff8b0852 100644 --- a/Libraries/Renderer/oss/ReactFabric-dev.js +++ b/Libraries/Renderer/oss/ReactFabric-dev.js @@ -1090,6 +1090,7 @@ var MemoComponent = 14; var SimpleMemoComponent = 15; var LazyComponent = 16; var IncompleteClassComponent = 17; +var DehydratedSuspenseComponent = 18; function getParent(inst) { do { @@ -3503,6 +3504,19 @@ function shouldYield$1() { return frameDeadline <= now$1(); } +var debugRenderPhaseSideEffects = false; +var debugRenderPhaseSideEffectsForStrictMode = false; +var enableUserTimingAPI = true; +var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; +var warnAboutDeprecatedLifecycles = false; +var enableProfilerTimer = true; +var enableSchedulerTracing = true; +var enableSuspenseServerRenderer = false; + +var warnAboutDeprecatedSetNativeProps = false; + +// Only used in www builds. + // Use to restore controlled state after a change event has fired. var restoreImpl = null; @@ -3651,21 +3665,31 @@ function shim$1() { } // Hydration (when unsupported) + var supportsHydration = false; var canHydrateInstance = shim$1; var canHydrateTextInstance = shim$1; +var canHydrateSuspenseInstance = shim$1; +var isSuspenseInstancePending = shim$1; +var isSuspenseInstanceFallback = shim$1; +var registerSuspenseInstanceRetry = shim$1; var getNextHydratableSibling = shim$1; var getFirstHydratableChild = shim$1; var hydrateInstance = shim$1; var hydrateTextInstance = shim$1; +var getNextHydratableInstanceAfterSuspenseInstance = shim$1; +var clearSuspenseBoundary = shim$1; +var clearSuspenseBoundaryFromContainer = shim$1; var didNotMatchHydratedContainerTextInstance = shim$1; var didNotMatchHydratedTextInstance = shim$1; var didNotHydrateContainerInstance = shim$1; var didNotHydrateInstance = shim$1; var didNotFindHydratableContainerInstance = shim$1; var didNotFindHydratableContainerTextInstance = shim$1; +var didNotFindHydratableContainerSuspenseInstance = shim$1; var didNotFindHydratableInstance = shim$1; var didNotFindHydratableTextInstance = shim$1; +var didNotFindHydratableSuspenseInstance = shim$1; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -3742,6 +3766,15 @@ var ReactFabricHostComponent = (function() { nativeProps ) { { + if (warnAboutDeprecatedSetNativeProps) { + warningWithoutStack$1( + false, + "Warning: Calling ref.setNativeProps(nativeProps) " + + "is deprecated and will be removed in a future release. " + + "Use the setNativeProps export from the react-native package instead." + + "\n\timport {setNativeProps} from 'react-native';\n\tsetNativeProps(ref, nativeProps);\n" + ); + } warnForStyleProps(nativeProps, this.viewConfig.validAttributes); } @@ -4121,16 +4154,6 @@ function setCurrentPhase(lifeCyclePhase) { } } -var debugRenderPhaseSideEffects = false; -var debugRenderPhaseSideEffectsForStrictMode = false; -var enableUserTimingAPI = true; -var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; -var warnAboutDeprecatedLifecycles = false; -var enableProfilerTimer = true; -var enableSchedulerTracing = true; - -// Only used in www builds. - // Prefix measurements so that it's possible to filter them. // Longer prefixes are hard to read in DevTools. var reactEmoji = "\u269B"; @@ -4402,7 +4425,8 @@ function stopFailedWorkTimer(fiber) { } fiber._debugIsCurrentlyTiming = false; var warning = - fiber.tag === SuspenseComponent + fiber.tag === SuspenseComponent || + fiber.tag === DehydratedSuspenseComponent ? "Rendering was suspended" : "An error was thrown inside this error boundary"; endFiberMark(fiber, null, warning); @@ -9277,17 +9301,6 @@ function mountWorkInProgressHook() { { hook._debugType = currentHookNameInDev; - if ( - currentlyRenderingFiber$1 !== null && - currentlyRenderingFiber$1.alternate !== null - ) { - warning$1( - false, - "%s: Rendered more hooks than during the previous render. This is " + - "not currently supported and may lead to unexpected behavior.", - getComponentName(currentlyRenderingFiber$1.type) - ); - } } if (workInProgressHook === null) { // This is the first hook in the list @@ -9431,7 +9444,6 @@ function updateReducer(reducer, initialArg, init) { } hook.memoizedState = newState; - // Don't persist the state accumlated from the render phase updates to // the base state unless the queue is empty. // TODO: Not sure if this is the desired semantics, but it's what we @@ -9440,6 +9452,9 @@ function updateReducer(reducer, initialArg, init) { hook.baseState = newState; } + queue.eagerReducer = reducer; + queue.eagerState = newState; + return [newState, _dispatch]; } } @@ -10302,6 +10317,18 @@ function enterHydrationState(fiber) { return true; } +function reenterHydrationStateFromDehydratedSuspenseInstance(fiber) { + if (!supportsHydration) { + return false; + } + + var suspenseInstance = fiber.stateNode; + nextHydratableInstance = getNextHydratableSibling(suspenseInstance); + popToNextHostParent(fiber); + isHydrating = true; + return true; +} + function deleteHydratableInstance(returnFiber, instance) { { switch (returnFiber.tag) { @@ -10356,6 +10383,9 @@ function insertNonHydratedInstance(returnFiber, fiber) { var text = fiber.pendingProps; didNotFindHydratableContainerTextInstance(parentContainer, text); break; + case SuspenseComponent: + didNotFindHydratableContainerSuspenseInstance(parentContainer); + break; } break; } @@ -10384,6 +10414,13 @@ function insertNonHydratedInstance(returnFiber, fiber) { _text ); break; + case SuspenseComponent: + didNotFindHydratableSuspenseInstance( + parentType, + parentProps, + parentInstance + ); + break; } break; } @@ -10414,6 +10451,18 @@ function tryHydrate(fiber, nextInstance) { } return false; } + case SuspenseComponent: { + if (enableSuspenseServerRenderer) { + var suspenseInstance = canHydrateSuspenseInstance(nextInstance); + if (suspenseInstance !== null) { + // Downgrade the tag to a dehydrated component until we've hydrated it. + fiber.tag = DehydratedSuspenseComponent; + fiber.stateNode = suspenseInstance; + return true; + } + } + return false; + } default: return false; } @@ -10534,12 +10583,32 @@ function prepareToHydrateHostTextInstance(fiber) { return shouldUpdate; } +function skipPastDehydratedSuspenseInstance(fiber) { + if (!supportsHydration) { + invariant( + false, + "Expected skipPastDehydratedSuspenseInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + var suspenseInstance = fiber.stateNode; + invariant( + suspenseInstance, + "Expected to have a hydrated suspense instance. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + nextHydratableInstance = getNextHydratableInstanceAfterSuspenseInstance( + suspenseInstance + ); +} + function popToNextHostParent(fiber) { var parent = fiber.return; while ( parent !== null && parent.tag !== HostComponent && - parent.tag !== HostRoot + parent.tag !== HostRoot && + parent.tag !== DehydratedSuspenseComponent ) { parent = parent.return; } @@ -10691,6 +10760,10 @@ function updateForwardRef( nextProps, renderExpirationTime ) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens after the first render suspends. + // We'll need to figure out if this is fine or can cause issues. + { if (workInProgress.type !== workInProgress.elementType) { // Lazy component props can't be validated in createElement @@ -10880,6 +10953,10 @@ function updateSimpleMemoComponent( updateExpirationTime, renderExpirationTime ) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens when the inner render suspends. + // We'll need to figure out if this is fine or can cause issues. + { if (workInProgress.type !== workInProgress.elementType) { // Lazy component props can't be validated in createElement @@ -11833,6 +11910,22 @@ function updateSuspenseComponent( // children -- we skip over the primary children entirely. var next = void 0; if (current$$1 === null) { + if (enableSuspenseServerRenderer) { + // If we're currently hydrating, try to hydrate this boundary. + // But only if this has a fallback. + if (nextProps.fallback !== undefined) { + tryToClaimNextHydratableInstance(workInProgress); + // This could've changed the tag if this was a dehydrated suspense component. + if (workInProgress.tag === DehydratedSuspenseComponent) { + return updateDehydratedSuspenseComponent( + null, + workInProgress, + renderExpirationTime + ); + } + } + } + // This is the initial mount. This branch is pretty simple because there's // no previous state that needs to be preserved. if (nextDidTimeout) { @@ -12035,6 +12128,107 @@ function updateSuspenseComponent( return next; } +function updateDehydratedSuspenseComponent( + current$$1, + workInProgress, + renderExpirationTime +) { + if (current$$1 === null) { + // During the first pass, we'll bail out and not drill into the children. + // Instead, we'll leave the content in place and try to hydrate it later. + workInProgress.expirationTime = Never; + return null; + } + if ((workInProgress.effectTag & DidCapture) !== NoEffect) { + // Something suspended. Leave the existing children in place. + // TODO: In non-concurrent mode, should we commit the nodes we have hydrated so far? + workInProgress.child = null; + return null; + } + // We use childExpirationTime to indicate that a child might depend on context, so if + // any context has changed, we need to treat is as if the input might have changed. + var hasContextChanged$$1 = + current$$1.childExpirationTime >= renderExpirationTime; + var suspenseInstance = current$$1.stateNode; + if ( + didReceiveUpdate || + hasContextChanged$$1 || + isSuspenseInstanceFallback(suspenseInstance) + ) { + // This boundary has changed since the first render. This means that we are now unable to + // hydrate it. We might still be able to hydrate it using an earlier expiration time but + // during this render we can't. Instead, we're going to delete the whole subtree and + // instead inject a new real Suspense boundary to take its place, which may render content + // or fallback. The real Suspense boundary will suspend for a while so we have some time + // to ensure it can produce real content, but all state and pending events will be lost. + + // Alternatively, this boundary is in a permanent fallback state. In this case, we'll never + // get an update and we'll never be able to hydrate the final content. Let's just try the + // client side render instead. + + // Detach from the current dehydrated boundary. + current$$1.alternate = null; + workInProgress.alternate = null; + + // Insert a deletion in the effect list. + var returnFiber = workInProgress.return; + invariant( + returnFiber !== null, + "Suspense boundaries are never on the root. " + + "This is probably a bug in React." + ); + var last = returnFiber.lastEffect; + if (last !== null) { + last.nextEffect = current$$1; + returnFiber.lastEffect = current$$1; + } else { + returnFiber.firstEffect = returnFiber.lastEffect = current$$1; + } + current$$1.nextEffect = null; + current$$1.effectTag = Deletion; + + // Upgrade this work in progress to a real Suspense component. + workInProgress.tag = SuspenseComponent; + workInProgress.stateNode = null; + workInProgress.memoizedState = null; + // This is now an insertion. + workInProgress.effectTag |= Placement; + // Retry as a real Suspense component. + return updateSuspenseComponent(null, workInProgress, renderExpirationTime); + } else if (isSuspenseInstancePending(suspenseInstance)) { + // This component is still pending more data from the server, so we can't hydrate its + // content. We treat it as if this component suspended itself. It might seem as if + // we could just try to render it client-side instead. However, this will perform a + // lot of unnecessary work and is unlikely to complete since it often will suspend + // on missing data anyway. Additionally, the server might be able to render more + // than we can on the client yet. In that case we'd end up with more fallback states + // on the client than if we just leave it alone. If the server times out or errors + // these should update this boundary to the permanent Fallback state instead. + // Mark it as having captured (i.e. suspended). + workInProgress.effectTag |= DidCapture; + // Leave the children in place. I.e. empty. + workInProgress.child = null; + // Register a callback to retry this boundary once the server has sent the result. + registerSuspenseInstanceRetry( + suspenseInstance, + retryTimedOutBoundary.bind(null, current$$1) + ); + return null; + } else { + // This is the first attempt. + reenterHydrationStateFromDehydratedSuspenseInstance(workInProgress); + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + workInProgress.child = mountChildFibers( + workInProgress, + null, + nextChildren, + renderExpirationTime + ); + return workInProgress.child; + } +} + function updatePortalComponent( current$$1, workInProgress, @@ -12321,6 +12515,15 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { } break; } + case DehydratedSuspenseComponent: { + if (enableSuspenseServerRenderer) { + // We know that this component will suspend again because if it has + // been unsuspended it has committed as a regular Suspense component. + // If it needs to be retried, it should have work scheduled on it. + workInProgress.effectTag |= DidCapture; + break; + } + } } return bailoutOnAlreadyFinishedWork( current$$1, @@ -12494,13 +12697,22 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { renderExpirationTime ); } - default: - invariant( - false, - "Unknown unit of work tag. This error is likely caused by a bug in " + - "React. Please file an issue." - ); + case DehydratedSuspenseComponent: { + if (enableSuspenseServerRenderer) { + return updateDehydratedSuspenseComponent( + current$$1, + workInProgress, + renderExpirationTime + ); + } + break; + } } + invariant( + false, + "Unknown unit of work tag. This error is likely caused by a bug in " + + "React. Please file an issue." + ); } var valueCursor = createCursor(null); @@ -12619,6 +12831,34 @@ function calculateChangedBits(context, newValue, oldValue) { } } +function scheduleWorkOnParentPath(parent, renderExpirationTime) { + // Update the child expiration time of all the ancestors, including + // the alternates. + var node = parent; + while (node !== null) { + var alternate = node.alternate; + if (node.childExpirationTime < renderExpirationTime) { + node.childExpirationTime = renderExpirationTime; + if ( + alternate !== null && + alternate.childExpirationTime < renderExpirationTime + ) { + alternate.childExpirationTime = renderExpirationTime; + } + } else if ( + alternate !== null && + alternate.childExpirationTime < renderExpirationTime + ) { + alternate.childExpirationTime = renderExpirationTime; + } else { + // Neither alternate was updated, which means the rest of the + // ancestor path already has sufficient priority. + break; + } + node = node.return; + } +} + function propagateContextChange( workInProgress, context, @@ -12668,31 +12908,8 @@ function propagateContextChange( ) { alternate.expirationTime = renderExpirationTime; } - // Update the child expiration time of all the ancestors, including - // the alternates. - var node = fiber.return; - while (node !== null) { - alternate = node.alternate; - if (node.childExpirationTime < renderExpirationTime) { - node.childExpirationTime = renderExpirationTime; - if ( - alternate !== null && - alternate.childExpirationTime < renderExpirationTime - ) { - alternate.childExpirationTime = renderExpirationTime; - } - } else if ( - alternate !== null && - alternate.childExpirationTime < renderExpirationTime - ) { - alternate.childExpirationTime = renderExpirationTime; - } else { - // Neither alternate was updated, which means the rest of the - // ancestor path already has sufficient priority. - break; - } - node = node.return; - } + + scheduleWorkOnParentPath(fiber.return, renderExpirationTime); // Mark the expiration time on the list, too. if (list.expirationTime < renderExpirationTime) { @@ -12708,6 +12925,29 @@ function propagateContextChange( } else if (fiber.tag === ContextProvider) { // Don't scan deeper if this is a matching provider nextFiber = fiber.type === workInProgress.type ? null : fiber.child; + } else if ( + enableSuspenseServerRenderer && + fiber.tag === DehydratedSuspenseComponent + ) { + // If a dehydrated suspense component is in this subtree, we don't know + // if it will have any context consumers in it. The best we can do is + // mark it as having updates on its children. + if (fiber.expirationTime < renderExpirationTime) { + fiber.expirationTime = renderExpirationTime; + } + var _alternate = fiber.alternate; + if ( + _alternate !== null && + _alternate.expirationTime < renderExpirationTime + ) { + _alternate.expirationTime = renderExpirationTime; + } + // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childExpirationTime on + // this fiber to indicate that a context has changed. + scheduleWorkOnParentPath(fiber, renderExpirationTime); + nextFiber = fiber.sibling; } else { // Traverse down. nextFiber = fiber.child; @@ -13984,7 +14224,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { var nextDidTimeout = nextState !== null; var prevDidTimeout = current !== null && current.memoizedState !== null; - if (current !== null && !nextDidTimeout && prevDidTimeout) { + if (current === null) { + // In cases where we didn't find a suitable hydration boundary we never + // downgraded this to a DehydratedSuspenseComponent, but we still need to + // pop the hydration state since we might be inside the insertion tree. + popHydrationState(workInProgress); + } else if (!nextDidTimeout && prevDidTimeout) { // We just switched from the fallback to the normal children. Delete // the fallback. // TODO: Would it be better to store the fallback fragment on @@ -14038,6 +14283,29 @@ function completeWork(current, workInProgress, renderExpirationTime) { } break; } + case DehydratedSuspenseComponent: { + if (enableSuspenseServerRenderer) { + if (current === null) { + var _wasHydrated2 = popHydrationState(workInProgress); + invariant( + _wasHydrated2, + "A dehydrated suspense component was completed without a hydrated node. " + + "This is probably a bug in React." + ); + skipPastDehydratedSuspenseInstance(workInProgress); + } else if ((workInProgress.effectTag & DidCapture) === NoEffect) { + // This boundary did not suspend so it's now hydrated. + // To handle any future suspense cases, we're going to now upgrade it + // to a Suspense component. We detach it from the existing current fiber. + current.alternate = null; + workInProgress.alternate = null; + workInProgress.tag = SuspenseComponent; + workInProgress.memoizedState = null; + workInProgress.stateNode = null; + } + } + break; + } default: invariant( false, @@ -14181,7 +14449,7 @@ var didWarnAboutUndefinedSnapshotBeforeUpdate = null; didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); } -var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; +var PossiblyWeakSet$1 = typeof WeakSet === "function" ? WeakSet : Set; function logError(boundary, errorInfo) { var source = errorInfo.source; @@ -14938,7 +15206,11 @@ function getHostSibling(fiber) { } node.sibling.return = node.return; node = node.sibling; - while (node.tag !== HostComponent && node.tag !== HostText) { + while ( + node.tag !== HostComponent && + node.tag !== HostText && + node.tag !== DehydratedSuspenseComponent + ) { // If it is not host node and, we might have a host node inside it. // Try to search down until we find one. if (node.effectTag & Placement) { @@ -15093,6 +15365,16 @@ function unmountHostComponents(current$$1) { removeChild(currentParent, node.stateNode); } // Don't visit children because we already visited them. + } else if ( + enableSuspenseServerRenderer && + node.tag === DehydratedSuspenseComponent + ) { + // Delete the dehydrated suspense boundary and all of its content. + if (currentParentIsContainer) { + clearSuspenseBoundaryFromContainer(currentParent, node.stateNode); + } else { + clearSuspenseBoundary(currentParent, node.stateNode); + } } else if (node.tag === HostPortal) { if (node.child !== null) { // When we go into a portal, it becomes the parent to remove from. @@ -15253,11 +15535,11 @@ function commitWork(current$$1, finishedWork) { finishedWork.updateQueue = null; var retryCache = finishedWork.stateNode; if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + retryCache = finishedWork.stateNode = new PossiblyWeakSet$1(); } thenables.forEach(function(thenable) { // Memoize using the boundary fiber to prevent redundant listeners. - var retry = retryTimedOutBoundary.bind(null, finishedWork, thenable); + var retry = resolveRetryThenable.bind(null, finishedWork, thenable); if (enableSchedulerTracing) { retry = tracing.unstable_wrap(retry); } @@ -15290,6 +15572,7 @@ function commitResetTextContent(current$$1) { resetTextContent(current$$1.stateNode); } +var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; function createRootErrorUpdate(fiber, errorInfo, expirationTime) { @@ -15355,6 +15638,39 @@ function createClassErrorUpdate(fiber, errorInfo, expirationTime) { return update; } +function attachPingListener(root, renderExpirationTime, thenable) { + // Attach a listener to the promise to "ping" the root and retry. But + // only if one does not already exist for the current render expiration + // time (which acts like a "thread ID" here). + var pingCache = root.pingCache; + var threadIDs = void 0; + if (pingCache === null) { + pingCache = root.pingCache = new PossiblyWeakMap(); + threadIDs = new Set(); + pingCache.set(thenable, threadIDs); + } else { + threadIDs = pingCache.get(thenable); + if (threadIDs === undefined) { + threadIDs = new Set(); + pingCache.set(thenable, threadIDs); + } + } + if (!threadIDs.has(renderExpirationTime)) { + // Memoize using the thread ID to prevent redundant listeners. + threadIDs.add(renderExpirationTime); + var ping = pingSuspendedRoot.bind( + null, + root, + thenable, + renderExpirationTime + ); + if (enableSchedulerTracing) { + ping = tracing.unstable_wrap(ping); + } + thenable.then(ping, ping); + } +} + function throwException( root, returnFiber, @@ -15409,6 +15725,9 @@ function throwException( } } } + // If there is a DehydratedSuspenseComponent we don't have to do anything because + // if something suspends inside it, we will simply leave that as dehydrated. It + // will never timeout. _workInProgress = _workInProgress.return; } while (_workInProgress !== null); @@ -15475,36 +15794,7 @@ function throwException( // Confirmed that the boundary is in a concurrent mode tree. Continue // with the normal suspend path. - // Attach a listener to the promise to "ping" the root and retry. But - // only if one does not already exist for the current render expiration - // time (which acts like a "thread ID" here). - var pingCache = root.pingCache; - var threadIDs = void 0; - if (pingCache === null) { - pingCache = root.pingCache = new PossiblyWeakMap(); - threadIDs = new Set(); - pingCache.set(thenable, threadIDs); - } else { - threadIDs = pingCache.get(thenable); - if (threadIDs === undefined) { - threadIDs = new Set(); - pingCache.set(thenable, threadIDs); - } - } - if (!threadIDs.has(renderExpirationTime)) { - // Memoize using the thread ID to prevent redundant listeners. - threadIDs.add(renderExpirationTime); - var ping = pingSuspendedRoot.bind( - null, - root, - thenable, - renderExpirationTime - ); - if (enableSchedulerTracing) { - ping = tracing.unstable_wrap(ping); - } - thenable.then(ping, ping); - } + attachPingListener(root, renderExpirationTime, thenable); var absoluteTimeoutMs = void 0; if (earliestTimeoutMs === -1) { @@ -15541,6 +15831,40 @@ function throwException( // whole tree. renderDidSuspend(root, absoluteTimeoutMs, renderExpirationTime); + _workInProgress.effectTag |= ShouldCapture; + _workInProgress.expirationTime = renderExpirationTime; + return; + } else if ( + enableSuspenseServerRenderer && + _workInProgress.tag === DehydratedSuspenseComponent + ) { + attachPingListener(root, renderExpirationTime, thenable); + + // Since we already have a current fiber, we can eagerly add a retry listener. + var retryCache = _workInProgress.memoizedState; + if (retryCache === null) { + retryCache = _workInProgress.memoizedState = new PossiblyWeakSet(); + var _current = _workInProgress.alternate; + invariant( + _current, + "A dehydrated suspense boundary must commit before trying to render. " + + "This is probably a bug in React." + ); + _current.memoizedState = retryCache; + } + // Memoize using the boundary fiber to prevent redundant listeners. + if (!retryCache.has(thenable)) { + retryCache.add(thenable); + var retry = resolveRetryThenable.bind( + null, + _workInProgress, + thenable + ); + if (enableSchedulerTracing) { + retry = tracing.unstable_wrap(retry); + } + thenable.then(retry, retry); + } _workInProgress.effectTag |= ShouldCapture; _workInProgress.expirationTime = renderExpirationTime; return; @@ -15639,6 +15963,7 @@ function unwindWork(workInProgress, renderExpirationTime) { return workInProgress; } case HostComponent: { + // TODO: popHydrationState popHostContext(workInProgress); return null; } @@ -15651,6 +15976,19 @@ function unwindWork(workInProgress, renderExpirationTime) { } return null; } + case DehydratedSuspenseComponent: { + if (enableSuspenseServerRenderer) { + // TODO: popHydrationState + var _effectTag3 = workInProgress.effectTag; + if (_effectTag3 & ShouldCapture) { + workInProgress.effectTag = + (_effectTag3 & ~ShouldCapture) | DidCapture; + // Captured a suspense effect. Re-render the boundary. + return workInProgress; + } + } + return null; + } case HostPortal: popHostContainer(workInProgress); return null; @@ -16070,6 +16408,10 @@ function commitPassiveEffects(root, firstEffect) { if (rootExpirationTime !== NoWork) { requestWork(root, rootExpirationTime); } + // Flush any sync work that was scheduled by effects + if (!isBatchingUpdates && !isRendering) { + performSyncWork(); + } } function isAlreadyFailedLegacyErrorBoundary(instance) { @@ -16685,7 +17027,7 @@ function workLoop(isYieldy) { } } else { // Flush asynchronous work until there's a higher priority event - while (nextUnitOfWork !== null && !shouldYieldToRenderer()) { + while (nextUnitOfWork !== null && !shouldYield$$1()) { nextUnitOfWork = performUnitOfWork(nextUnitOfWork); } } @@ -17144,17 +17486,7 @@ function pingSuspendedRoot(root, thenable, pingTime) { } } -function retryTimedOutBoundary(boundaryFiber, thenable) { - // The boundary fiber (a Suspense component) previously timed out and was - // rendered in its fallback state. One of the promises that suspended it has - // resolved, which means at least part of the tree was likely unblocked. Try - var retryCache = boundaryFiber.stateNode; - if (retryCache !== null) { - // The thenable resolved, so we no longer need to memoize, because it will - // never be thrown again. - retryCache.delete(thenable); - } - +function retryTimedOutBoundary(boundaryFiber) { var currentTime = requestCurrentTime(); var retryTime = computeExpirationForFiber(currentTime, boundaryFiber); var root = scheduleWorkToRoot(boundaryFiber, retryTime); @@ -17167,6 +17499,38 @@ function retryTimedOutBoundary(boundaryFiber, thenable) { } } +function resolveRetryThenable(boundaryFiber, thenable) { + // The boundary fiber (a Suspense component) previously timed out and was + // rendered in its fallback state. One of the promises that suspended it has + // resolved, which means at least part of the tree was likely unblocked. Try + var retryCache = void 0; + if (enableSuspenseServerRenderer) { + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + break; + case DehydratedSuspenseComponent: + retryCache = boundaryFiber.memoizedState; + break; + default: + invariant( + false, + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); + } + } else { + retryCache = boundaryFiber.stateNode; + } + if (retryCache !== null) { + // The thenable resolved, so we no longer need to memoize, because it will + // never be thrown again. + retryCache.delete(thenable); + } + + retryTimedOutBoundary(boundaryFiber); +} + function scheduleWorkToRoot(fiber, expirationTime) { recordScheduleUpdate(); @@ -17265,8 +17629,10 @@ function warnIfNotCurrentlyBatchingInDev(fiber) { "});\n" + "/* assert on the output */\n\n" + "This ensures that you're testing the behavior the user would see in the browser." + - " Learn more at https://fb.me/react-wrap-tests-with-act", - getComponentName(fiber.type) + " Learn more at https://fb.me/react-wrap-tests-with-act" + + "%s", + getComponentName(fiber.type), + getStackByFiberInDevAndProd(fiber) ); } } @@ -17408,7 +17774,7 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - if (msUntilTimeout === 0 && !shouldYieldToRenderer()) { + if (msUntilTimeout === 0 && !shouldYield$$1()) { // Don't wait an additional tick. Commit the tree immediately. root.pendingCommitExpirationTime = suspendedExpirationTime; root.finishedWork = finishedWork; @@ -17605,43 +17971,24 @@ function findHighestPriorityRoot() { nextFlushedExpirationTime = highestPriorityWork; } -// TODO: This wrapper exists because many of the older tests (the ones that use -// flushDeferredPri) rely on the number of times `shouldYield` is called. We -// should get rid of it. -var didYield = false; -function shouldYieldToRenderer() { - if (didYield) { - return true; - } - if (shouldYield$$1()) { - didYield = true; - return true; - } - return false; -} - -function performAsyncWork() { - try { - if (!shouldYieldToRenderer()) { - // The callback timed out. That means at least one update has expired. - // Iterate through the root schedule. If they contain expired work, set - // the next render expiration time to the current time. This has the effect - // of flushing all expired work in a single batch, instead of flushing each - // level one at a time. - if (firstScheduledRoot !== null) { - recomputeCurrentRendererTime(); - var root = firstScheduledRoot; - do { - didExpireAtExpirationTime(root, currentRendererTime); - // The root schedule is circular, so this is never null. - root = root.nextScheduledRoot; - } while (root !== firstScheduledRoot); - } +function performAsyncWork(didTimeout) { + if (didTimeout) { + // The callback timed out. That means at least one update has expired. + // Iterate through the root schedule. If they contain expired work, set + // the next render expiration time to the current time. This has the effect + // of flushing all expired work in a single batch, instead of flushing each + // level one at a time. + if (firstScheduledRoot !== null) { + recomputeCurrentRendererTime(); + var root = firstScheduledRoot; + do { + didExpireAtExpirationTime(root, currentRendererTime); + // The root schedule is circular, so this is never null. + root = root.nextScheduledRoot; + } while (root !== firstScheduledRoot); } - performWork(NoWork, true); - } finally { - didYield = false; } + performWork(NoWork, true); } function performSyncWork() { @@ -17667,7 +18014,7 @@ function performWork(minExpirationTime, isYieldy) { nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && minExpirationTime <= nextFlushedExpirationTime && - !(didYield && currentRendererTime > nextFlushedExpirationTime) + !(shouldYield$$1() && currentRendererTime > nextFlushedExpirationTime) ) { performWorkOnRoot( nextFlushedRoot, @@ -17811,7 +18158,7 @@ function performWorkOnRoot(root, expirationTime, isYieldy) { if (_finishedWork !== null) { // We've completed the root. Check the if we should yield one more time // before committing. - if (!shouldYieldToRenderer()) { + if (!shouldYield$$1()) { // Still time left. Commit the root. completeRoot$1(root, _finishedWork, expirationTime); } else { @@ -18226,7 +18573,7 @@ function createPortal( // TODO: this is special because it gets imported during build. -var ReactVersion = "16.8.1"; +var ReactVersion = "16.8.3"; // Modules provided by RN: var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { @@ -18320,6 +18667,17 @@ var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { * Manipulation](docs/direct-manipulation.html)). */ setNativeProps: function(nativeProps) { + { + if (warnAboutDeprecatedSetNativeProps) { + warningWithoutStack$1( + false, + "Warning: Calling ref.setNativeProps(nativeProps) " + + "is deprecated and will be removed in a future release. " + + "Use the setNativeProps export from the react-native package instead." + + "\n\timport {setNativeProps} from 'react-native';\n\tsetNativeProps(ref, nativeProps);\n" + ); + } + } // Class components don't have viewConfig -> validateAttributes. // Nor does it make sense to set native props on a non-native component. // Instead, find the nearest host component and set props on it. @@ -18341,7 +18699,10 @@ var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { return; } - var viewConfig = maybeInstance.viewConfig; + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + var viewConfig = + maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; { warnForStyleProps(nativeProps, viewConfig.validAttributes); @@ -18354,7 +18715,7 @@ var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { // view invalidation for certain components (eg RCTTextInput) on iOS. if (updatePayload != null) { UIManager.updateView( - maybeInstance._nativeTag, + nativeTag, viewConfig.uiViewClassName, updatePayload ); @@ -18575,6 +18936,18 @@ var ReactNativeComponent = function(findNodeHandle, findHostInstance) { ReactNativeComponent.prototype.setNativeProps = function setNativeProps( nativeProps ) { + { + if (warnAboutDeprecatedSetNativeProps) { + warningWithoutStack$1( + false, + "Warning: Calling ref.setNativeProps(nativeProps) " + + "is deprecated and will be removed in a future release. " + + "Use the setNativeProps export from the react-native package instead." + + "\n\timport {setNativeProps} from 'react-native';\n\tsetNativeProps(ref, nativeProps);\n" + ); + } + } + // Class components don't have viewConfig -> validateAttributes. // Nor does it make sense to set native props on a non-native component. // Instead, find the nearest host component and set props on it. @@ -18596,6 +18969,8 @@ var ReactNativeComponent = function(findNodeHandle, findHostInstance) { return; } + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; var viewConfig = maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; @@ -18606,7 +18981,7 @@ var ReactNativeComponent = function(findNodeHandle, findHostInstance) { // view invalidation for certain components (eg RCTTextInput) on iOS. if (updatePayload != null) { UIManager.updateView( - maybeInstance._nativeTag, + nativeTag, viewConfig.uiViewClassName, updatePayload ); @@ -18734,6 +19109,36 @@ var getInspectorDataForViewTag = void 0; }; } +// Module provided by RN: +function setNativeProps(handle, nativeProps) { + if (handle._nativeTag == null) { + !(handle._nativeTag != null) + ? warningWithoutStack$1( + false, + "setNativeProps was called with a ref that isn't a " + + "native component. Use React.forwardRef to get access to the underlying native component" + ) + : void 0; + return; + } + + { + warnForStyleProps(nativeProps, handle.viewConfig.validAttributes); + } + + var updatePayload = create(nativeProps, handle.viewConfig.validAttributes); + // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. + if (updatePayload != null) { + UIManager.updateView( + handle._nativeTag, + handle.viewConfig.uiViewClassName, + updatePayload + ); + } +} + var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function findNodeHandle(componentOrHandle) { @@ -18801,6 +19206,8 @@ var ReactFabric = { findNodeHandle: findNodeHandle, + setNativeProps: setNativeProps, + render: function(element, containerTag, callback) { var root = roots.get(containerTag); diff --git a/Libraries/Renderer/oss/ReactFabric-prod.js b/Libraries/Renderer/oss/ReactFabric-prod.js index 6a2913b0b56..f77404ffb91 100644 --- a/Libraries/Renderer/oss/ReactFabric-prod.js +++ b/Libraries/Renderer/oss/ReactFabric-prod.js @@ -3188,6 +3188,8 @@ function updateReducer(reducer) { is(newState, hook.memoizedState) || (didReceiveUpdate = !0); hook.memoizedState = newState; hook.baseUpdate === queue.last && (hook.baseState = newState); + queue.eagerReducer = reducer; + queue.eagerState = newState; return [newState, _dispatch]; } } @@ -3508,6 +3510,8 @@ function tryHydrate(fiber, nextInstance) { (nextInstance = shim$1(nextInstance, fiber.pendingProps)), null !== nextInstance ? ((fiber.stateNode = nextInstance), !0) : !1 ); + case 13: + return !1; default: return !1; } @@ -4571,19 +4575,19 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { null !== dependency && dependency.expirationTime < renderExpirationTime && (dependency.expirationTime = renderExpirationTime); + dependency = renderExpirationTime; for (var node = oldValue.return; null !== node; ) { - dependency = node.alternate; - if (node.childExpirationTime < renderExpirationTime) - (node.childExpirationTime = renderExpirationTime), - null !== dependency && - dependency.childExpirationTime < - renderExpirationTime && - (dependency.childExpirationTime = renderExpirationTime); + var alternate = node.alternate; + if (node.childExpirationTime < dependency) + (node.childExpirationTime = dependency), + null !== alternate && + alternate.childExpirationTime < dependency && + (alternate.childExpirationTime = dependency); else if ( - null !== dependency && - dependency.childExpirationTime < renderExpirationTime + null !== alternate && + alternate.childExpirationTime < dependency ) - dependency.childExpirationTime = renderExpirationTime; + alternate.childExpirationTime = dependency; else break; node = node.return; } @@ -4713,12 +4717,11 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { renderExpirationTime ) ); - default: - invariant( - !1, - "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." - ); } + invariant( + !1, + "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." + ); } var valueCursor = { current: null }, currentlyRenderingFiber = null, @@ -5361,6 +5364,8 @@ function unwindWork(workInProgress) { workInProgress) : null ); + case 18: + return null; case 4: return popHostContainer(workInProgress), null; case 10: @@ -5686,6 +5691,7 @@ function commitPassiveEffects(root, firstEffect) { isRendering = previousIsRendering; previousIsRendering = root.expirationTime; 0 !== previousIsRendering && requestWork(root, previousIsRendering); + isBatchingUpdates || isRendering || performWork(1073741823, !1); } function flushPassiveEffects() { if (null !== passiveEffectCallbackHandle) { @@ -5960,6 +5966,8 @@ function completeUnitOfWork(workInProgress) { case 17: isContextProvider(current$$1.type) && popContext(current$$1); break; + case 18: + break; default: invariant( !1, @@ -6050,7 +6058,7 @@ function renderRoot(root$jscomp$0, isYieldy) { do { try { if (isYieldy) - for (; null !== nextUnitOfWork && !shouldYieldToRenderer(); ) + for (; null !== nextUnitOfWork && !(frameDeadline <= now$1()); ) nextUnitOfWork = performUnitOfWork(nextUnitOfWork); else for (; null !== nextUnitOfWork; ) @@ -6136,27 +6144,24 @@ function renderRoot(root$jscomp$0, isYieldy) { sourceFiber$jscomp$0.expirationTime = 1073741823; break a; } - sourceFiber$jscomp$0 = root.pingCache; - null === sourceFiber$jscomp$0 - ? ((sourceFiber$jscomp$0 = root.pingCache = new PossiblyWeakMap()), - (returnFiber$jscomp$0 = new Set()), - sourceFiber$jscomp$0.set(thenable, returnFiber$jscomp$0)) - : ((returnFiber$jscomp$0 = sourceFiber$jscomp$0.get( - thenable - )), - void 0 === returnFiber$jscomp$0 && - ((returnFiber$jscomp$0 = new Set()), - sourceFiber$jscomp$0.set( - thenable, - returnFiber$jscomp$0 - ))); - returnFiber$jscomp$0.has(returnFiber) || - (returnFiber$jscomp$0.add(returnFiber), + sourceFiber$jscomp$0 = root; + returnFiber$jscomp$0 = returnFiber; + var pingCache = sourceFiber$jscomp$0.pingCache; + null === pingCache + ? ((pingCache = sourceFiber$jscomp$0.pingCache = new PossiblyWeakMap()), + (current$$1 = new Set()), + pingCache.set(thenable, current$$1)) + : ((current$$1 = pingCache.get(thenable)), + void 0 === current$$1 && + ((current$$1 = new Set()), + pingCache.set(thenable, current$$1))); + current$$1.has(returnFiber$jscomp$0) || + (current$$1.add(returnFiber$jscomp$0), (sourceFiber$jscomp$0 = pingSuspendedRoot.bind( null, - root, + sourceFiber$jscomp$0, thenable, - returnFiber + returnFiber$jscomp$0 )), thenable.then(sourceFiber$jscomp$0, sourceFiber$jscomp$0)); -1 === earliestTimeoutMs @@ -6200,24 +6205,25 @@ function renderRoot(root$jscomp$0, isYieldy) { break a; case 1: if ( - ((thenable = value), - (earliestTimeoutMs = root.type), - (startTimeMs = root.stateNode), + ((earliestTimeoutMs = value), + (startTimeMs = root.type), + (sourceFiber$jscomp$0 = root.stateNode), 0 === (root.effectTag & 64) && ("function" === - typeof earliestTimeoutMs.getDerivedStateFromError || - (null !== startTimeMs && - "function" === typeof startTimeMs.componentDidCatch && + typeof startTimeMs.getDerivedStateFromError || + (null !== sourceFiber$jscomp$0 && + "function" === + typeof sourceFiber$jscomp$0.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has( - startTimeMs + sourceFiber$jscomp$0 ))))) ) { root.effectTag |= 2048; root.expirationTime = returnFiber; returnFiber = createClassErrorUpdate( root, - thenable, + earliestTimeoutMs, returnFiber ); enqueueCapturedUpdate(root, returnFiber); @@ -6477,7 +6483,7 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - 0 !== msUntilTimeout || shouldYieldToRenderer() + 0 !== msUntilTimeout || frameDeadline <= now$1() ? 0 < msUntilTimeout && (root.timeoutHandle = scheduleTimeout( onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), @@ -6577,27 +6583,19 @@ function findHighestPriorityRoot() { nextFlushedRoot = highestPriorityRoot; nextFlushedExpirationTime = highestPriorityWork; } -var didYield = !1; -function shouldYieldToRenderer() { - return didYield ? !0 : frameDeadline <= now$1() ? (didYield = !0) : !1; -} -function performAsyncWork() { - try { - if (!shouldYieldToRenderer() && null !== firstScheduledRoot) { - recomputeCurrentRendererTime(); - var root = firstScheduledRoot; - do { - var expirationTime = root.expirationTime; - 0 !== expirationTime && - currentRendererTime <= expirationTime && - (root.nextExpirationTimeToWorkOn = currentRendererTime); - root = root.nextScheduledRoot; - } while (root !== firstScheduledRoot); - } - performWork(0, !0); - } finally { - didYield = !1; +function performAsyncWork(didTimeout) { + if (didTimeout && null !== firstScheduledRoot) { + recomputeCurrentRendererTime(); + didTimeout = firstScheduledRoot; + do { + var expirationTime = didTimeout.expirationTime; + 0 !== expirationTime && + currentRendererTime <= expirationTime && + (didTimeout.nextExpirationTimeToWorkOn = currentRendererTime); + didTimeout = didTimeout.nextScheduledRoot; + } while (didTimeout !== firstScheduledRoot); } + performWork(0, !0); } function performWork(minExpirationTime, isYieldy) { findHighestPriorityRoot(); @@ -6608,7 +6606,10 @@ function performWork(minExpirationTime, isYieldy) { null !== nextFlushedRoot && 0 !== nextFlushedExpirationTime && minExpirationTime <= nextFlushedExpirationTime && - !(didYield && currentRendererTime > nextFlushedExpirationTime); + !( + frameDeadline <= now$1() && + currentRendererTime > nextFlushedExpirationTime + ); ) performWorkOnRoot( @@ -6676,7 +6677,7 @@ function performWorkOnRoot(root, expirationTime, isYieldy) { renderRoot(root, isYieldy), (_finishedWork = root.finishedWork), null !== _finishedWork && - (shouldYieldToRenderer() + (frameDeadline <= now$1() ? (root.finishedWork = _finishedWork) : completeRoot$1(root, _finishedWork, expirationTime))); } else @@ -6917,18 +6918,20 @@ var roots = new Map(), maybeInstance = findHostInstance(this); } catch (error) {} if (null != maybeInstance) { - var viewConfig = + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + maybeInstance = maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; nativeProps = diffProperties( null, emptyObject, nativeProps, - viewConfig.validAttributes + maybeInstance.validAttributes ); null != nativeProps && UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, + nativeTag, + maybeInstance.uiViewClassName, nativeProps ); } @@ -6937,6 +6940,21 @@ var roots = new Map(), })(React.Component); })(findNodeHandle, findHostInstance), findNodeHandle: findNodeHandle, + setNativeProps: function(handle, nativeProps) { + null != handle._nativeTag && + ((nativeProps = diffProperties( + null, + emptyObject, + nativeProps, + handle.viewConfig.validAttributes + )), + null != nativeProps && + UIManager.updateView( + handle._nativeTag, + handle.viewConfig.uiViewClassName, + nativeProps + )); + }, render: function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { @@ -7022,17 +7040,20 @@ var roots = new Map(), maybeInstance = findHostInstance(this); } catch (error) {} if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig; + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + maybeInstance = + maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; nativeProps = diffProperties( null, emptyObject, nativeProps, - viewConfig.validAttributes + maybeInstance.validAttributes ); null != nativeProps && UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, + nativeTag, + maybeInstance.uiViewClassName, nativeProps ); } @@ -7068,7 +7089,7 @@ var roots = new Map(), findFiberByHostInstance: getInstanceFromInstance, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.8.1", + version: "16.8.3", 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 4e42e56b1bb..ab75b165f51 100644 --- a/Libraries/Renderer/oss/ReactFabric-profiling.js +++ b/Libraries/Renderer/oss/ReactFabric-profiling.js @@ -3208,6 +3208,8 @@ function updateReducer(reducer) { is(newState, hook.memoizedState) || (didReceiveUpdate = !0); hook.memoizedState = newState; hook.baseUpdate === queue.last && (hook.baseState = newState); + queue.eagerReducer = reducer; + queue.eagerState = newState; return [newState, _dispatch]; } } @@ -3538,6 +3540,8 @@ function tryHydrate(fiber, nextInstance) { (nextInstance = shim$1(nextInstance, fiber.pendingProps)), null !== nextInstance ? ((fiber.stateNode = nextInstance), !0) : !1 ); + case 13: + return !1; default: return !1; } @@ -4644,19 +4648,19 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { null !== dependency && dependency.expirationTime < renderExpirationTime && (dependency.expirationTime = renderExpirationTime); + dependency = renderExpirationTime; for (var node = oldValue.return; null !== node; ) { - dependency = node.alternate; - if (node.childExpirationTime < renderExpirationTime) - (node.childExpirationTime = renderExpirationTime), - null !== dependency && - dependency.childExpirationTime < - renderExpirationTime && - (dependency.childExpirationTime = renderExpirationTime); + var alternate = node.alternate; + if (node.childExpirationTime < dependency) + (node.childExpirationTime = dependency), + null !== alternate && + alternate.childExpirationTime < dependency && + (alternate.childExpirationTime = dependency); else if ( - null !== dependency && - dependency.childExpirationTime < renderExpirationTime + null !== alternate && + alternate.childExpirationTime < dependency ) - dependency.childExpirationTime = renderExpirationTime; + alternate.childExpirationTime = dependency; else break; node = node.return; } @@ -4786,12 +4790,11 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { renderExpirationTime ) ); - default: - invariant( - !1, - "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." - ); } + invariant( + !1, + "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." + ); } var valueCursor = { current: null }, currentlyRenderingFiber = null, @@ -5465,22 +5468,23 @@ function throwException( sourceFiber.expirationTime = 1073741823; return; } - sourceFiber = root.pingCache; - null === sourceFiber - ? ((sourceFiber = root.pingCache = new PossiblyWeakMap()), - (returnFiber = new Set()), - sourceFiber.set(thenable, returnFiber)) - : ((returnFiber = sourceFiber.get(thenable)), - void 0 === returnFiber && - ((returnFiber = new Set()), - sourceFiber.set(thenable, returnFiber))); - returnFiber.has(renderExpirationTime) || - (returnFiber.add(renderExpirationTime), + sourceFiber = root; + returnFiber = renderExpirationTime; + var pingCache = sourceFiber.pingCache; + null === pingCache + ? ((pingCache = sourceFiber.pingCache = new PossiblyWeakMap()), + (current$$1 = new Set()), + pingCache.set(thenable, current$$1)) + : ((current$$1 = pingCache.get(thenable)), + void 0 === current$$1 && + ((current$$1 = new Set()), pingCache.set(thenable, current$$1))); + current$$1.has(returnFiber) || + (current$$1.add(returnFiber), (sourceFiber = pingSuspendedRoot.bind( null, - root, + sourceFiber, thenable, - renderExpirationTime + returnFiber )), (sourceFiber = tracing.unstable_wrap(sourceFiber)), thenable.then(sourceFiber, sourceFiber)); @@ -5528,21 +5532,21 @@ function throwException( return; case 1: if ( - ((thenable = value), - (earliestTimeoutMs = root.type), - (startTimeMs = root.stateNode), + ((earliestTimeoutMs = value), + (startTimeMs = root.type), + (sourceFiber = root.stateNode), 0 === (root.effectTag & 64) && - ("function" === typeof earliestTimeoutMs.getDerivedStateFromError || - (null !== startTimeMs && - "function" === typeof startTimeMs.componentDidCatch && + ("function" === typeof startTimeMs.getDerivedStateFromError || + (null !== sourceFiber && + "function" === typeof sourceFiber.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(startTimeMs))))) + !legacyErrorBoundariesThatAlreadyFailed.has(sourceFiber))))) ) { root.effectTag |= 2048; root.expirationTime = renderExpirationTime; renderExpirationTime = createClassErrorUpdate( root, - thenable, + earliestTimeoutMs, renderExpirationTime ); enqueueCapturedUpdate(root, renderExpirationTime); @@ -5583,6 +5587,8 @@ function unwindWork(workInProgress) { workInProgress) : null ); + case 18: + return null; case 4: return popHostContainer(workInProgress), null; case 10: @@ -5927,6 +5933,7 @@ function commitPassiveEffects(root, firstEffect) { isRendering = previousIsRendering; previousIsRendering = root.expirationTime; 0 !== previousIsRendering && requestWork(root, previousIsRendering); + isBatchingUpdates || isRendering || performWork(1073741823, !1); } function flushPassiveEffects() { if (null !== passiveEffectCallbackHandle) { @@ -6241,6 +6248,8 @@ function completeUnitOfWork(workInProgress) { case 17: isContextProvider(current$$1.type) && popContext(current$$1); break; + case 18: + break; default: invariant( !1, @@ -6387,7 +6396,7 @@ function renderRoot(root, isYieldy) { do { try { if (isYieldy) - for (; null !== nextUnitOfWork && !shouldYieldToRenderer(); ) + for (; null !== nextUnitOfWork && !(frameDeadline <= now$1()); ) nextUnitOfWork = performUnitOfWork(nextUnitOfWork); else for (; null !== nextUnitOfWork; ) @@ -6680,7 +6689,7 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - 0 !== msUntilTimeout || shouldYieldToRenderer() + 0 !== msUntilTimeout || frameDeadline <= now$1() ? 0 < msUntilTimeout && (root.timeoutHandle = scheduleTimeout( onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), @@ -6780,27 +6789,19 @@ function findHighestPriorityRoot() { nextFlushedRoot = highestPriorityRoot; nextFlushedExpirationTime = highestPriorityWork; } -var didYield = !1; -function shouldYieldToRenderer() { - return didYield ? !0 : frameDeadline <= now$1() ? (didYield = !0) : !1; -} -function performAsyncWork() { - try { - if (!shouldYieldToRenderer() && null !== firstScheduledRoot) { - recomputeCurrentRendererTime(); - var root = firstScheduledRoot; - do { - var expirationTime = root.expirationTime; - 0 !== expirationTime && - currentRendererTime <= expirationTime && - (root.nextExpirationTimeToWorkOn = currentRendererTime); - root = root.nextScheduledRoot; - } while (root !== firstScheduledRoot); - } - performWork(0, !0); - } finally { - didYield = !1; +function performAsyncWork(didTimeout) { + if (didTimeout && null !== firstScheduledRoot) { + recomputeCurrentRendererTime(); + didTimeout = firstScheduledRoot; + do { + var expirationTime = didTimeout.expirationTime; + 0 !== expirationTime && + currentRendererTime <= expirationTime && + (didTimeout.nextExpirationTimeToWorkOn = currentRendererTime); + didTimeout = didTimeout.nextScheduledRoot; + } while (didTimeout !== firstScheduledRoot); } + performWork(0, !0); } function performWork(minExpirationTime, isYieldy) { findHighestPriorityRoot(); @@ -6811,7 +6812,10 @@ function performWork(minExpirationTime, isYieldy) { null !== nextFlushedRoot && 0 !== nextFlushedExpirationTime && minExpirationTime <= nextFlushedExpirationTime && - !(didYield && currentRendererTime > nextFlushedExpirationTime); + !( + frameDeadline <= now$1() && + currentRendererTime > nextFlushedExpirationTime + ); ) performWorkOnRoot( @@ -6879,7 +6883,7 @@ function performWorkOnRoot(root, expirationTime, isYieldy) { renderRoot(root, isYieldy), (_finishedWork = root.finishedWork), null !== _finishedWork && - (shouldYieldToRenderer() + (frameDeadline <= now$1() ? (root.finishedWork = _finishedWork) : completeRoot$1(root, _finishedWork, expirationTime))); } else @@ -7120,18 +7124,20 @@ var roots = new Map(), maybeInstance = findHostInstance(this); } catch (error) {} if (null != maybeInstance) { - var viewConfig = + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + maybeInstance = maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; nativeProps = diffProperties( null, emptyObject, nativeProps, - viewConfig.validAttributes + maybeInstance.validAttributes ); null != nativeProps && UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, + nativeTag, + maybeInstance.uiViewClassName, nativeProps ); } @@ -7140,6 +7146,21 @@ var roots = new Map(), })(React.Component); })(findNodeHandle, findHostInstance), findNodeHandle: findNodeHandle, + setNativeProps: function(handle, nativeProps) { + null != handle._nativeTag && + ((nativeProps = diffProperties( + null, + emptyObject, + nativeProps, + handle.viewConfig.validAttributes + )), + null != nativeProps && + UIManager.updateView( + handle._nativeTag, + handle.viewConfig.uiViewClassName, + nativeProps + )); + }, render: function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { @@ -7230,17 +7251,20 @@ var roots = new Map(), maybeInstance = findHostInstance(this); } catch (error) {} if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig; + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + maybeInstance = + maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; nativeProps = diffProperties( null, emptyObject, nativeProps, - viewConfig.validAttributes + maybeInstance.validAttributes ); null != nativeProps && UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, + nativeTag, + maybeInstance.uiViewClassName, nativeProps ); } @@ -7276,7 +7300,7 @@ var roots = new Map(), findFiberByHostInstance: getInstanceFromInstance, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.8.1", + version: "16.8.3", 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 5dad5a29b88..8afedd6a192 100644 --- a/Libraries/Renderer/oss/ReactNativeRenderer-dev.js +++ b/Libraries/Renderer/oss/ReactNativeRenderer-dev.js @@ -1090,6 +1090,7 @@ var MemoComponent = 14; var SimpleMemoComponent = 15; var LazyComponent = 16; var IncompleteClassComponent = 17; +var DehydratedSuspenseComponent = 18; function getParent(inst) { do { @@ -3724,6 +3725,19 @@ function warnForStyleProps(props, validAttributes) { } } +var debugRenderPhaseSideEffects = false; +var debugRenderPhaseSideEffectsForStrictMode = false; +var enableUserTimingAPI = true; +var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; +var warnAboutDeprecatedLifecycles = false; +var enableProfilerTimer = true; +var enableSchedulerTracing = true; +var enableSuspenseServerRenderer = false; + +var warnAboutDeprecatedSetNativeProps = false; + +// Only used in www builds. + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); @@ -3789,6 +3803,15 @@ var ReactNativeFiberHostComponent = (function() { nativeProps ) { { + if (warnAboutDeprecatedSetNativeProps) { + warningWithoutStack$1( + false, + "Warning: Calling ref.setNativeProps(nativeProps) " + + "is deprecated and will be removed in a future release. " + + "Use the setNativeProps export from the react-native package instead." + + "\n\timport {setNativeProps} from 'react-native';\n\tsetNativeProps(ref, nativeProps);\n" + ); + } warnForStyleProps(nativeProps, this.viewConfig.validAttributes); } @@ -3892,21 +3915,31 @@ function shim$1() { } // Hydration (when unsupported) + var supportsHydration = false; var canHydrateInstance = shim$1; var canHydrateTextInstance = shim$1; +var canHydrateSuspenseInstance = shim$1; +var isSuspenseInstancePending = shim$1; +var isSuspenseInstanceFallback = shim$1; +var registerSuspenseInstanceRetry = shim$1; var getNextHydratableSibling = shim$1; var getFirstHydratableChild = shim$1; var hydrateInstance = shim$1; var hydrateTextInstance = shim$1; +var getNextHydratableInstanceAfterSuspenseInstance = shim$1; +var clearSuspenseBoundary = shim$1; +var clearSuspenseBoundaryFromContainer = shim$1; var didNotMatchHydratedContainerTextInstance = shim$1; var didNotMatchHydratedTextInstance = shim$1; var didNotHydrateContainerInstance = shim$1; var didNotHydrateInstance = shim$1; var didNotFindHydratableContainerInstance = shim$1; var didNotFindHydratableContainerTextInstance = shim$1; +var didNotFindHydratableContainerSuspenseInstance = shim$1; var didNotFindHydratableInstance = shim$1; var didNotFindHydratableTextInstance = shim$1; +var didNotFindHydratableSuspenseInstance = shim$1; // Modules provided by RN: // Unused @@ -4412,16 +4445,6 @@ function setCurrentPhase(lifeCyclePhase) { } } -var debugRenderPhaseSideEffects = false; -var debugRenderPhaseSideEffectsForStrictMode = false; -var enableUserTimingAPI = true; -var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; -var warnAboutDeprecatedLifecycles = false; -var enableProfilerTimer = true; -var enableSchedulerTracing = true; - -// Only used in www builds. - // Prefix measurements so that it's possible to filter them. // Longer prefixes are hard to read in DevTools. var reactEmoji = "\u269B"; @@ -4693,7 +4716,8 @@ function stopFailedWorkTimer(fiber) { } fiber._debugIsCurrentlyTiming = false; var warning = - fiber.tag === SuspenseComponent + fiber.tag === SuspenseComponent || + fiber.tag === DehydratedSuspenseComponent ? "Rendering was suspended" : "An error was thrown inside this error boundary"; endFiberMark(fiber, null, warning); @@ -9568,17 +9592,6 @@ function mountWorkInProgressHook() { { hook._debugType = currentHookNameInDev; - if ( - currentlyRenderingFiber$1 !== null && - currentlyRenderingFiber$1.alternate !== null - ) { - warning$1( - false, - "%s: Rendered more hooks than during the previous render. This is " + - "not currently supported and may lead to unexpected behavior.", - getComponentName(currentlyRenderingFiber$1.type) - ); - } } if (workInProgressHook === null) { // This is the first hook in the list @@ -9722,7 +9735,6 @@ function updateReducer(reducer, initialArg, init) { } hook.memoizedState = newState; - // Don't persist the state accumlated from the render phase updates to // the base state unless the queue is empty. // TODO: Not sure if this is the desired semantics, but it's what we @@ -9731,6 +9743,9 @@ function updateReducer(reducer, initialArg, init) { hook.baseState = newState; } + queue.eagerReducer = reducer; + queue.eagerState = newState; + return [newState, _dispatch]; } } @@ -10593,6 +10608,18 @@ function enterHydrationState(fiber) { return true; } +function reenterHydrationStateFromDehydratedSuspenseInstance(fiber) { + if (!supportsHydration) { + return false; + } + + var suspenseInstance = fiber.stateNode; + nextHydratableInstance = getNextHydratableSibling(suspenseInstance); + popToNextHostParent(fiber); + isHydrating = true; + return true; +} + function deleteHydratableInstance(returnFiber, instance) { { switch (returnFiber.tag) { @@ -10647,6 +10674,9 @@ function insertNonHydratedInstance(returnFiber, fiber) { var text = fiber.pendingProps; didNotFindHydratableContainerTextInstance(parentContainer, text); break; + case SuspenseComponent: + didNotFindHydratableContainerSuspenseInstance(parentContainer); + break; } break; } @@ -10675,6 +10705,13 @@ function insertNonHydratedInstance(returnFiber, fiber) { _text ); break; + case SuspenseComponent: + didNotFindHydratableSuspenseInstance( + parentType, + parentProps, + parentInstance + ); + break; } break; } @@ -10705,6 +10742,18 @@ function tryHydrate(fiber, nextInstance) { } return false; } + case SuspenseComponent: { + if (enableSuspenseServerRenderer) { + var suspenseInstance = canHydrateSuspenseInstance(nextInstance); + if (suspenseInstance !== null) { + // Downgrade the tag to a dehydrated component until we've hydrated it. + fiber.tag = DehydratedSuspenseComponent; + fiber.stateNode = suspenseInstance; + return true; + } + } + return false; + } default: return false; } @@ -10825,12 +10874,32 @@ function prepareToHydrateHostTextInstance(fiber) { return shouldUpdate; } +function skipPastDehydratedSuspenseInstance(fiber) { + if (!supportsHydration) { + invariant( + false, + "Expected skipPastDehydratedSuspenseInstance() to never be called. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + } + var suspenseInstance = fiber.stateNode; + invariant( + suspenseInstance, + "Expected to have a hydrated suspense instance. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + nextHydratableInstance = getNextHydratableInstanceAfterSuspenseInstance( + suspenseInstance + ); +} + function popToNextHostParent(fiber) { var parent = fiber.return; while ( parent !== null && parent.tag !== HostComponent && - parent.tag !== HostRoot + parent.tag !== HostRoot && + parent.tag !== DehydratedSuspenseComponent ) { parent = parent.return; } @@ -10982,6 +11051,10 @@ function updateForwardRef( nextProps, renderExpirationTime ) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens after the first render suspends. + // We'll need to figure out if this is fine or can cause issues. + { if (workInProgress.type !== workInProgress.elementType) { // Lazy component props can't be validated in createElement @@ -11171,6 +11244,10 @@ function updateSimpleMemoComponent( updateExpirationTime, renderExpirationTime ) { + // TODO: current can be non-null here even if the component + // hasn't yet mounted. This happens when the inner render suspends. + // We'll need to figure out if this is fine or can cause issues. + { if (workInProgress.type !== workInProgress.elementType) { // Lazy component props can't be validated in createElement @@ -12124,6 +12201,22 @@ function updateSuspenseComponent( // children -- we skip over the primary children entirely. var next = void 0; if (current$$1 === null) { + if (enableSuspenseServerRenderer) { + // If we're currently hydrating, try to hydrate this boundary. + // But only if this has a fallback. + if (nextProps.fallback !== undefined) { + tryToClaimNextHydratableInstance(workInProgress); + // This could've changed the tag if this was a dehydrated suspense component. + if (workInProgress.tag === DehydratedSuspenseComponent) { + return updateDehydratedSuspenseComponent( + null, + workInProgress, + renderExpirationTime + ); + } + } + } + // This is the initial mount. This branch is pretty simple because there's // no previous state that needs to be preserved. if (nextDidTimeout) { @@ -12326,6 +12419,107 @@ function updateSuspenseComponent( return next; } +function updateDehydratedSuspenseComponent( + current$$1, + workInProgress, + renderExpirationTime +) { + if (current$$1 === null) { + // During the first pass, we'll bail out and not drill into the children. + // Instead, we'll leave the content in place and try to hydrate it later. + workInProgress.expirationTime = Never; + return null; + } + if ((workInProgress.effectTag & DidCapture) !== NoEffect) { + // Something suspended. Leave the existing children in place. + // TODO: In non-concurrent mode, should we commit the nodes we have hydrated so far? + workInProgress.child = null; + return null; + } + // We use childExpirationTime to indicate that a child might depend on context, so if + // any context has changed, we need to treat is as if the input might have changed. + var hasContextChanged$$1 = + current$$1.childExpirationTime >= renderExpirationTime; + var suspenseInstance = current$$1.stateNode; + if ( + didReceiveUpdate || + hasContextChanged$$1 || + isSuspenseInstanceFallback(suspenseInstance) + ) { + // This boundary has changed since the first render. This means that we are now unable to + // hydrate it. We might still be able to hydrate it using an earlier expiration time but + // during this render we can't. Instead, we're going to delete the whole subtree and + // instead inject a new real Suspense boundary to take its place, which may render content + // or fallback. The real Suspense boundary will suspend for a while so we have some time + // to ensure it can produce real content, but all state and pending events will be lost. + + // Alternatively, this boundary is in a permanent fallback state. In this case, we'll never + // get an update and we'll never be able to hydrate the final content. Let's just try the + // client side render instead. + + // Detach from the current dehydrated boundary. + current$$1.alternate = null; + workInProgress.alternate = null; + + // Insert a deletion in the effect list. + var returnFiber = workInProgress.return; + invariant( + returnFiber !== null, + "Suspense boundaries are never on the root. " + + "This is probably a bug in React." + ); + var last = returnFiber.lastEffect; + if (last !== null) { + last.nextEffect = current$$1; + returnFiber.lastEffect = current$$1; + } else { + returnFiber.firstEffect = returnFiber.lastEffect = current$$1; + } + current$$1.nextEffect = null; + current$$1.effectTag = Deletion; + + // Upgrade this work in progress to a real Suspense component. + workInProgress.tag = SuspenseComponent; + workInProgress.stateNode = null; + workInProgress.memoizedState = null; + // This is now an insertion. + workInProgress.effectTag |= Placement; + // Retry as a real Suspense component. + return updateSuspenseComponent(null, workInProgress, renderExpirationTime); + } else if (isSuspenseInstancePending(suspenseInstance)) { + // This component is still pending more data from the server, so we can't hydrate its + // content. We treat it as if this component suspended itself. It might seem as if + // we could just try to render it client-side instead. However, this will perform a + // lot of unnecessary work and is unlikely to complete since it often will suspend + // on missing data anyway. Additionally, the server might be able to render more + // than we can on the client yet. In that case we'd end up with more fallback states + // on the client than if we just leave it alone. If the server times out or errors + // these should update this boundary to the permanent Fallback state instead. + // Mark it as having captured (i.e. suspended). + workInProgress.effectTag |= DidCapture; + // Leave the children in place. I.e. empty. + workInProgress.child = null; + // Register a callback to retry this boundary once the server has sent the result. + registerSuspenseInstanceRetry( + suspenseInstance, + retryTimedOutBoundary.bind(null, current$$1) + ); + return null; + } else { + // This is the first attempt. + reenterHydrationStateFromDehydratedSuspenseInstance(workInProgress); + var nextProps = workInProgress.pendingProps; + var nextChildren = nextProps.children; + workInProgress.child = mountChildFibers( + workInProgress, + null, + nextChildren, + renderExpirationTime + ); + return workInProgress.child; + } +} + function updatePortalComponent( current$$1, workInProgress, @@ -12612,6 +12806,15 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { } break; } + case DehydratedSuspenseComponent: { + if (enableSuspenseServerRenderer) { + // We know that this component will suspend again because if it has + // been unsuspended it has committed as a regular Suspense component. + // If it needs to be retried, it should have work scheduled on it. + workInProgress.effectTag |= DidCapture; + break; + } + } } return bailoutOnAlreadyFinishedWork( current$$1, @@ -12785,13 +12988,22 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { renderExpirationTime ); } - default: - invariant( - false, - "Unknown unit of work tag. This error is likely caused by a bug in " + - "React. Please file an issue." - ); + case DehydratedSuspenseComponent: { + if (enableSuspenseServerRenderer) { + return updateDehydratedSuspenseComponent( + current$$1, + workInProgress, + renderExpirationTime + ); + } + break; + } } + invariant( + false, + "Unknown unit of work tag. This error is likely caused by a bug in " + + "React. Please file an issue." + ); } var valueCursor = createCursor(null); @@ -12910,6 +13122,34 @@ function calculateChangedBits(context, newValue, oldValue) { } } +function scheduleWorkOnParentPath(parent, renderExpirationTime) { + // Update the child expiration time of all the ancestors, including + // the alternates. + var node = parent; + while (node !== null) { + var alternate = node.alternate; + if (node.childExpirationTime < renderExpirationTime) { + node.childExpirationTime = renderExpirationTime; + if ( + alternate !== null && + alternate.childExpirationTime < renderExpirationTime + ) { + alternate.childExpirationTime = renderExpirationTime; + } + } else if ( + alternate !== null && + alternate.childExpirationTime < renderExpirationTime + ) { + alternate.childExpirationTime = renderExpirationTime; + } else { + // Neither alternate was updated, which means the rest of the + // ancestor path already has sufficient priority. + break; + } + node = node.return; + } +} + function propagateContextChange( workInProgress, context, @@ -12959,31 +13199,8 @@ function propagateContextChange( ) { alternate.expirationTime = renderExpirationTime; } - // Update the child expiration time of all the ancestors, including - // the alternates. - var node = fiber.return; - while (node !== null) { - alternate = node.alternate; - if (node.childExpirationTime < renderExpirationTime) { - node.childExpirationTime = renderExpirationTime; - if ( - alternate !== null && - alternate.childExpirationTime < renderExpirationTime - ) { - alternate.childExpirationTime = renderExpirationTime; - } - } else if ( - alternate !== null && - alternate.childExpirationTime < renderExpirationTime - ) { - alternate.childExpirationTime = renderExpirationTime; - } else { - // Neither alternate was updated, which means the rest of the - // ancestor path already has sufficient priority. - break; - } - node = node.return; - } + + scheduleWorkOnParentPath(fiber.return, renderExpirationTime); // Mark the expiration time on the list, too. if (list.expirationTime < renderExpirationTime) { @@ -12999,6 +13216,29 @@ function propagateContextChange( } else if (fiber.tag === ContextProvider) { // Don't scan deeper if this is a matching provider nextFiber = fiber.type === workInProgress.type ? null : fiber.child; + } else if ( + enableSuspenseServerRenderer && + fiber.tag === DehydratedSuspenseComponent + ) { + // If a dehydrated suspense component is in this subtree, we don't know + // if it will have any context consumers in it. The best we can do is + // mark it as having updates on its children. + if (fiber.expirationTime < renderExpirationTime) { + fiber.expirationTime = renderExpirationTime; + } + var _alternate = fiber.alternate; + if ( + _alternate !== null && + _alternate.expirationTime < renderExpirationTime + ) { + _alternate.expirationTime = renderExpirationTime; + } + // This is intentionally passing this fiber as the parent + // because we want to schedule this fiber as having work + // on its children. We'll use the childExpirationTime on + // this fiber to indicate that a context has changed. + scheduleWorkOnParentPath(fiber, renderExpirationTime); + nextFiber = fiber.sibling; } else { // Traverse down. nextFiber = fiber.child; @@ -14275,7 +14515,12 @@ function completeWork(current, workInProgress, renderExpirationTime) { var nextDidTimeout = nextState !== null; var prevDidTimeout = current !== null && current.memoizedState !== null; - if (current !== null && !nextDidTimeout && prevDidTimeout) { + if (current === null) { + // In cases where we didn't find a suitable hydration boundary we never + // downgraded this to a DehydratedSuspenseComponent, but we still need to + // pop the hydration state since we might be inside the insertion tree. + popHydrationState(workInProgress); + } else if (!nextDidTimeout && prevDidTimeout) { // We just switched from the fallback to the normal children. Delete // the fallback. // TODO: Would it be better to store the fallback fragment on @@ -14329,6 +14574,29 @@ function completeWork(current, workInProgress, renderExpirationTime) { } break; } + case DehydratedSuspenseComponent: { + if (enableSuspenseServerRenderer) { + if (current === null) { + var _wasHydrated2 = popHydrationState(workInProgress); + invariant( + _wasHydrated2, + "A dehydrated suspense component was completed without a hydrated node. " + + "This is probably a bug in React." + ); + skipPastDehydratedSuspenseInstance(workInProgress); + } else if ((workInProgress.effectTag & DidCapture) === NoEffect) { + // This boundary did not suspend so it's now hydrated. + // To handle any future suspense cases, we're going to now upgrade it + // to a Suspense component. We detach it from the existing current fiber. + current.alternate = null; + workInProgress.alternate = null; + workInProgress.tag = SuspenseComponent; + workInProgress.memoizedState = null; + workInProgress.stateNode = null; + } + } + break; + } default: invariant( false, @@ -14472,7 +14740,7 @@ var didWarnAboutUndefinedSnapshotBeforeUpdate = null; didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); } -var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; +var PossiblyWeakSet$1 = typeof WeakSet === "function" ? WeakSet : Set; function logError(boundary, errorInfo) { var source = errorInfo.source; @@ -15230,7 +15498,11 @@ function getHostSibling(fiber) { } node.sibling.return = node.return; node = node.sibling; - while (node.tag !== HostComponent && node.tag !== HostText) { + while ( + node.tag !== HostComponent && + node.tag !== HostText && + node.tag !== DehydratedSuspenseComponent + ) { // If it is not host node and, we might have a host node inside it. // Try to search down until we find one. if (node.effectTag & Placement) { @@ -15383,6 +15655,16 @@ function unmountHostComponents(current$$1) { removeChild(currentParent, node.stateNode); } // Don't visit children because we already visited them. + } else if ( + enableSuspenseServerRenderer && + node.tag === DehydratedSuspenseComponent + ) { + // Delete the dehydrated suspense boundary and all of its content. + if (currentParentIsContainer) { + clearSuspenseBoundaryFromContainer(currentParent, node.stateNode); + } else { + clearSuspenseBoundary(currentParent, node.stateNode); + } } else if (node.tag === HostPortal) { if (node.child !== null) { // When we go into a portal, it becomes the parent to remove from. @@ -15543,11 +15825,11 @@ function commitWork(current$$1, finishedWork) { finishedWork.updateQueue = null; var retryCache = finishedWork.stateNode; if (retryCache === null) { - retryCache = finishedWork.stateNode = new PossiblyWeakSet(); + retryCache = finishedWork.stateNode = new PossiblyWeakSet$1(); } thenables.forEach(function(thenable) { // Memoize using the boundary fiber to prevent redundant listeners. - var retry = retryTimedOutBoundary.bind(null, finishedWork, thenable); + var retry = resolveRetryThenable.bind(null, finishedWork, thenable); if (enableSchedulerTracing) { retry = tracing.unstable_wrap(retry); } @@ -15580,6 +15862,7 @@ function commitResetTextContent(current$$1) { resetTextContent(current$$1.stateNode); } +var PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; var PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; function createRootErrorUpdate(fiber, errorInfo, expirationTime) { @@ -15645,6 +15928,39 @@ function createClassErrorUpdate(fiber, errorInfo, expirationTime) { return update; } +function attachPingListener(root, renderExpirationTime, thenable) { + // Attach a listener to the promise to "ping" the root and retry. But + // only if one does not already exist for the current render expiration + // time (which acts like a "thread ID" here). + var pingCache = root.pingCache; + var threadIDs = void 0; + if (pingCache === null) { + pingCache = root.pingCache = new PossiblyWeakMap(); + threadIDs = new Set(); + pingCache.set(thenable, threadIDs); + } else { + threadIDs = pingCache.get(thenable); + if (threadIDs === undefined) { + threadIDs = new Set(); + pingCache.set(thenable, threadIDs); + } + } + if (!threadIDs.has(renderExpirationTime)) { + // Memoize using the thread ID to prevent redundant listeners. + threadIDs.add(renderExpirationTime); + var ping = pingSuspendedRoot.bind( + null, + root, + thenable, + renderExpirationTime + ); + if (enableSchedulerTracing) { + ping = tracing.unstable_wrap(ping); + } + thenable.then(ping, ping); + } +} + function throwException( root, returnFiber, @@ -15699,6 +16015,9 @@ function throwException( } } } + // If there is a DehydratedSuspenseComponent we don't have to do anything because + // if something suspends inside it, we will simply leave that as dehydrated. It + // will never timeout. _workInProgress = _workInProgress.return; } while (_workInProgress !== null); @@ -15765,36 +16084,7 @@ function throwException( // Confirmed that the boundary is in a concurrent mode tree. Continue // with the normal suspend path. - // Attach a listener to the promise to "ping" the root and retry. But - // only if one does not already exist for the current render expiration - // time (which acts like a "thread ID" here). - var pingCache = root.pingCache; - var threadIDs = void 0; - if (pingCache === null) { - pingCache = root.pingCache = new PossiblyWeakMap(); - threadIDs = new Set(); - pingCache.set(thenable, threadIDs); - } else { - threadIDs = pingCache.get(thenable); - if (threadIDs === undefined) { - threadIDs = new Set(); - pingCache.set(thenable, threadIDs); - } - } - if (!threadIDs.has(renderExpirationTime)) { - // Memoize using the thread ID to prevent redundant listeners. - threadIDs.add(renderExpirationTime); - var ping = pingSuspendedRoot.bind( - null, - root, - thenable, - renderExpirationTime - ); - if (enableSchedulerTracing) { - ping = tracing.unstable_wrap(ping); - } - thenable.then(ping, ping); - } + attachPingListener(root, renderExpirationTime, thenable); var absoluteTimeoutMs = void 0; if (earliestTimeoutMs === -1) { @@ -15831,6 +16121,40 @@ function throwException( // whole tree. renderDidSuspend(root, absoluteTimeoutMs, renderExpirationTime); + _workInProgress.effectTag |= ShouldCapture; + _workInProgress.expirationTime = renderExpirationTime; + return; + } else if ( + enableSuspenseServerRenderer && + _workInProgress.tag === DehydratedSuspenseComponent + ) { + attachPingListener(root, renderExpirationTime, thenable); + + // Since we already have a current fiber, we can eagerly add a retry listener. + var retryCache = _workInProgress.memoizedState; + if (retryCache === null) { + retryCache = _workInProgress.memoizedState = new PossiblyWeakSet(); + var _current = _workInProgress.alternate; + invariant( + _current, + "A dehydrated suspense boundary must commit before trying to render. " + + "This is probably a bug in React." + ); + _current.memoizedState = retryCache; + } + // Memoize using the boundary fiber to prevent redundant listeners. + if (!retryCache.has(thenable)) { + retryCache.add(thenable); + var retry = resolveRetryThenable.bind( + null, + _workInProgress, + thenable + ); + if (enableSchedulerTracing) { + retry = tracing.unstable_wrap(retry); + } + thenable.then(retry, retry); + } _workInProgress.effectTag |= ShouldCapture; _workInProgress.expirationTime = renderExpirationTime; return; @@ -15929,6 +16253,7 @@ function unwindWork(workInProgress, renderExpirationTime) { return workInProgress; } case HostComponent: { + // TODO: popHydrationState popHostContext(workInProgress); return null; } @@ -15941,6 +16266,19 @@ function unwindWork(workInProgress, renderExpirationTime) { } return null; } + case DehydratedSuspenseComponent: { + if (enableSuspenseServerRenderer) { + // TODO: popHydrationState + var _effectTag3 = workInProgress.effectTag; + if (_effectTag3 & ShouldCapture) { + workInProgress.effectTag = + (_effectTag3 & ~ShouldCapture) | DidCapture; + // Captured a suspense effect. Re-render the boundary. + return workInProgress; + } + } + return null; + } case HostPortal: popHostContainer(workInProgress); return null; @@ -16360,6 +16698,10 @@ function commitPassiveEffects(root, firstEffect) { if (rootExpirationTime !== NoWork) { requestWork(root, rootExpirationTime); } + // Flush any sync work that was scheduled by effects + if (!isBatchingUpdates && !isRendering) { + performSyncWork(); + } } function isAlreadyFailedLegacyErrorBoundary(instance) { @@ -16975,7 +17317,7 @@ function workLoop(isYieldy) { } } else { // Flush asynchronous work until there's a higher priority event - while (nextUnitOfWork !== null && !shouldYieldToRenderer()) { + while (nextUnitOfWork !== null && !shouldYield$$1()) { nextUnitOfWork = performUnitOfWork(nextUnitOfWork); } } @@ -17434,17 +17776,7 @@ function pingSuspendedRoot(root, thenable, pingTime) { } } -function retryTimedOutBoundary(boundaryFiber, thenable) { - // The boundary fiber (a Suspense component) previously timed out and was - // rendered in its fallback state. One of the promises that suspended it has - // resolved, which means at least part of the tree was likely unblocked. Try - var retryCache = boundaryFiber.stateNode; - if (retryCache !== null) { - // The thenable resolved, so we no longer need to memoize, because it will - // never be thrown again. - retryCache.delete(thenable); - } - +function retryTimedOutBoundary(boundaryFiber) { var currentTime = requestCurrentTime(); var retryTime = computeExpirationForFiber(currentTime, boundaryFiber); var root = scheduleWorkToRoot(boundaryFiber, retryTime); @@ -17457,6 +17789,38 @@ function retryTimedOutBoundary(boundaryFiber, thenable) { } } +function resolveRetryThenable(boundaryFiber, thenable) { + // The boundary fiber (a Suspense component) previously timed out and was + // rendered in its fallback state. One of the promises that suspended it has + // resolved, which means at least part of the tree was likely unblocked. Try + var retryCache = void 0; + if (enableSuspenseServerRenderer) { + switch (boundaryFiber.tag) { + case SuspenseComponent: + retryCache = boundaryFiber.stateNode; + break; + case DehydratedSuspenseComponent: + retryCache = boundaryFiber.memoizedState; + break; + default: + invariant( + false, + "Pinged unknown suspense boundary type. " + + "This is probably a bug in React." + ); + } + } else { + retryCache = boundaryFiber.stateNode; + } + if (retryCache !== null) { + // The thenable resolved, so we no longer need to memoize, because it will + // never be thrown again. + retryCache.delete(thenable); + } + + retryTimedOutBoundary(boundaryFiber); +} + function scheduleWorkToRoot(fiber, expirationTime) { recordScheduleUpdate(); @@ -17555,8 +17919,10 @@ function warnIfNotCurrentlyBatchingInDev(fiber) { "});\n" + "/* assert on the output */\n\n" + "This ensures that you're testing the behavior the user would see in the browser." + - " Learn more at https://fb.me/react-wrap-tests-with-act", - getComponentName(fiber.type) + " Learn more at https://fb.me/react-wrap-tests-with-act" + + "%s", + getComponentName(fiber.type), + getStackByFiberInDevAndProd(fiber) ); } } @@ -17698,7 +18064,7 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - if (msUntilTimeout === 0 && !shouldYieldToRenderer()) { + if (msUntilTimeout === 0 && !shouldYield$$1()) { // Don't wait an additional tick. Commit the tree immediately. root.pendingCommitExpirationTime = suspendedExpirationTime; root.finishedWork = finishedWork; @@ -17895,43 +18261,24 @@ function findHighestPriorityRoot() { nextFlushedExpirationTime = highestPriorityWork; } -// TODO: This wrapper exists because many of the older tests (the ones that use -// flushDeferredPri) rely on the number of times `shouldYield` is called. We -// should get rid of it. -var didYield = false; -function shouldYieldToRenderer() { - if (didYield) { - return true; - } - if (shouldYield$$1()) { - didYield = true; - return true; - } - return false; -} - -function performAsyncWork() { - try { - if (!shouldYieldToRenderer()) { - // The callback timed out. That means at least one update has expired. - // Iterate through the root schedule. If they contain expired work, set - // the next render expiration time to the current time. This has the effect - // of flushing all expired work in a single batch, instead of flushing each - // level one at a time. - if (firstScheduledRoot !== null) { - recomputeCurrentRendererTime(); - var root = firstScheduledRoot; - do { - didExpireAtExpirationTime(root, currentRendererTime); - // The root schedule is circular, so this is never null. - root = root.nextScheduledRoot; - } while (root !== firstScheduledRoot); - } +function performAsyncWork(didTimeout) { + if (didTimeout) { + // The callback timed out. That means at least one update has expired. + // Iterate through the root schedule. If they contain expired work, set + // the next render expiration time to the current time. This has the effect + // of flushing all expired work in a single batch, instead of flushing each + // level one at a time. + if (firstScheduledRoot !== null) { + recomputeCurrentRendererTime(); + var root = firstScheduledRoot; + do { + didExpireAtExpirationTime(root, currentRendererTime); + // The root schedule is circular, so this is never null. + root = root.nextScheduledRoot; + } while (root !== firstScheduledRoot); } - performWork(NoWork, true); - } finally { - didYield = false; } + performWork(NoWork, true); } function performSyncWork() { @@ -17957,7 +18304,7 @@ function performWork(minExpirationTime, isYieldy) { nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && minExpirationTime <= nextFlushedExpirationTime && - !(didYield && currentRendererTime > nextFlushedExpirationTime) + !(shouldYield$$1() && currentRendererTime > nextFlushedExpirationTime) ) { performWorkOnRoot( nextFlushedRoot, @@ -18101,7 +18448,7 @@ function performWorkOnRoot(root, expirationTime, isYieldy) { if (_finishedWork !== null) { // We've completed the root. Check the if we should yield one more time // before committing. - if (!shouldYieldToRenderer()) { + if (!shouldYield$$1()) { // Still time left. Commit the root. completeRoot(root, _finishedWork, expirationTime); } else { @@ -18516,7 +18863,7 @@ function createPortal( // TODO: this is special because it gets imported during build. -var ReactVersion = "16.8.1"; +var ReactVersion = "16.8.3"; // Modules provided by RN: var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { @@ -18610,6 +18957,17 @@ var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { * Manipulation](docs/direct-manipulation.html)). */ setNativeProps: function(nativeProps) { + { + if (warnAboutDeprecatedSetNativeProps) { + warningWithoutStack$1( + false, + "Warning: Calling ref.setNativeProps(nativeProps) " + + "is deprecated and will be removed in a future release. " + + "Use the setNativeProps export from the react-native package instead." + + "\n\timport {setNativeProps} from 'react-native';\n\tsetNativeProps(ref, nativeProps);\n" + ); + } + } // Class components don't have viewConfig -> validateAttributes. // Nor does it make sense to set native props on a non-native component. // Instead, find the nearest host component and set props on it. @@ -18631,7 +18989,10 @@ var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { return; } - var viewConfig = maybeInstance.viewConfig; + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + var viewConfig = + maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; { warnForStyleProps(nativeProps, viewConfig.validAttributes); @@ -18644,7 +19005,7 @@ var NativeMethodsMixin = function(findNodeHandle, findHostInstance) { // view invalidation for certain components (eg RCTTextInput) on iOS. if (updatePayload != null) { UIManager.updateView( - maybeInstance._nativeTag, + nativeTag, viewConfig.uiViewClassName, updatePayload ); @@ -18865,6 +19226,18 @@ var ReactNativeComponent = function(findNodeHandle, findHostInstance) { ReactNativeComponent.prototype.setNativeProps = function setNativeProps( nativeProps ) { + { + if (warnAboutDeprecatedSetNativeProps) { + warningWithoutStack$1( + false, + "Warning: Calling ref.setNativeProps(nativeProps) " + + "is deprecated and will be removed in a future release. " + + "Use the setNativeProps export from the react-native package instead." + + "\n\timport {setNativeProps} from 'react-native';\n\tsetNativeProps(ref, nativeProps);\n" + ); + } + } + // Class components don't have viewConfig -> validateAttributes. // Nor does it make sense to set native props on a non-native component. // Instead, find the nearest host component and set props on it. @@ -18886,6 +19259,8 @@ var ReactNativeComponent = function(findNodeHandle, findHostInstance) { return; } + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; var viewConfig = maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; @@ -18896,7 +19271,7 @@ var ReactNativeComponent = function(findNodeHandle, findHostInstance) { // view invalidation for certain components (eg RCTTextInput) on iOS. if (updatePayload != null) { UIManager.updateView( - maybeInstance._nativeTag, + nativeTag, viewConfig.uiViewClassName, updatePayload ); @@ -19018,6 +19393,36 @@ var getInspectorDataForViewTag = void 0; }; } +// Module provided by RN: +function setNativeProps(handle, nativeProps) { + if (handle._nativeTag == null) { + !(handle._nativeTag != null) + ? warningWithoutStack$1( + false, + "setNativeProps was called with a ref that isn't a " + + "native component. Use React.forwardRef to get access to the underlying native component" + ) + : void 0; + return; + } + + { + warnForStyleProps(nativeProps, handle.viewConfig.validAttributes); + } + + var updatePayload = create(nativeProps, handle.viewConfig.validAttributes); + // Avoid the overhead of bridge calls if there's no update. + // This is an expensive no-op for Android, and causes an unnecessary + // view invalidation for certain components (eg RCTTextInput) on iOS. + if (updatePayload != null) { + UIManager.updateView( + handle._nativeTag, + handle.viewConfig.uiViewClassName, + updatePayload + ); + } +} + // TODO: direct imports like some-package/src/* are bad. Fix me. // Module provided by RN: var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; @@ -19093,6 +19498,8 @@ var ReactNativeRenderer = { findNodeHandle: findNodeHandle, + setNativeProps: setNativeProps, + render: function(element, containerTag, callback) { var root = roots.get(containerTag); diff --git a/Libraries/Renderer/oss/ReactNativeRenderer-prod.js b/Libraries/Renderer/oss/ReactNativeRenderer-prod.js index a9a20a350ad..ef16155a086 100644 --- a/Libraries/Renderer/oss/ReactNativeRenderer-prod.js +++ b/Libraries/Renderer/oss/ReactNativeRenderer-prod.js @@ -3224,6 +3224,8 @@ function updateReducer(reducer) { is(newState, hook.memoizedState) || (didReceiveUpdate = !0); hook.memoizedState = newState; hook.baseUpdate === queue.last && (hook.baseState = newState); + queue.eagerReducer = reducer; + queue.eagerState = newState; return [newState, _dispatch]; } } @@ -3544,6 +3546,8 @@ function tryHydrate(fiber, nextInstance) { (nextInstance = shim$1(nextInstance, fiber.pendingProps)), null !== nextInstance ? ((fiber.stateNode = nextInstance), !0) : !1 ); + case 13: + return !1; default: return !1; } @@ -4607,19 +4611,19 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { null !== dependency && dependency.expirationTime < renderExpirationTime && (dependency.expirationTime = renderExpirationTime); + dependency = renderExpirationTime; for (var node = oldValue.return; null !== node; ) { - dependency = node.alternate; - if (node.childExpirationTime < renderExpirationTime) - (node.childExpirationTime = renderExpirationTime), - null !== dependency && - dependency.childExpirationTime < - renderExpirationTime && - (dependency.childExpirationTime = renderExpirationTime); + var alternate = node.alternate; + if (node.childExpirationTime < dependency) + (node.childExpirationTime = dependency), + null !== alternate && + alternate.childExpirationTime < dependency && + (alternate.childExpirationTime = dependency); else if ( - null !== dependency && - dependency.childExpirationTime < renderExpirationTime + null !== alternate && + alternate.childExpirationTime < dependency ) - dependency.childExpirationTime = renderExpirationTime; + alternate.childExpirationTime = dependency; else break; node = node.return; } @@ -4749,12 +4753,11 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { renderExpirationTime ) ); - default: - invariant( - !1, - "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." - ); } + invariant( + !1, + "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." + ); } var valueCursor = { current: null }, currentlyRenderingFiber = null, @@ -5091,7 +5094,7 @@ function logCapturedError(capturedError) { : Error("Unspecified error at:" + componentStack); ExceptionsManager.handleException(error, !1); } -var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; +var PossiblyWeakSet$1 = "function" === typeof WeakSet ? WeakSet : Set; function logError(boundary, errorInfo) { var source = errorInfo.source, stack = errorInfo.stack; @@ -5304,7 +5307,7 @@ function commitPlacement(finishedWork) { parentFiber.sibling.return = parentFiber.return; for ( parentFiber = parentFiber.sibling; - 5 !== parentFiber.tag && 6 !== parentFiber.tag; + 5 !== parentFiber.tag && 6 !== parentFiber.tag && 18 !== parentFiber.tag; ) { if (parentFiber.effectTag & 2) continue b; @@ -5548,9 +5551,9 @@ function commitWork(current$$1, finishedWork) { finishedWork.updateQueue = null; var retryCache = finishedWork.stateNode; null === retryCache && - (retryCache = finishedWork.stateNode = new PossiblyWeakSet()); + (retryCache = finishedWork.stateNode = new PossiblyWeakSet$1()); instance.forEach(function(thenable) { - var retry = retryTimedOutBoundary.bind(null, finishedWork, thenable); + var retry = resolveRetryThenable.bind(null, finishedWork, thenable); retryCache.has(thenable) || (retryCache.add(thenable), thenable.then(retry, retry)); }); @@ -5635,6 +5638,8 @@ function unwindWork(workInProgress) { workInProgress) : null ); + case 18: + return null; case 4: return popHostContainer(workInProgress), null; case 10: @@ -5890,6 +5895,7 @@ function commitPassiveEffects(root, firstEffect) { isRendering = previousIsRendering; previousIsRendering = root.expirationTime; 0 !== previousIsRendering && requestWork(root, previousIsRendering); + isBatchingUpdates || isRendering || performWork(1073741823, !1); } function flushPassiveEffects() { if (null !== passiveEffectCallbackHandle) { @@ -6167,6 +6173,8 @@ function completeUnitOfWork(workInProgress) { case 17: isContextProvider(current$$1.type) && popContext(current$$1); break; + case 18: + break; default: invariant( !1, @@ -6260,7 +6268,7 @@ function renderRoot(root$jscomp$0, isYieldy) { do { try { if (isYieldy) - for (; null !== nextUnitOfWork && !shouldYieldToRenderer(); ) + for (; null !== nextUnitOfWork && !(frameDeadline <= now$1()); ) nextUnitOfWork = performUnitOfWork(nextUnitOfWork); else for (; null !== nextUnitOfWork; ) @@ -6346,27 +6354,24 @@ function renderRoot(root$jscomp$0, isYieldy) { sourceFiber$jscomp$0.expirationTime = 1073741823; break a; } - sourceFiber$jscomp$0 = root.pingCache; - null === sourceFiber$jscomp$0 - ? ((sourceFiber$jscomp$0 = root.pingCache = new PossiblyWeakMap()), - (returnFiber$jscomp$0 = new Set()), - sourceFiber$jscomp$0.set(thenable, returnFiber$jscomp$0)) - : ((returnFiber$jscomp$0 = sourceFiber$jscomp$0.get( - thenable - )), - void 0 === returnFiber$jscomp$0 && - ((returnFiber$jscomp$0 = new Set()), - sourceFiber$jscomp$0.set( - thenable, - returnFiber$jscomp$0 - ))); - returnFiber$jscomp$0.has(returnFiber) || - (returnFiber$jscomp$0.add(returnFiber), + sourceFiber$jscomp$0 = root; + returnFiber$jscomp$0 = returnFiber; + var pingCache = sourceFiber$jscomp$0.pingCache; + null === pingCache + ? ((pingCache = sourceFiber$jscomp$0.pingCache = new PossiblyWeakMap()), + (current$$1 = new Set()), + pingCache.set(thenable, current$$1)) + : ((current$$1 = pingCache.get(thenable)), + void 0 === current$$1 && + ((current$$1 = new Set()), + pingCache.set(thenable, current$$1))); + current$$1.has(returnFiber$jscomp$0) || + (current$$1.add(returnFiber$jscomp$0), (sourceFiber$jscomp$0 = pingSuspendedRoot.bind( null, - root, + sourceFiber$jscomp$0, thenable, - returnFiber + returnFiber$jscomp$0 )), thenable.then(sourceFiber$jscomp$0, sourceFiber$jscomp$0)); -1 === earliestTimeoutMs @@ -6410,24 +6415,25 @@ function renderRoot(root$jscomp$0, isYieldy) { break a; case 1: if ( - ((thenable = value), - (earliestTimeoutMs = root.type), - (startTimeMs = root.stateNode), + ((earliestTimeoutMs = value), + (startTimeMs = root.type), + (sourceFiber$jscomp$0 = root.stateNode), 0 === (root.effectTag & 64) && ("function" === - typeof earliestTimeoutMs.getDerivedStateFromError || - (null !== startTimeMs && - "function" === typeof startTimeMs.componentDidCatch && + typeof startTimeMs.getDerivedStateFromError || + (null !== sourceFiber$jscomp$0 && + "function" === + typeof sourceFiber$jscomp$0.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || !legacyErrorBoundariesThatAlreadyFailed.has( - startTimeMs + sourceFiber$jscomp$0 ))))) ) { root.effectTag |= 2048; root.expirationTime = returnFiber; returnFiber = createClassErrorUpdate( root, - thenable, + earliestTimeoutMs, returnFiber ); enqueueCapturedUpdate(root, returnFiber); @@ -6604,7 +6610,7 @@ function pingSuspendedRoot(root, thenable, pingTime) { 0 !== pingTime && requestWork(root, pingTime); } } -function retryTimedOutBoundary(boundaryFiber, thenable) { +function resolveRetryThenable(boundaryFiber, thenable) { var retryCache = boundaryFiber.stateNode; null !== retryCache && retryCache.delete(thenable); thenable = requestCurrentTime(); @@ -6701,7 +6707,7 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - 0 !== msUntilTimeout || shouldYieldToRenderer() + 0 !== msUntilTimeout || frameDeadline <= now$1() ? 0 < msUntilTimeout && (root.timeoutHandle = scheduleTimeout( onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), @@ -6801,27 +6807,19 @@ function findHighestPriorityRoot() { nextFlushedRoot = highestPriorityRoot; nextFlushedExpirationTime = highestPriorityWork; } -var didYield = !1; -function shouldYieldToRenderer() { - return didYield ? !0 : frameDeadline <= now$1() ? (didYield = !0) : !1; -} -function performAsyncWork() { - try { - if (!shouldYieldToRenderer() && null !== firstScheduledRoot) { - recomputeCurrentRendererTime(); - var root = firstScheduledRoot; - do { - var expirationTime = root.expirationTime; - 0 !== expirationTime && - currentRendererTime <= expirationTime && - (root.nextExpirationTimeToWorkOn = currentRendererTime); - root = root.nextScheduledRoot; - } while (root !== firstScheduledRoot); - } - performWork(0, !0); - } finally { - didYield = !1; +function performAsyncWork(didTimeout) { + if (didTimeout && null !== firstScheduledRoot) { + recomputeCurrentRendererTime(); + didTimeout = firstScheduledRoot; + do { + var expirationTime = didTimeout.expirationTime; + 0 !== expirationTime && + currentRendererTime <= expirationTime && + (didTimeout.nextExpirationTimeToWorkOn = currentRendererTime); + didTimeout = didTimeout.nextScheduledRoot; + } while (didTimeout !== firstScheduledRoot); } + performWork(0, !0); } function performWork(minExpirationTime, isYieldy) { findHighestPriorityRoot(); @@ -6832,7 +6830,10 @@ function performWork(minExpirationTime, isYieldy) { null !== nextFlushedRoot && 0 !== nextFlushedExpirationTime && minExpirationTime <= nextFlushedExpirationTime && - !(didYield && currentRendererTime > nextFlushedExpirationTime); + !( + frameDeadline <= now$1() && + currentRendererTime > nextFlushedExpirationTime + ); ) performWorkOnRoot( @@ -6900,7 +6901,7 @@ function performWorkOnRoot(root, expirationTime, isYieldy) { renderRoot(root, isYieldy), (_finishedWork = root.finishedWork), null !== _finishedWork && - (shouldYieldToRenderer() + (frameDeadline <= now$1() ? (root.finishedWork = _finishedWork) : completeRoot(root, _finishedWork, expirationTime))); } else @@ -7141,18 +7142,20 @@ var roots = new Map(), maybeInstance = findHostInstance(this); } catch (error) {} if (null != maybeInstance) { - var viewConfig = + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + maybeInstance = maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; nativeProps = diffProperties( null, emptyObject, nativeProps, - viewConfig.validAttributes + maybeInstance.validAttributes ); null != nativeProps && UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, + nativeTag, + maybeInstance.uiViewClassName, nativeProps ); } @@ -7161,6 +7164,21 @@ var roots = new Map(), })(React.Component); })(findNodeHandle, findHostInstance), findNodeHandle: findNodeHandle, + setNativeProps: function(handle, nativeProps) { + null != handle._nativeTag && + ((nativeProps = diffProperties( + null, + emptyObject, + nativeProps, + handle.viewConfig.validAttributes + )), + null != nativeProps && + UIManager.updateView( + handle._nativeTag, + handle.viewConfig.uiViewClassName, + nativeProps + )); + }, render: function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { @@ -7251,17 +7269,20 @@ var roots = new Map(), maybeInstance = findHostInstance(this); } catch (error) {} if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig; + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + maybeInstance = + maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; nativeProps = diffProperties( null, emptyObject, nativeProps, - viewConfig.validAttributes + maybeInstance.validAttributes ); null != nativeProps && UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, + nativeTag, + maybeInstance.uiViewClassName, nativeProps ); } @@ -7302,7 +7323,7 @@ var roots = new Map(), findFiberByHostInstance: getInstanceFromTag, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.8.1", + version: "16.8.3", 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 b0636f84225..3490e98d5f3 100644 --- a/Libraries/Renderer/oss/ReactNativeRenderer-profiling.js +++ b/Libraries/Renderer/oss/ReactNativeRenderer-profiling.js @@ -3244,6 +3244,8 @@ function updateReducer(reducer) { is(newState, hook.memoizedState) || (didReceiveUpdate = !0); hook.memoizedState = newState; hook.baseUpdate === queue.last && (hook.baseState = newState); + queue.eagerReducer = reducer; + queue.eagerState = newState; return [newState, _dispatch]; } } @@ -3574,6 +3576,8 @@ function tryHydrate(fiber, nextInstance) { (nextInstance = shim$1(nextInstance, fiber.pendingProps)), null !== nextInstance ? ((fiber.stateNode = nextInstance), !0) : !1 ); + case 13: + return !1; default: return !1; } @@ -4680,19 +4684,19 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { null !== dependency && dependency.expirationTime < renderExpirationTime && (dependency.expirationTime = renderExpirationTime); + dependency = renderExpirationTime; for (var node = oldValue.return; null !== node; ) { - dependency = node.alternate; - if (node.childExpirationTime < renderExpirationTime) - (node.childExpirationTime = renderExpirationTime), - null !== dependency && - dependency.childExpirationTime < - renderExpirationTime && - (dependency.childExpirationTime = renderExpirationTime); + var alternate = node.alternate; + if (node.childExpirationTime < dependency) + (node.childExpirationTime = dependency), + null !== alternate && + alternate.childExpirationTime < dependency && + (alternate.childExpirationTime = dependency); else if ( - null !== dependency && - dependency.childExpirationTime < renderExpirationTime + null !== alternate && + alternate.childExpirationTime < dependency ) - dependency.childExpirationTime = renderExpirationTime; + alternate.childExpirationTime = dependency; else break; node = node.return; } @@ -4822,12 +4826,11 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) { renderExpirationTime ) ); - default: - invariant( - !1, - "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." - ); } + invariant( + !1, + "Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue." + ); } var valueCursor = { current: null }, currentlyRenderingFiber = null, @@ -5164,7 +5167,7 @@ function logCapturedError(capturedError) { : Error("Unspecified error at:" + componentStack); ExceptionsManager.handleException(error, !1); } -var PossiblyWeakSet = "function" === typeof WeakSet ? WeakSet : Set; +var PossiblyWeakSet$1 = "function" === typeof WeakSet ? WeakSet : Set; function logError(boundary, errorInfo) { var source = errorInfo.source, stack = errorInfo.stack; @@ -5377,7 +5380,7 @@ function commitPlacement(finishedWork) { parentFiber.sibling.return = parentFiber.return; for ( parentFiber = parentFiber.sibling; - 5 !== parentFiber.tag && 6 !== parentFiber.tag; + 5 !== parentFiber.tag && 6 !== parentFiber.tag && 18 !== parentFiber.tag; ) { if (parentFiber.effectTag & 2) continue b; @@ -5621,9 +5624,9 @@ function commitWork(current$$1, finishedWork) { finishedWork.updateQueue = null; var retryCache = finishedWork.stateNode; null === retryCache && - (retryCache = finishedWork.stateNode = new PossiblyWeakSet()); + (retryCache = finishedWork.stateNode = new PossiblyWeakSet$1()); instance.forEach(function(thenable) { - var retry = retryTimedOutBoundary.bind(null, finishedWork, thenable); + var retry = resolveRetryThenable.bind(null, finishedWork, thenable); retry = tracing.unstable_wrap(retry); retryCache.has(thenable) || (retryCache.add(thenable), thenable.then(retry, retry)); @@ -5740,22 +5743,23 @@ function throwException( sourceFiber.expirationTime = 1073741823; return; } - sourceFiber = root.pingCache; - null === sourceFiber - ? ((sourceFiber = root.pingCache = new PossiblyWeakMap()), - (returnFiber = new Set()), - sourceFiber.set(thenable, returnFiber)) - : ((returnFiber = sourceFiber.get(thenable)), - void 0 === returnFiber && - ((returnFiber = new Set()), - sourceFiber.set(thenable, returnFiber))); - returnFiber.has(renderExpirationTime) || - (returnFiber.add(renderExpirationTime), + sourceFiber = root; + returnFiber = renderExpirationTime; + var pingCache = sourceFiber.pingCache; + null === pingCache + ? ((pingCache = sourceFiber.pingCache = new PossiblyWeakMap()), + (current$$1 = new Set()), + pingCache.set(thenable, current$$1)) + : ((current$$1 = pingCache.get(thenable)), + void 0 === current$$1 && + ((current$$1 = new Set()), pingCache.set(thenable, current$$1))); + current$$1.has(returnFiber) || + (current$$1.add(returnFiber), (sourceFiber = pingSuspendedRoot.bind( null, - root, + sourceFiber, thenable, - renderExpirationTime + returnFiber )), (sourceFiber = tracing.unstable_wrap(sourceFiber)), thenable.then(sourceFiber, sourceFiber)); @@ -5803,21 +5807,21 @@ function throwException( return; case 1: if ( - ((thenable = value), - (earliestTimeoutMs = root.type), - (startTimeMs = root.stateNode), + ((earliestTimeoutMs = value), + (startTimeMs = root.type), + (sourceFiber = root.stateNode), 0 === (root.effectTag & 64) && - ("function" === typeof earliestTimeoutMs.getDerivedStateFromError || - (null !== startTimeMs && - "function" === typeof startTimeMs.componentDidCatch && + ("function" === typeof startTimeMs.getDerivedStateFromError || + (null !== sourceFiber && + "function" === typeof sourceFiber.componentDidCatch && (null === legacyErrorBoundariesThatAlreadyFailed || - !legacyErrorBoundariesThatAlreadyFailed.has(startTimeMs))))) + !legacyErrorBoundariesThatAlreadyFailed.has(sourceFiber))))) ) { root.effectTag |= 2048; root.expirationTime = renderExpirationTime; renderExpirationTime = createClassErrorUpdate( root, - thenable, + earliestTimeoutMs, renderExpirationTime ); enqueueCapturedUpdate(root, renderExpirationTime); @@ -5858,6 +5862,8 @@ function unwindWork(workInProgress) { workInProgress) : null ); + case 18: + return null; case 4: return popHostContainer(workInProgress), null; case 10: @@ -6132,6 +6138,7 @@ function commitPassiveEffects(root, firstEffect) { isRendering = previousIsRendering; previousIsRendering = root.expirationTime; 0 !== previousIsRendering && requestWork(root, previousIsRendering); + isBatchingUpdates || isRendering || performWork(1073741823, !1); } function flushPassiveEffects() { if (null !== passiveEffectCallbackHandle) { @@ -6453,6 +6460,8 @@ function completeUnitOfWork(workInProgress) { case 17: isContextProvider(current$$1.type) && popContext(current$$1); break; + case 18: + break; default: invariant( !1, @@ -6607,7 +6616,7 @@ function renderRoot(root, isYieldy) { do { try { if (isYieldy) - for (; null !== nextUnitOfWork && !shouldYieldToRenderer(); ) + for (; null !== nextUnitOfWork && !(frameDeadline <= now$1()); ) nextUnitOfWork = performUnitOfWork(nextUnitOfWork); else for (; null !== nextUnitOfWork; ) @@ -6788,7 +6797,7 @@ function pingSuspendedRoot(root, thenable, pingTime) { 0 !== pingTime && requestWork(root, pingTime); } } -function retryTimedOutBoundary(boundaryFiber, thenable) { +function resolveRetryThenable(boundaryFiber, thenable) { var retryCache = boundaryFiber.stateNode; null !== retryCache && retryCache.delete(thenable); thenable = requestCurrentTime(); @@ -6911,7 +6920,7 @@ function onSuspend( msUntilTimeout ) { root.expirationTime = rootExpirationTime; - 0 !== msUntilTimeout || shouldYieldToRenderer() + 0 !== msUntilTimeout || frameDeadline <= now$1() ? 0 < msUntilTimeout && (root.timeoutHandle = scheduleTimeout( onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), @@ -7011,27 +7020,19 @@ function findHighestPriorityRoot() { nextFlushedRoot = highestPriorityRoot; nextFlushedExpirationTime = highestPriorityWork; } -var didYield = !1; -function shouldYieldToRenderer() { - return didYield ? !0 : frameDeadline <= now$1() ? (didYield = !0) : !1; -} -function performAsyncWork() { - try { - if (!shouldYieldToRenderer() && null !== firstScheduledRoot) { - recomputeCurrentRendererTime(); - var root = firstScheduledRoot; - do { - var expirationTime = root.expirationTime; - 0 !== expirationTime && - currentRendererTime <= expirationTime && - (root.nextExpirationTimeToWorkOn = currentRendererTime); - root = root.nextScheduledRoot; - } while (root !== firstScheduledRoot); - } - performWork(0, !0); - } finally { - didYield = !1; +function performAsyncWork(didTimeout) { + if (didTimeout && null !== firstScheduledRoot) { + recomputeCurrentRendererTime(); + didTimeout = firstScheduledRoot; + do { + var expirationTime = didTimeout.expirationTime; + 0 !== expirationTime && + currentRendererTime <= expirationTime && + (didTimeout.nextExpirationTimeToWorkOn = currentRendererTime); + didTimeout = didTimeout.nextScheduledRoot; + } while (didTimeout !== firstScheduledRoot); } + performWork(0, !0); } function performWork(minExpirationTime, isYieldy) { findHighestPriorityRoot(); @@ -7042,7 +7043,10 @@ function performWork(minExpirationTime, isYieldy) { null !== nextFlushedRoot && 0 !== nextFlushedExpirationTime && minExpirationTime <= nextFlushedExpirationTime && - !(didYield && currentRendererTime > nextFlushedExpirationTime); + !( + frameDeadline <= now$1() && + currentRendererTime > nextFlushedExpirationTime + ); ) performWorkOnRoot( @@ -7110,7 +7114,7 @@ function performWorkOnRoot(root, expirationTime, isYieldy) { renderRoot(root, isYieldy), (_finishedWork = root.finishedWork), null !== _finishedWork && - (shouldYieldToRenderer() + (frameDeadline <= now$1() ? (root.finishedWork = _finishedWork) : completeRoot(root, _finishedWork, expirationTime))); } else @@ -7351,18 +7355,20 @@ var roots = new Map(), maybeInstance = findHostInstance(this); } catch (error) {} if (null != maybeInstance) { - var viewConfig = + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + maybeInstance = maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; nativeProps = diffProperties( null, emptyObject, nativeProps, - viewConfig.validAttributes + maybeInstance.validAttributes ); null != nativeProps && UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, + nativeTag, + maybeInstance.uiViewClassName, nativeProps ); } @@ -7371,6 +7377,21 @@ var roots = new Map(), })(React.Component); })(findNodeHandle, findHostInstance), findNodeHandle: findNodeHandle, + setNativeProps: function(handle, nativeProps) { + null != handle._nativeTag && + ((nativeProps = diffProperties( + null, + emptyObject, + nativeProps, + handle.viewConfig.validAttributes + )), + null != nativeProps && + UIManager.updateView( + handle._nativeTag, + handle.viewConfig.uiViewClassName, + nativeProps + )); + }, render: function(element, containerTag, callback) { var root = roots.get(containerTag); if (!root) { @@ -7466,17 +7487,20 @@ var roots = new Map(), maybeInstance = findHostInstance(this); } catch (error) {} if (null != maybeInstance) { - var viewConfig = maybeInstance.viewConfig; + var nativeTag = + maybeInstance._nativeTag || maybeInstance.canonical._nativeTag; + maybeInstance = + maybeInstance.viewConfig || maybeInstance.canonical.viewConfig; nativeProps = diffProperties( null, emptyObject, nativeProps, - viewConfig.validAttributes + maybeInstance.validAttributes ); null != nativeProps && UIManager.updateView( - maybeInstance._nativeTag, - viewConfig.uiViewClassName, + nativeTag, + maybeInstance.uiViewClassName, nativeProps ); } @@ -7517,7 +7541,7 @@ var roots = new Map(), findFiberByHostInstance: getInstanceFromTag, getInspectorDataForViewTag: getInspectorDataForViewTag, bundleType: 0, - version: "16.8.1", + version: "16.8.3", rendererPackageName: "react-native-renderer" }); var ReactNativeRenderer$2 = { default: ReactNativeRenderer }, diff --git a/Libraries/Renderer/shims/ReactNativeTypes.js b/Libraries/Renderer/shims/ReactNativeTypes.js index f9058abc1e9..1e145ed5e1d 100644 --- a/Libraries/Renderer/shims/ReactNativeTypes.js +++ b/Libraries/Renderer/shims/ReactNativeTypes.js @@ -131,6 +131,7 @@ type SecretInternalsFabricType = { export type ReactNativeType = { NativeComponent: typeof ReactNativeComponent, findNodeHandle(componentOrHandle: any): ?number, + setNativeProps(handle: any, nativeProps: Object): void, render( element: React$Element, containerTag: any, @@ -146,6 +147,7 @@ export type ReactNativeType = { export type ReactFabricType = { NativeComponent: typeof ReactNativeComponent, findNodeHandle(componentOrHandle: any): ?number, + setNativeProps(handle: any, nativeProps: Object): void, render( element: React$Element, containerTag: any, diff --git a/package.json b/package.json index 9dc310ad39f..9c83e0c5588 100644 --- a/package.json +++ b/package.json @@ -155,7 +155,7 @@ "test-ios-e2e": "detox test -c ios.sim.release" }, "peerDependencies": { - "react": "16.8.1" + "react": "16.8.3" }, "dependencies": { "@babel/runtime": "^7.0.0", @@ -232,9 +232,9 @@ "jest-junit": "5.2.0", "jscodeshift": "^0.6.2", "prettier": "1.13.6", - "react": "16.8.1", + "react": "16.8.3", "react-native-dummy": "0.2.0", - "react-test-renderer": "16.8.1", + "react-test-renderer": "16.8.3", "shelljs": "^0.7.8" }, "detox": { @@ -256,4 +256,4 @@ } } } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 966cd577f79..03e7ea47596 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6065,10 +6065,10 @@ react-devtools-core@^3.6.0: shell-quote "^1.6.1" ws "^3.3.1" -react-is@^16.8.1: - version "16.8.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.1.tgz#a80141e246eb894824fb4f2901c0c50ef31d4cdb" - integrity sha512-ioMCzVDWvCvKD8eeT+iukyWrBGrA3DiFYkXfBsVYIRdaREZuBjENG+KjrikavCLasozqRWTwFUagU/O4vPpRMA== +react-is@^16.8.3: + version "16.8.3" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.3.tgz#4ad8b029c2a718fc0cfc746c8d4e1b7221e5387d" + integrity sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA== react-native-dummy@0.2.0: version "0.2.0" @@ -6083,15 +6083,15 @@ react-proxy@^1.1.7: lodash "^4.6.1" react-deep-force-update "^1.0.0" -react-test-renderer@16.8.1: - version "16.8.1" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.1.tgz#72845ad9269be526126e97853311982f781767be" - integrity sha512-Bd21TN3+YVl6GZwav6O0T6m5UwGfOj+2+xZH5VH93ToD6M5uclN/c+R1DGX49ueG413KZPUx7Kw3sOYz2aJgfg== +react-test-renderer@16.8.3: + version "16.8.3" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.3.tgz#230006af264cc46aeef94392e04747c21839e05e" + integrity sha512-rjJGYebduKNZH0k1bUivVrRLX04JfIQ0FKJLPK10TAb06XWhfi4gTobooF9K/DEFNW98iGac3OSxkfIJUN9Mdg== dependencies: object-assign "^4.1.1" prop-types "^15.6.2" - react-is "^16.8.1" - scheduler "^0.13.1" + react-is "^16.8.3" + scheduler "^0.13.3" react-transform-hmr@^1.0.4: version "1.0.4" @@ -6101,15 +6101,15 @@ react-transform-hmr@^1.0.4: global "^4.3.0" react-proxy "^1.1.7" -react@16.8.1: - version "16.8.1" - resolved "https://registry.yarnpkg.com/react/-/react-16.8.1.tgz#ae11831f6cb2a05d58603a976afc8a558e852c4a" - integrity sha512-wLw5CFGPdo7p/AgteFz7GblI2JPOos0+biSoxf1FPsGxWQZdN/pj6oToJs1crn61DL3Ln7mN86uZ4j74p31ELQ== +react@16.8.3: + version "16.8.3" + resolved "https://registry.yarnpkg.com/react/-/react-16.8.3.tgz#c6f988a2ce895375de216edcfaedd6b9a76451d9" + integrity sha512-3UoSIsEq8yTJuSu0luO1QQWYbgGEILm+eJl2QN/VLDi7hL+EN18M3q3oVZwmVzzBJ3DkM7RMdRwBmZZ+b4IzSA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.1" + scheduler "^0.13.3" read-pkg-up@^1.0.1: version "1.0.1" @@ -6502,10 +6502,10 @@ sax@~1.1.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240" integrity sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA= -scheduler@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.1.tgz#1a217df1bfaabaf4f1b92a9127d5d732d85a9591" - integrity sha512-VJKOkiKIN2/6NOoexuypwSrybx13MY7NSy9RNt8wPvZDMRT1CW6qlpF5jXRToXNHz3uWzbm2elNpZfXfGPqP9A== +scheduler@^0.13.3: + version "0.13.3" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.3.tgz#bed3c5850f62ea9c716a4d781f9daeb9b2a58896" + integrity sha512-UxN5QRYWtpR1egNWzJcVLk8jlegxAugswQc984lD3kU7NuobsO37/sRfbpTdBjtnD5TBNFA2Q2oLV5+UmPSmEQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1"