1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import type {
    
  11.   ReactProviderType,
    
  12.   ReactContext,
    
  13.   ReactNodeList,
    
  14. } from 'shared/ReactTypes';
    
  15. import type {LazyComponent as LazyComponentType} from 'react/src/ReactLazy';
    
  16. import type {Fiber, FiberRoot} from './ReactInternalTypes';
    
  17. import type {TypeOfMode} from './ReactTypeOfMode';
    
  18. import type {Lanes, Lane} from './ReactFiberLane';
    
  19. import type {
    
  20.   SuspenseState,
    
  21.   SuspenseListRenderState,
    
  22.   SuspenseListTailMode,
    
  23. } from './ReactFiberSuspenseComponent';
    
  24. import type {SuspenseContext} from './ReactFiberSuspenseContext';
    
  25. import type {
    
  26.   OffscreenProps,
    
  27.   OffscreenState,
    
  28.   OffscreenQueue,
    
  29.   OffscreenInstance,
    
  30. } from './ReactFiberActivityComponent';
    
  31. import {OffscreenDetached} from './ReactFiberActivityComponent';
    
  32. import type {
    
  33.   Cache,
    
  34.   CacheComponentState,
    
  35.   SpawnedCachePool,
    
  36. } from './ReactFiberCacheComponent';
    
  37. import type {UpdateQueue} from './ReactFiberClassUpdateQueue';
    
  38. import type {RootState} from './ReactFiberRoot';
    
  39. import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';
    
  40. import type {TransitionStatus} from './ReactFiberConfig';
    
  41. import type {Hook} from './ReactFiberHooks';
    
  42. 
    
  43. import checkPropTypes from 'shared/checkPropTypes';
    
  44. import {
    
  45.   markComponentRenderStarted,
    
  46.   markComponentRenderStopped,
    
  47.   setIsStrictModeForDevtools,
    
  48. } from './ReactFiberDevToolsHook';
    
  49. import {
    
  50.   IndeterminateComponent,
    
  51.   FunctionComponent,
    
  52.   ClassComponent,
    
  53.   HostRoot,
    
  54.   HostComponent,
    
  55.   HostHoistable,
    
  56.   HostSingleton,
    
  57.   HostText,
    
  58.   HostPortal,
    
  59.   ForwardRef,
    
  60.   Fragment,
    
  61.   Mode,
    
  62.   ContextProvider,
    
  63.   ContextConsumer,
    
  64.   Profiler,
    
  65.   SuspenseComponent,
    
  66.   SuspenseListComponent,
    
  67.   MemoComponent,
    
  68.   SimpleMemoComponent,
    
  69.   LazyComponent,
    
  70.   IncompleteClassComponent,
    
  71.   ScopeComponent,
    
  72.   OffscreenComponent,
    
  73.   LegacyHiddenComponent,
    
  74.   CacheComponent,
    
  75.   TracingMarkerComponent,
    
  76. } from './ReactWorkTags';
    
  77. import {
    
  78.   NoFlags,
    
  79.   PerformedWork,
    
  80.   Placement,
    
  81.   Hydrating,
    
  82.   ContentReset,
    
  83.   DidCapture,
    
  84.   Update,
    
  85.   Ref,
    
  86.   RefStatic,
    
  87.   ChildDeletion,
    
  88.   ForceUpdateForLegacySuspense,
    
  89.   StaticMask,
    
  90.   ShouldCapture,
    
  91.   ForceClientRender,
    
  92.   Passive,
    
  93. } from './ReactFiberFlags';
    
  94. import ReactSharedInternals from 'shared/ReactSharedInternals';
    
  95. import {
    
  96.   debugRenderPhaseSideEffectsForStrictMode,
    
  97.   disableLegacyContext,
    
  98.   disableModulePatternComponents,
    
  99.   enableProfilerCommitHooks,
    
  100.   enableProfilerTimer,
    
  101.   enableScopeAPI,
    
  102.   enableCache,
    
  103.   enableLazyContextPropagation,
    
  104.   enableSchedulingProfiler,
    
  105.   enableTransitionTracing,
    
  106.   enableLegacyHidden,
    
  107.   enableCPUSuspense,
    
  108.   enableFloat,
    
  109.   enableHostSingletons,
    
  110.   enableFormActions,
    
  111.   enableAsyncActions,
    
  112.   enablePostpone,
    
  113. } from 'shared/ReactFeatureFlags';
    
  114. import isArray from 'shared/isArray';
    
  115. import shallowEqual from 'shared/shallowEqual';
    
  116. import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
    
  117. import getComponentNameFromType from 'shared/getComponentNameFromType';
    
  118. import ReactStrictModeWarnings from './ReactStrictModeWarnings';
    
  119. import {REACT_LAZY_TYPE, getIteratorFn} from 'shared/ReactSymbols';
    
  120. import {
    
  121.   getCurrentFiberOwnerNameInDevOrNull,
    
  122.   setIsRendering,
    
  123. } from './ReactCurrentFiber';
    
  124. import {
    
  125.   resolveFunctionForHotReloading,
    
  126.   resolveForwardRefForHotReloading,
    
  127.   resolveClassForHotReloading,
    
  128. } from './ReactFiberHotReloading';
    
  129. 
    
  130. import {
    
  131.   mountChildFibers,
    
  132.   reconcileChildFibers,
    
  133.   cloneChildFibers,
    
  134. } from './ReactChildFiber';
    
  135. import {
    
  136.   processUpdateQueue,
    
  137.   cloneUpdateQueue,
    
  138.   initializeUpdateQueue,
    
  139.   enqueueCapturedUpdate,
    
  140. } from './ReactFiberClassUpdateQueue';
    
  141. import {
    
  142.   NoLane,
    
  143.   NoLanes,
    
  144.   SyncLane,
    
  145.   OffscreenLane,
    
  146.   DefaultHydrationLane,
    
  147.   SomeRetryLane,
    
  148.   includesSomeLane,
    
  149.   laneToLanes,
    
  150.   removeLanes,
    
  151.   mergeLanes,
    
  152.   getBumpedLaneForHydration,
    
  153.   pickArbitraryLane,
    
  154. } from './ReactFiberLane';
    
  155. import {
    
  156.   ConcurrentMode,
    
  157.   NoMode,
    
  158.   ProfileMode,
    
  159.   StrictLegacyMode,
    
  160. } from './ReactTypeOfMode';
    
  161. import {
    
  162.   shouldSetTextContent,
    
  163.   isSuspenseInstancePending,
    
  164.   isSuspenseInstanceFallback,
    
  165.   getSuspenseInstanceFallbackErrorDetails,
    
  166.   registerSuspenseInstanceRetry,
    
  167.   supportsHydration,
    
  168.   supportsResources,
    
  169.   supportsSingletons,
    
  170.   isPrimaryRenderer,
    
  171.   getResource,
    
  172.   createHoistableInstance,
    
  173. } from './ReactFiberConfig';
    
  174. import type {SuspenseInstance} from './ReactFiberConfig';
    
  175. import {shouldError, shouldSuspend} from './ReactFiberReconciler';
    
  176. import {
    
  177.   pushHostContext,
    
  178.   pushHostContainer,
    
  179.   getRootHostContainer,
    
  180.   HostTransitionContext,
    
  181. } from './ReactFiberHostContext';
    
  182. import {
    
  183.   suspenseStackCursor,
    
  184.   pushSuspenseListContext,
    
  185.   ForceSuspenseFallback,
    
  186.   hasSuspenseListContext,
    
  187.   setDefaultShallowSuspenseListContext,
    
  188.   setShallowSuspenseListContext,
    
  189.   pushPrimaryTreeSuspenseHandler,
    
  190.   pushFallbackTreeSuspenseHandler,
    
  191.   pushOffscreenSuspenseHandler,
    
  192.   reuseSuspenseHandlerOnStack,
    
  193.   popSuspenseHandler,
    
  194. } from './ReactFiberSuspenseContext';
    
  195. import {
    
  196.   pushHiddenContext,
    
  197.   reuseHiddenContextOnStack,
    
  198. } from './ReactFiberHiddenContext';
    
  199. import {findFirstSuspended} from './ReactFiberSuspenseComponent';
    
  200. import {
    
  201.   pushProvider,
    
  202.   propagateContextChange,
    
  203.   lazilyPropagateParentContextChanges,
    
  204.   propagateParentContextChangesToDeferredTree,
    
  205.   checkIfContextChanged,
    
  206.   readContext,
    
  207.   prepareToReadContext,
    
  208.   scheduleContextWorkOnParentPath,
    
  209. } from './ReactFiberNewContext';
    
  210. import {
    
  211.   renderWithHooks,
    
  212.   checkDidRenderIdHook,
    
  213.   bailoutHooks,
    
  214.   replaySuspendedComponentWithHooks,
    
  215.   renderTransitionAwareHostComponentWithHooks,
    
  216. } from './ReactFiberHooks';
    
  217. import {stopProfilerTimerIfRunning} from './ReactProfilerTimer';
    
  218. import {
    
  219.   getMaskedContext,
    
  220.   getUnmaskedContext,
    
  221.   hasContextChanged as hasLegacyContextChanged,
    
  222.   pushContextProvider as pushLegacyContextProvider,
    
  223.   isContextProvider as isLegacyContextProvider,
    
  224.   pushTopLevelContextObject,
    
  225.   invalidateContextProvider,
    
  226. } from './ReactFiberContext';
    
  227. import {
    
  228.   getIsHydrating,
    
  229.   enterHydrationState,
    
  230.   reenterHydrationStateFromDehydratedSuspenseInstance,
    
  231.   resetHydrationState,
    
  232.   claimHydratableSingleton,
    
  233.   tryToClaimNextHydratableInstance,
    
  234.   tryToClaimNextHydratableTextInstance,
    
  235.   tryToClaimNextHydratableSuspenseInstance,
    
  236.   warnIfHydrating,
    
  237.   queueHydrationError,
    
  238. } from './ReactFiberHydrationContext';
    
  239. import {
    
  240.   adoptClassInstance,
    
  241.   constructClassInstance,
    
  242.   mountClassInstance,
    
  243.   resumeMountClassInstance,
    
  244.   updateClassInstance,
    
  245. } from './ReactFiberClassComponent';
    
  246. import {resolveDefaultProps} from './ReactFiberLazyComponent';
    
  247. import {
    
  248.   resolveLazyComponentTag,
    
  249.   createFiberFromTypeAndProps,
    
  250.   createFiberFromFragment,
    
  251.   createFiberFromOffscreen,
    
  252.   createWorkInProgress,
    
  253.   isSimpleFunctionComponent,
    
  254. } from './ReactFiber';
    
  255. import {
    
  256.   retryDehydratedSuspenseBoundary,
    
  257.   scheduleUpdateOnFiber,
    
  258.   renderDidSuspendDelayIfPossible,
    
  259.   markSkippedUpdateLanes,
    
  260.   getWorkInProgressRoot,
    
  261. } from './ReactFiberWorkLoop';
    
  262. import {enqueueConcurrentRenderForLane} from './ReactFiberConcurrentUpdates';
    
  263. import {pushCacheProvider, CacheContext} from './ReactFiberCacheComponent';
    
  264. import {
    
  265.   createCapturedValue,
    
  266.   createCapturedValueAtFiber,
    
  267.   type CapturedValue,
    
  268. } from './ReactCapturedValue';
    
  269. import {createClassErrorUpdate} from './ReactFiberThrow';
    
  270. import is from 'shared/objectIs';
    
  271. import {
    
  272.   getForksAtLevel,
    
  273.   isForkedChild,
    
  274.   pushTreeId,
    
  275.   pushMaterializedTreeId,
    
  276. } from './ReactFiberTreeContext';
    
  277. import {
    
  278.   requestCacheFromPool,
    
  279.   pushRootTransition,
    
  280.   getSuspendedCache,
    
  281.   pushTransition,
    
  282.   getOffscreenDeferredCache,
    
  283.   getPendingTransitions,
    
  284. } from './ReactFiberTransition';
    
  285. import {
    
  286.   getMarkerInstances,
    
  287.   pushMarkerInstance,
    
  288.   pushRootMarkerInstance,
    
  289.   TransitionTracingMarker,
    
  290. } from './ReactFiberTracingMarkerComponent';
    
  291. 
    
  292. const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
    
  293. 
    
  294. // A special exception that's used to unwind the stack when an update flows
    
  295. // into a dehydrated boundary.
    
  296. export const SelectiveHydrationException: mixed = new Error(
    
  297.   "This is not a real error. It's an implementation detail of React's " +
    
  298.     "selective hydration feature. If this leaks into userspace, it's a bug in " +
    
  299.     'React. Please file an issue.',
    
  300. );
    
  301. 
    
  302. let didReceiveUpdate: boolean = false;
    
  303. 
    
  304. let didWarnAboutBadClass;
    
  305. let didWarnAboutModulePatternComponent;
    
  306. let didWarnAboutContextTypeOnFunctionComponent;
    
  307. let didWarnAboutGetDerivedStateOnFunctionComponent;
    
  308. let didWarnAboutFunctionRefs;
    
  309. export let didWarnAboutReassigningProps: boolean;
    
  310. let didWarnAboutRevealOrder;
    
  311. let didWarnAboutTailOptions;
    
  312. let didWarnAboutDefaultPropsOnFunctionComponent;
    
  313. 
    
  314. if (__DEV__) {
    
  315.   didWarnAboutBadClass = ({}: {[string]: boolean});
    
  316.   didWarnAboutModulePatternComponent = ({}: {[string]: boolean});
    
  317.   didWarnAboutContextTypeOnFunctionComponent = ({}: {[string]: boolean});
    
  318.   didWarnAboutGetDerivedStateOnFunctionComponent = ({}: {[string]: boolean});
    
  319.   didWarnAboutFunctionRefs = ({}: {[string]: boolean});
    
  320.   didWarnAboutReassigningProps = false;
    
  321.   didWarnAboutRevealOrder = ({}: {[empty]: boolean});
    
  322.   didWarnAboutTailOptions = ({}: {[string]: boolean});
    
  323.   didWarnAboutDefaultPropsOnFunctionComponent = ({}: {[string]: boolean});
    
  324. }
    
  325. 
    
  326. export function reconcileChildren(
    
  327.   current: Fiber | null,
    
  328.   workInProgress: Fiber,
    
  329.   nextChildren: any,
    
  330.   renderLanes: Lanes,
    
  331. ) {
    
  332.   if (current === null) {
    
  333.     // If this is a fresh new component that hasn't been rendered yet, we
    
  334.     // won't update its child set by applying minimal side-effects. Instead,
    
  335.     // we will add them all to the child before it gets rendered. That means
    
  336.     // we can optimize this reconciliation pass by not tracking side-effects.
    
  337.     workInProgress.child = mountChildFibers(
    
  338.       workInProgress,
    
  339.       null,
    
  340.       nextChildren,
    
  341.       renderLanes,
    
  342.     );
    
  343.   } else {
    
  344.     // If the current child is the same as the work in progress, it means that
    
  345.     // we haven't yet started any work on these children. Therefore, we use
    
  346.     // the clone algorithm to create a copy of all the current children.
    
  347. 
    
  348.     // If we had any progressed work already, that is invalid at this point so
    
  349.     // let's throw it out.
    
  350.     workInProgress.child = reconcileChildFibers(
    
  351.       workInProgress,
    
  352.       current.child,
    
  353.       nextChildren,
    
  354.       renderLanes,
    
  355.     );
    
  356.   }
    
  357. }
    
  358. 
    
  359. function forceUnmountCurrentAndReconcile(
    
  360.   current: Fiber,
    
  361.   workInProgress: Fiber,
    
  362.   nextChildren: any,
    
  363.   renderLanes: Lanes,
    
  364. ) {
    
  365.   // This function is fork of reconcileChildren. It's used in cases where we
    
  366.   // want to reconcile without matching against the existing set. This has the
    
  367.   // effect of all current children being unmounted; even if the type and key
    
  368.   // are the same, the old child is unmounted and a new child is created.
    
  369.   //
    
  370.   // To do this, we're going to go through the reconcile algorithm twice. In
    
  371.   // the first pass, we schedule a deletion for all the current children by
    
  372.   // passing null.
    
  373.   workInProgress.child = reconcileChildFibers(
    
  374.     workInProgress,
    
  375.     current.child,
    
  376.     null,
    
  377.     renderLanes,
    
  378.   );
    
  379.   // In the second pass, we mount the new children. The trick here is that we
    
  380.   // pass null in place of where we usually pass the current child set. This has
    
  381.   // the effect of remounting all children regardless of whether their
    
  382.   // identities match.
    
  383.   workInProgress.child = reconcileChildFibers(
    
  384.     workInProgress,
    
  385.     null,
    
  386.     nextChildren,
    
  387.     renderLanes,
    
  388.   );
    
  389. }
    
  390. 
    
  391. function updateForwardRef(
    
  392.   current: Fiber | null,
    
  393.   workInProgress: Fiber,
    
  394.   Component: any,
    
  395.   nextProps: any,
    
  396.   renderLanes: Lanes,
    
  397. ) {
    
  398.   // TODO: current can be non-null here even if the component
    
  399.   // hasn't yet mounted. This happens after the first render suspends.
    
  400.   // We'll need to figure out if this is fine or can cause issues.
    
  401. 
    
  402.   if (__DEV__) {
    
  403.     if (workInProgress.type !== workInProgress.elementType) {
    
  404.       // Lazy component props can't be validated in createElement
    
  405.       // because they're only guaranteed to be resolved here.
    
  406.       const innerPropTypes = Component.propTypes;
    
  407.       if (innerPropTypes) {
    
  408.         checkPropTypes(
    
  409.           innerPropTypes,
    
  410.           nextProps, // Resolved props
    
  411.           'prop',
    
  412.           getComponentNameFromType(Component),
    
  413.         );
    
  414.       }
    
  415.     }
    
  416.   }
    
  417. 
    
  418.   const render = Component.render;
    
  419.   const ref = workInProgress.ref;
    
  420. 
    
  421.   // The rest is a fork of updateFunctionComponent
    
  422.   let nextChildren;
    
  423.   let hasId;
    
  424.   prepareToReadContext(workInProgress, renderLanes);
    
  425.   if (enableSchedulingProfiler) {
    
  426.     markComponentRenderStarted(workInProgress);
    
  427.   }
    
  428.   if (__DEV__) {
    
  429.     ReactCurrentOwner.current = workInProgress;
    
  430.     setIsRendering(true);
    
  431.     nextChildren = renderWithHooks(
    
  432.       current,
    
  433.       workInProgress,
    
  434.       render,
    
  435.       nextProps,
    
  436.       ref,
    
  437.       renderLanes,
    
  438.     );
    
  439.     hasId = checkDidRenderIdHook();
    
  440.     setIsRendering(false);
    
  441.   } else {
    
  442.     nextChildren = renderWithHooks(
    
  443.       current,
    
  444.       workInProgress,
    
  445.       render,
    
  446.       nextProps,
    
  447.       ref,
    
  448.       renderLanes,
    
  449.     );
    
  450.     hasId = checkDidRenderIdHook();
    
  451.   }
    
  452.   if (enableSchedulingProfiler) {
    
  453.     markComponentRenderStopped();
    
  454.   }
    
  455. 
    
  456.   if (current !== null && !didReceiveUpdate) {
    
  457.     bailoutHooks(current, workInProgress, renderLanes);
    
  458.     return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
    
  459.   }
    
  460. 
    
  461.   if (getIsHydrating() && hasId) {
    
  462.     pushMaterializedTreeId(workInProgress);
    
  463.   }
    
  464. 
    
  465.   // React DevTools reads this flag.
    
  466.   workInProgress.flags |= PerformedWork;
    
  467.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  468.   return workInProgress.child;
    
  469. }
    
  470. 
    
  471. function updateMemoComponent(
    
  472.   current: Fiber | null,
    
  473.   workInProgress: Fiber,
    
  474.   Component: any,
    
  475.   nextProps: any,
    
  476.   renderLanes: Lanes,
    
  477. ): null | Fiber {
    
  478.   if (current === null) {
    
  479.     const type = Component.type;
    
  480.     if (
    
  481.       isSimpleFunctionComponent(type) &&
    
  482.       Component.compare === null &&
    
  483.       // SimpleMemoComponent codepath doesn't resolve outer props either.
    
  484.       Component.defaultProps === undefined
    
  485.     ) {
    
  486.       let resolvedType = type;
    
  487.       if (__DEV__) {
    
  488.         resolvedType = resolveFunctionForHotReloading(type);
    
  489.       }
    
  490.       // If this is a plain function component without default props,
    
  491.       // and with only the default shallow comparison, we upgrade it
    
  492.       // to a SimpleMemoComponent to allow fast path updates.
    
  493.       workInProgress.tag = SimpleMemoComponent;
    
  494.       workInProgress.type = resolvedType;
    
  495.       if (__DEV__) {
    
  496.         validateFunctionComponentInDev(workInProgress, type);
    
  497.       }
    
  498.       return updateSimpleMemoComponent(
    
  499.         current,
    
  500.         workInProgress,
    
  501.         resolvedType,
    
  502.         nextProps,
    
  503.         renderLanes,
    
  504.       );
    
  505.     }
    
  506.     if (__DEV__) {
    
  507.       const innerPropTypes = type.propTypes;
    
  508.       if (innerPropTypes) {
    
  509.         // Inner memo component props aren't currently validated in createElement.
    
  510.         // We could move it there, but we'd still need this for lazy code path.
    
  511.         checkPropTypes(
    
  512.           innerPropTypes,
    
  513.           nextProps, // Resolved props
    
  514.           'prop',
    
  515.           getComponentNameFromType(type),
    
  516.         );
    
  517.       }
    
  518.       if (Component.defaultProps !== undefined) {
    
  519.         const componentName = getComponentNameFromType(type) || 'Unknown';
    
  520.         if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) {
    
  521.           console.error(
    
  522.             '%s: Support for defaultProps will be removed from memo components ' +
    
  523.               'in a future major release. Use JavaScript default parameters instead.',
    
  524.             componentName,
    
  525.           );
    
  526.           didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true;
    
  527.         }
    
  528.       }
    
  529.     }
    
  530.     const child = createFiberFromTypeAndProps(
    
  531.       Component.type,
    
  532.       null,
    
  533.       nextProps,
    
  534.       null,
    
  535.       workInProgress,
    
  536.       workInProgress.mode,
    
  537.       renderLanes,
    
  538.     );
    
  539.     child.ref = workInProgress.ref;
    
  540.     child.return = workInProgress;
    
  541.     workInProgress.child = child;
    
  542.     return child;
    
  543.   }
    
  544.   if (__DEV__) {
    
  545.     const type = Component.type;
    
  546.     const innerPropTypes = type.propTypes;
    
  547.     if (innerPropTypes) {
    
  548.       // Inner memo component props aren't currently validated in createElement.
    
  549.       // We could move it there, but we'd still need this for lazy code path.
    
  550.       checkPropTypes(
    
  551.         innerPropTypes,
    
  552.         nextProps, // Resolved props
    
  553.         'prop',
    
  554.         getComponentNameFromType(type),
    
  555.       );
    
  556.     }
    
  557.   }
    
  558.   const currentChild = ((current.child: any): Fiber); // This is always exactly one child
    
  559.   const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(
    
  560.     current,
    
  561.     renderLanes,
    
  562.   );
    
  563.   if (!hasScheduledUpdateOrContext) {
    
  564.     // This will be the props with resolved defaultProps,
    
  565.     // unlike current.memoizedProps which will be the unresolved ones.
    
  566.     const prevProps = currentChild.memoizedProps;
    
  567.     // Default to shallow comparison
    
  568.     let compare = Component.compare;
    
  569.     compare = compare !== null ? compare : shallowEqual;
    
  570.     if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) {
    
  571.       return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
    
  572.     }
    
  573.   }
    
  574.   // React DevTools reads this flag.
    
  575.   workInProgress.flags |= PerformedWork;
    
  576.   const newChild = createWorkInProgress(currentChild, nextProps);
    
  577.   newChild.ref = workInProgress.ref;
    
  578.   newChild.return = workInProgress;
    
  579.   workInProgress.child = newChild;
    
  580.   return newChild;
    
  581. }
    
  582. 
    
  583. function updateSimpleMemoComponent(
    
  584.   current: Fiber | null,
    
  585.   workInProgress: Fiber,
    
  586.   Component: any,
    
  587.   nextProps: any,
    
  588.   renderLanes: Lanes,
    
  589. ): null | Fiber {
    
  590.   // TODO: current can be non-null here even if the component
    
  591.   // hasn't yet mounted. This happens when the inner render suspends.
    
  592.   // We'll need to figure out if this is fine or can cause issues.
    
  593. 
    
  594.   if (__DEV__) {
    
  595.     if (workInProgress.type !== workInProgress.elementType) {
    
  596.       // Lazy component props can't be validated in createElement
    
  597.       // because they're only guaranteed to be resolved here.
    
  598.       let outerMemoType = workInProgress.elementType;
    
  599.       if (outerMemoType.$$typeof === REACT_LAZY_TYPE) {
    
  600.         // We warn when you define propTypes on lazy()
    
  601.         // so let's just skip over it to find memo() outer wrapper.
    
  602.         // Inner props for memo are validated later.
    
  603.         const lazyComponent: LazyComponentType<any, any> = outerMemoType;
    
  604.         const payload = lazyComponent._payload;
    
  605.         const init = lazyComponent._init;
    
  606.         try {
    
  607.           outerMemoType = init(payload);
    
  608.         } catch (x) {
    
  609.           outerMemoType = null;
    
  610.         }
    
  611.         // Inner propTypes will be validated in the function component path.
    
  612.         const outerPropTypes = outerMemoType && (outerMemoType: any).propTypes;
    
  613.         if (outerPropTypes) {
    
  614.           checkPropTypes(
    
  615.             outerPropTypes,
    
  616.             nextProps, // Resolved (SimpleMemoComponent has no defaultProps)
    
  617.             'prop',
    
  618.             getComponentNameFromType(outerMemoType),
    
  619.           );
    
  620.         }
    
  621.       }
    
  622.     }
    
  623.   }
    
  624.   if (current !== null) {
    
  625.     const prevProps = current.memoizedProps;
    
  626.     if (
    
  627.       shallowEqual(prevProps, nextProps) &&
    
  628.       current.ref === workInProgress.ref &&
    
  629.       // Prevent bailout if the implementation changed due to hot reload.
    
  630.       (__DEV__ ? workInProgress.type === current.type : true)
    
  631.     ) {
    
  632.       didReceiveUpdate = false;
    
  633. 
    
  634.       // The props are shallowly equal. Reuse the previous props object, like we
    
  635.       // would during a normal fiber bailout.
    
  636.       //
    
  637.       // We don't have strong guarantees that the props object is referentially
    
  638.       // equal during updates where we can't bail out anyway — like if the props
    
  639.       // are shallowly equal, but there's a local state or context update in the
    
  640.       // same batch.
    
  641.       //
    
  642.       // However, as a principle, we should aim to make the behavior consistent
    
  643.       // across different ways of memoizing a component. For example, React.memo
    
  644.       // has a different internal Fiber layout if you pass a normal function
    
  645.       // component (SimpleMemoComponent) versus if you pass a different type
    
  646.       // like forwardRef (MemoComponent). But this is an implementation detail.
    
  647.       // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't
    
  648.       // affect whether the props object is reused during a bailout.
    
  649.       workInProgress.pendingProps = nextProps = prevProps;
    
  650. 
    
  651.       if (!checkScheduledUpdateOrContext(current, renderLanes)) {
    
  652.         // The pending lanes were cleared at the beginning of beginWork. We're
    
  653.         // about to bail out, but there might be other lanes that weren't
    
  654.         // included in the current render. Usually, the priority level of the
    
  655.         // remaining updates is accumulated during the evaluation of the
    
  656.         // component (i.e. when processing the update queue). But since since
    
  657.         // we're bailing out early *without* evaluating the component, we need
    
  658.         // to account for it here, too. Reset to the value of the current fiber.
    
  659.         // NOTE: This only applies to SimpleMemoComponent, not MemoComponent,
    
  660.         // because a MemoComponent fiber does not have hooks or an update queue;
    
  661.         // rather, it wraps around an inner component, which may or may not
    
  662.         // contains hooks.
    
  663.         // TODO: Move the reset at in beginWork out of the common path so that
    
  664.         // this is no longer necessary.
    
  665.         workInProgress.lanes = current.lanes;
    
  666.         return bailoutOnAlreadyFinishedWork(
    
  667.           current,
    
  668.           workInProgress,
    
  669.           renderLanes,
    
  670.         );
    
  671.       } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) {
    
  672.         // This is a special case that only exists for legacy mode.
    
  673.         // See https://github.com/facebook/react/pull/19216.
    
  674.         didReceiveUpdate = true;
    
  675.       }
    
  676.     }
    
  677.   }
    
  678.   return updateFunctionComponent(
    
  679.     current,
    
  680.     workInProgress,
    
  681.     Component,
    
  682.     nextProps,
    
  683.     renderLanes,
    
  684.   );
    
  685. }
    
  686. 
    
  687. function updateOffscreenComponent(
    
  688.   current: Fiber | null,
    
  689.   workInProgress: Fiber,
    
  690.   renderLanes: Lanes,
    
  691. ) {
    
  692.   const nextProps: OffscreenProps = workInProgress.pendingProps;
    
  693.   const nextChildren = nextProps.children;
    
  694.   const nextIsDetached =
    
  695.     (workInProgress.stateNode._pendingVisibility & OffscreenDetached) !== 0;
    
  696. 
    
  697.   const prevState: OffscreenState | null =
    
  698.     current !== null ? current.memoizedState : null;
    
  699. 
    
  700.   markRef(current, workInProgress);
    
  701. 
    
  702.   if (
    
  703.     nextProps.mode === 'hidden' ||
    
  704.     (enableLegacyHidden &&
    
  705.       nextProps.mode === 'unstable-defer-without-hiding') ||
    
  706.     nextIsDetached
    
  707.   ) {
    
  708.     // Rendering a hidden tree.
    
  709. 
    
  710.     const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;
    
  711.     if (didSuspend) {
    
  712.       // Something suspended inside a hidden tree
    
  713. 
    
  714.       // Include the base lanes from the last render
    
  715.       const nextBaseLanes =
    
  716.         prevState !== null
    
  717.           ? mergeLanes(prevState.baseLanes, renderLanes)
    
  718.           : renderLanes;
    
  719. 
    
  720.       if (current !== null) {
    
  721.         // Reset to the current children
    
  722.         let currentChild = (workInProgress.child = current.child);
    
  723. 
    
  724.         // The current render suspended, but there may be other lanes with
    
  725.         // pending work. We can't read `childLanes` from the current Offscreen
    
  726.         // fiber because we reset it when it was deferred; however, we can read
    
  727.         // the pending lanes from the child fibers.
    
  728.         let currentChildLanes = NoLanes;
    
  729.         while (currentChild !== null) {
    
  730.           currentChildLanes = mergeLanes(
    
  731.             mergeLanes(currentChildLanes, currentChild.lanes),
    
  732.             currentChild.childLanes,
    
  733.           );
    
  734.           currentChild = currentChild.sibling;
    
  735.         }
    
  736.         const lanesWeJustAttempted = nextBaseLanes;
    
  737.         const remainingChildLanes = removeLanes(
    
  738.           currentChildLanes,
    
  739.           lanesWeJustAttempted,
    
  740.         );
    
  741.         workInProgress.childLanes = remainingChildLanes;
    
  742.       } else {
    
  743.         workInProgress.childLanes = NoLanes;
    
  744.         workInProgress.child = null;
    
  745.       }
    
  746. 
    
  747.       return deferHiddenOffscreenComponent(
    
  748.         current,
    
  749.         workInProgress,
    
  750.         nextBaseLanes,
    
  751.         renderLanes,
    
  752.       );
    
  753.     }
    
  754. 
    
  755.     if ((workInProgress.mode & ConcurrentMode) === NoMode) {
    
  756.       // In legacy sync mode, don't defer the subtree. Render it now.
    
  757.       // TODO: Consider how Offscreen should work with transitions in the future
    
  758.       const nextState: OffscreenState = {
    
  759.         baseLanes: NoLanes,
    
  760.         cachePool: null,
    
  761.       };
    
  762.       workInProgress.memoizedState = nextState;
    
  763.       if (enableCache) {
    
  764.         // push the cache pool even though we're going to bail out
    
  765.         // because otherwise there'd be a context mismatch
    
  766.         if (current !== null) {
    
  767.           pushTransition(workInProgress, null, null);
    
  768.         }
    
  769.       }
    
  770.       reuseHiddenContextOnStack(workInProgress);
    
  771.       pushOffscreenSuspenseHandler(workInProgress);
    
  772.     } else if (!includesSomeLane(renderLanes, (OffscreenLane: Lane))) {
    
  773.       // We're hidden, and we're not rendering at Offscreen. We will bail out
    
  774.       // and resume this tree later.
    
  775. 
    
  776.       // Schedule this fiber to re-render at Offscreen priority
    
  777.       workInProgress.lanes = workInProgress.childLanes =
    
  778.         laneToLanes(OffscreenLane);
    
  779. 
    
  780.       // Include the base lanes from the last render
    
  781.       const nextBaseLanes =
    
  782.         prevState !== null
    
  783.           ? mergeLanes(prevState.baseLanes, renderLanes)
    
  784.           : renderLanes;
    
  785. 
    
  786.       return deferHiddenOffscreenComponent(
    
  787.         current,
    
  788.         workInProgress,
    
  789.         nextBaseLanes,
    
  790.         renderLanes,
    
  791.       );
    
  792.     } else {
    
  793.       // This is the second render. The surrounding visible content has already
    
  794.       // committed. Now we resume rendering the hidden tree.
    
  795. 
    
  796.       // Rendering at offscreen, so we can clear the base lanes.
    
  797.       const nextState: OffscreenState = {
    
  798.         baseLanes: NoLanes,
    
  799.         cachePool: null,
    
  800.       };
    
  801.       workInProgress.memoizedState = nextState;
    
  802.       if (enableCache && current !== null) {
    
  803.         // If the render that spawned this one accessed the cache pool, resume
    
  804.         // using the same cache. Unless the parent changed, since that means
    
  805.         // there was a refresh.
    
  806.         const prevCachePool = prevState !== null ? prevState.cachePool : null;
    
  807.         // TODO: Consider if and how Offscreen pre-rendering should
    
  808.         // be attributed to the transition that spawned it
    
  809.         pushTransition(workInProgress, prevCachePool, null);
    
  810.       }
    
  811. 
    
  812.       // Push the lanes that were skipped when we bailed out.
    
  813.       if (prevState !== null) {
    
  814.         pushHiddenContext(workInProgress, prevState);
    
  815.       } else {
    
  816.         reuseHiddenContextOnStack(workInProgress);
    
  817.       }
    
  818.       pushOffscreenSuspenseHandler(workInProgress);
    
  819.     }
    
  820.   } else {
    
  821.     // Rendering a visible tree.
    
  822.     if (prevState !== null) {
    
  823.       // We're going from hidden -> visible.
    
  824.       let prevCachePool = null;
    
  825.       if (enableCache) {
    
  826.         // If the render that spawned this one accessed the cache pool, resume
    
  827.         // using the same cache. Unless the parent changed, since that means
    
  828.         // there was a refresh.
    
  829.         prevCachePool = prevState.cachePool;
    
  830.       }
    
  831. 
    
  832.       let transitions = null;
    
  833.       if (enableTransitionTracing) {
    
  834.         // We have now gone from hidden to visible, so any transitions should
    
  835.         // be added to the stack to get added to any Offscreen/suspense children
    
  836.         const instance: OffscreenInstance | null = workInProgress.stateNode;
    
  837.         if (instance !== null && instance._transitions != null) {
    
  838.           transitions = Array.from(instance._transitions);
    
  839.         }
    
  840.       }
    
  841. 
    
  842.       pushTransition(workInProgress, prevCachePool, transitions);
    
  843. 
    
  844.       // Push the lanes that were skipped when we bailed out.
    
  845.       pushHiddenContext(workInProgress, prevState);
    
  846.       reuseSuspenseHandlerOnStack(workInProgress);
    
  847. 
    
  848.       // Since we're not hidden anymore, reset the state
    
  849.       workInProgress.memoizedState = null;
    
  850.     } else {
    
  851.       // We weren't previously hidden, and we still aren't, so there's nothing
    
  852.       // special to do. Need to push to the stack regardless, though, to avoid
    
  853.       // a push/pop misalignment.
    
  854. 
    
  855.       if (enableCache) {
    
  856.         // If the render that spawned this one accessed the cache pool, resume
    
  857.         // using the same cache. Unless the parent changed, since that means
    
  858.         // there was a refresh.
    
  859.         if (current !== null) {
    
  860.           pushTransition(workInProgress, null, null);
    
  861.         }
    
  862.       }
    
  863. 
    
  864.       // We're about to bail out, but we need to push this to the stack anyway
    
  865.       // to avoid a push/pop misalignment.
    
  866.       reuseHiddenContextOnStack(workInProgress);
    
  867.       reuseSuspenseHandlerOnStack(workInProgress);
    
  868.     }
    
  869.   }
    
  870. 
    
  871.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  872.   return workInProgress.child;
    
  873. }
    
  874. 
    
  875. function deferHiddenOffscreenComponent(
    
  876.   current: Fiber | null,
    
  877.   workInProgress: Fiber,
    
  878.   nextBaseLanes: Lanes,
    
  879.   renderLanes: Lanes,
    
  880. ) {
    
  881.   const nextState: OffscreenState = {
    
  882.     baseLanes: nextBaseLanes,
    
  883.     // Save the cache pool so we can resume later.
    
  884.     cachePool: enableCache ? getOffscreenDeferredCache() : null,
    
  885.   };
    
  886.   workInProgress.memoizedState = nextState;
    
  887.   if (enableCache) {
    
  888.     // push the cache pool even though we're going to bail out
    
  889.     // because otherwise there'd be a context mismatch
    
  890.     if (current !== null) {
    
  891.       pushTransition(workInProgress, null, null);
    
  892.     }
    
  893.   }
    
  894. 
    
  895.   // We're about to bail out, but we need to push this to the stack anyway
    
  896.   // to avoid a push/pop misalignment.
    
  897.   reuseHiddenContextOnStack(workInProgress);
    
  898. 
    
  899.   pushOffscreenSuspenseHandler(workInProgress);
    
  900. 
    
  901.   if (enableLazyContextPropagation && current !== null) {
    
  902.     // Since this tree will resume rendering in a separate render, we need
    
  903.     // to propagate parent contexts now so we don't lose track of which
    
  904.     // ones changed.
    
  905.     propagateParentContextChangesToDeferredTree(
    
  906.       current,
    
  907.       workInProgress,
    
  908.       renderLanes,
    
  909.     );
    
  910.   }
    
  911. 
    
  912.   return null;
    
  913. }
    
  914. 
    
  915. // Note: These happen to have identical begin phases, for now. We shouldn't hold
    
  916. // ourselves to this constraint, though. If the behavior diverges, we should
    
  917. // fork the function.
    
  918. const updateLegacyHiddenComponent = updateOffscreenComponent;
    
  919. 
    
  920. function updateCacheComponent(
    
  921.   current: Fiber | null,
    
  922.   workInProgress: Fiber,
    
  923.   renderLanes: Lanes,
    
  924. ) {
    
  925.   if (!enableCache) {
    
  926.     return null;
    
  927.   }
    
  928. 
    
  929.   prepareToReadContext(workInProgress, renderLanes);
    
  930.   const parentCache = readContext(CacheContext);
    
  931. 
    
  932.   if (current === null) {
    
  933.     // Initial mount. Request a fresh cache from the pool.
    
  934.     const freshCache = requestCacheFromPool(renderLanes);
    
  935.     const initialState: CacheComponentState = {
    
  936.       parent: parentCache,
    
  937.       cache: freshCache,
    
  938.     };
    
  939.     workInProgress.memoizedState = initialState;
    
  940.     initializeUpdateQueue(workInProgress);
    
  941.     pushCacheProvider(workInProgress, freshCache);
    
  942.   } else {
    
  943.     // Check for updates
    
  944.     if (includesSomeLane(current.lanes, renderLanes)) {
    
  945.       cloneUpdateQueue(current, workInProgress);
    
  946.       processUpdateQueue(workInProgress, null, null, renderLanes);
    
  947.     }
    
  948.     const prevState: CacheComponentState = current.memoizedState;
    
  949.     const nextState: CacheComponentState = workInProgress.memoizedState;
    
  950. 
    
  951.     // Compare the new parent cache to the previous to see detect there was
    
  952.     // a refresh.
    
  953.     if (prevState.parent !== parentCache) {
    
  954.       // Refresh in parent. Update the parent.
    
  955.       const derivedState: CacheComponentState = {
    
  956.         parent: parentCache,
    
  957.         cache: parentCache,
    
  958.       };
    
  959. 
    
  960.       // Copied from getDerivedStateFromProps implementation. Once the update
    
  961.       // queue is empty, persist the derived state onto the base state.
    
  962.       workInProgress.memoizedState = derivedState;
    
  963.       if (workInProgress.lanes === NoLanes) {
    
  964.         const updateQueue: UpdateQueue<any> = (workInProgress.updateQueue: any);
    
  965.         workInProgress.memoizedState = updateQueue.baseState = derivedState;
    
  966.       }
    
  967. 
    
  968.       pushCacheProvider(workInProgress, parentCache);
    
  969.       // No need to propagate a context change because the refreshed parent
    
  970.       // already did.
    
  971.     } else {
    
  972.       // The parent didn't refresh. Now check if this cache did.
    
  973.       const nextCache = nextState.cache;
    
  974.       pushCacheProvider(workInProgress, nextCache);
    
  975.       if (nextCache !== prevState.cache) {
    
  976.         // This cache refreshed. Propagate a context change.
    
  977.         propagateContextChange(workInProgress, CacheContext, renderLanes);
    
  978.       }
    
  979.     }
    
  980.   }
    
  981. 
    
  982.   const nextChildren = workInProgress.pendingProps.children;
    
  983.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  984.   return workInProgress.child;
    
  985. }
    
  986. 
    
  987. // This should only be called if the name changes
    
  988. function updateTracingMarkerComponent(
    
  989.   current: Fiber | null,
    
  990.   workInProgress: Fiber,
    
  991.   renderLanes: Lanes,
    
  992. ) {
    
  993.   if (!enableTransitionTracing) {
    
  994.     return null;
    
  995.   }
    
  996. 
    
  997.   // TODO: (luna) Only update the tracing marker if it's newly rendered or it's name changed.
    
  998.   // A tracing marker is only associated with the transitions that rendered
    
  999.   // or updated it, so we can create a new set of transitions each time
    
  1000.   if (current === null) {
    
  1001.     const currentTransitions = getPendingTransitions();
    
  1002.     if (currentTransitions !== null) {
    
  1003.       const markerInstance: TracingMarkerInstance = {
    
  1004.         tag: TransitionTracingMarker,
    
  1005.         transitions: new Set(currentTransitions),
    
  1006.         pendingBoundaries: null,
    
  1007.         name: workInProgress.pendingProps.name,
    
  1008.         aborts: null,
    
  1009.       };
    
  1010.       workInProgress.stateNode = markerInstance;
    
  1011. 
    
  1012.       // We call the marker complete callback when all child suspense boundaries resolve.
    
  1013.       // We do this in the commit phase on Offscreen. If the marker has no child suspense
    
  1014.       // boundaries, we need to schedule a passive effect to make sure we call the marker
    
  1015.       // complete callback.
    
  1016.       workInProgress.flags |= Passive;
    
  1017.     }
    
  1018.   } else {
    
  1019.     if (__DEV__) {
    
  1020.       if (current.memoizedProps.name !== workInProgress.pendingProps.name) {
    
  1021.         console.error(
    
  1022.           'Changing the name of a tracing marker after mount is not supported. ' +
    
  1023.             'To remount the tracing marker, pass it a new key.',
    
  1024.         );
    
  1025.       }
    
  1026.     }
    
  1027.   }
    
  1028. 
    
  1029.   const instance: TracingMarkerInstance | null = workInProgress.stateNode;
    
  1030.   if (instance !== null) {
    
  1031.     pushMarkerInstance(workInProgress, instance);
    
  1032.   }
    
  1033.   const nextChildren = workInProgress.pendingProps.children;
    
  1034.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1035.   return workInProgress.child;
    
  1036. }
    
  1037. 
    
  1038. function updateFragment(
    
  1039.   current: Fiber | null,
    
  1040.   workInProgress: Fiber,
    
  1041.   renderLanes: Lanes,
    
  1042. ) {
    
  1043.   const nextChildren = workInProgress.pendingProps;
    
  1044.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1045.   return workInProgress.child;
    
  1046. }
    
  1047. 
    
  1048. function updateMode(
    
  1049.   current: Fiber | null,
    
  1050.   workInProgress: Fiber,
    
  1051.   renderLanes: Lanes,
    
  1052. ) {
    
  1053.   const nextChildren = workInProgress.pendingProps.children;
    
  1054.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1055.   return workInProgress.child;
    
  1056. }
    
  1057. 
    
  1058. function updateProfiler(
    
  1059.   current: Fiber | null,
    
  1060.   workInProgress: Fiber,
    
  1061.   renderLanes: Lanes,
    
  1062. ) {
    
  1063.   if (enableProfilerTimer) {
    
  1064.     workInProgress.flags |= Update;
    
  1065. 
    
  1066.     if (enableProfilerCommitHooks) {
    
  1067.       // Reset effect durations for the next eventual effect phase.
    
  1068.       // These are reset during render to allow the DevTools commit hook a chance to read them,
    
  1069.       const stateNode = workInProgress.stateNode;
    
  1070.       stateNode.effectDuration = 0;
    
  1071.       stateNode.passiveEffectDuration = 0;
    
  1072.     }
    
  1073.   }
    
  1074.   const nextProps = workInProgress.pendingProps;
    
  1075.   const nextChildren = nextProps.children;
    
  1076.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1077.   return workInProgress.child;
    
  1078. }
    
  1079. 
    
  1080. function markRef(current: Fiber | null, workInProgress: Fiber) {
    
  1081.   const ref = workInProgress.ref;
    
  1082.   if (
    
  1083.     (current === null && ref !== null) ||
    
  1084.     (current !== null && current.ref !== ref)
    
  1085.   ) {
    
  1086.     // Schedule a Ref effect
    
  1087.     workInProgress.flags |= Ref;
    
  1088.     workInProgress.flags |= RefStatic;
    
  1089.   }
    
  1090. }
    
  1091. 
    
  1092. function updateFunctionComponent(
    
  1093.   current: null | Fiber,
    
  1094.   workInProgress: Fiber,
    
  1095.   Component: any,
    
  1096.   nextProps: any,
    
  1097.   renderLanes: Lanes,
    
  1098. ) {
    
  1099.   if (__DEV__) {
    
  1100.     if (workInProgress.type !== workInProgress.elementType) {
    
  1101.       // Lazy component props can't be validated in createElement
    
  1102.       // because they're only guaranteed to be resolved here.
    
  1103.       const innerPropTypes = Component.propTypes;
    
  1104.       if (innerPropTypes) {
    
  1105.         checkPropTypes(
    
  1106.           innerPropTypes,
    
  1107.           nextProps, // Resolved props
    
  1108.           'prop',
    
  1109.           getComponentNameFromType(Component),
    
  1110.         );
    
  1111.       }
    
  1112.     }
    
  1113.   }
    
  1114. 
    
  1115.   let context;
    
  1116.   if (!disableLegacyContext) {
    
  1117.     const unmaskedContext = getUnmaskedContext(workInProgress, Component, true);
    
  1118.     context = getMaskedContext(workInProgress, unmaskedContext);
    
  1119.   }
    
  1120. 
    
  1121.   let nextChildren;
    
  1122.   let hasId;
    
  1123.   prepareToReadContext(workInProgress, renderLanes);
    
  1124.   if (enableSchedulingProfiler) {
    
  1125.     markComponentRenderStarted(workInProgress);
    
  1126.   }
    
  1127.   if (__DEV__) {
    
  1128.     ReactCurrentOwner.current = workInProgress;
    
  1129.     setIsRendering(true);
    
  1130.     nextChildren = renderWithHooks(
    
  1131.       current,
    
  1132.       workInProgress,
    
  1133.       Component,
    
  1134.       nextProps,
    
  1135.       context,
    
  1136.       renderLanes,
    
  1137.     );
    
  1138.     hasId = checkDidRenderIdHook();
    
  1139.     setIsRendering(false);
    
  1140.   } else {
    
  1141.     nextChildren = renderWithHooks(
    
  1142.       current,
    
  1143.       workInProgress,
    
  1144.       Component,
    
  1145.       nextProps,
    
  1146.       context,
    
  1147.       renderLanes,
    
  1148.     );
    
  1149.     hasId = checkDidRenderIdHook();
    
  1150.   }
    
  1151.   if (enableSchedulingProfiler) {
    
  1152.     markComponentRenderStopped();
    
  1153.   }
    
  1154. 
    
  1155.   if (current !== null && !didReceiveUpdate) {
    
  1156.     bailoutHooks(current, workInProgress, renderLanes);
    
  1157.     return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
    
  1158.   }
    
  1159. 
    
  1160.   if (getIsHydrating() && hasId) {
    
  1161.     pushMaterializedTreeId(workInProgress);
    
  1162.   }
    
  1163. 
    
  1164.   // React DevTools reads this flag.
    
  1165.   workInProgress.flags |= PerformedWork;
    
  1166.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1167.   return workInProgress.child;
    
  1168. }
    
  1169. 
    
  1170. export function replayFunctionComponent(
    
  1171.   current: Fiber | null,
    
  1172.   workInProgress: Fiber,
    
  1173.   nextProps: any,
    
  1174.   Component: any,
    
  1175.   secondArg: any,
    
  1176.   renderLanes: Lanes,
    
  1177. ): Fiber | null {
    
  1178.   // This function is used to replay a component that previously suspended,
    
  1179.   // after its data resolves. It's a simplified version of
    
  1180.   // updateFunctionComponent that reuses the hooks from the previous attempt.
    
  1181. 
    
  1182.   prepareToReadContext(workInProgress, renderLanes);
    
  1183.   if (enableSchedulingProfiler) {
    
  1184.     markComponentRenderStarted(workInProgress);
    
  1185.   }
    
  1186.   const nextChildren = replaySuspendedComponentWithHooks(
    
  1187.     current,
    
  1188.     workInProgress,
    
  1189.     Component,
    
  1190.     nextProps,
    
  1191.     secondArg,
    
  1192.   );
    
  1193.   const hasId = checkDidRenderIdHook();
    
  1194.   if (enableSchedulingProfiler) {
    
  1195.     markComponentRenderStopped();
    
  1196.   }
    
  1197. 
    
  1198.   if (current !== null && !didReceiveUpdate) {
    
  1199.     bailoutHooks(current, workInProgress, renderLanes);
    
  1200.     return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
    
  1201.   }
    
  1202. 
    
  1203.   if (getIsHydrating() && hasId) {
    
  1204.     pushMaterializedTreeId(workInProgress);
    
  1205.   }
    
  1206. 
    
  1207.   // React DevTools reads this flag.
    
  1208.   workInProgress.flags |= PerformedWork;
    
  1209.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1210.   return workInProgress.child;
    
  1211. }
    
  1212. 
    
  1213. function updateClassComponent(
    
  1214.   current: Fiber | null,
    
  1215.   workInProgress: Fiber,
    
  1216.   Component: any,
    
  1217.   nextProps: any,
    
  1218.   renderLanes: Lanes,
    
  1219. ) {
    
  1220.   if (__DEV__) {
    
  1221.     // This is used by DevTools to force a boundary to error.
    
  1222.     switch (shouldError(workInProgress)) {
    
  1223.       case false: {
    
  1224.         const instance = workInProgress.stateNode;
    
  1225.         const ctor = workInProgress.type;
    
  1226.         // TODO This way of resetting the error boundary state is a hack.
    
  1227.         // Is there a better way to do this?
    
  1228.         const tempInstance = new ctor(
    
  1229.           workInProgress.memoizedProps,
    
  1230.           instance.context,
    
  1231.         );
    
  1232.         const state = tempInstance.state;
    
  1233.         instance.updater.enqueueSetState(instance, state, null);
    
  1234.         break;
    
  1235.       }
    
  1236.       case true: {
    
  1237.         workInProgress.flags |= DidCapture;
    
  1238.         workInProgress.flags |= ShouldCapture;
    
  1239.         // eslint-disable-next-line react-internal/prod-error-codes
    
  1240.         const error = new Error('Simulated error coming from DevTools');
    
  1241.         const lane = pickArbitraryLane(renderLanes);
    
  1242.         workInProgress.lanes = mergeLanes(workInProgress.lanes, lane);
    
  1243.         // Schedule the error boundary to re-render using updated state
    
  1244.         const update = createClassErrorUpdate(
    
  1245.           workInProgress,
    
  1246.           createCapturedValueAtFiber(error, workInProgress),
    
  1247.           lane,
    
  1248.         );
    
  1249.         enqueueCapturedUpdate(workInProgress, update);
    
  1250.         break;
    
  1251.       }
    
  1252.     }
    
  1253. 
    
  1254.     if (workInProgress.type !== workInProgress.elementType) {
    
  1255.       // Lazy component props can't be validated in createElement
    
  1256.       // because they're only guaranteed to be resolved here.
    
  1257.       const innerPropTypes = Component.propTypes;
    
  1258.       if (innerPropTypes) {
    
  1259.         checkPropTypes(
    
  1260.           innerPropTypes,
    
  1261.           nextProps, // Resolved props
    
  1262.           'prop',
    
  1263.           getComponentNameFromType(Component),
    
  1264.         );
    
  1265.       }
    
  1266.     }
    
  1267.   }
    
  1268. 
    
  1269.   // Push context providers early to prevent context stack mismatches.
    
  1270.   // During mounting we don't know the child context yet as the instance doesn't exist.
    
  1271.   // We will invalidate the child context in finishClassComponent() right after rendering.
    
  1272.   let hasContext;
    
  1273.   if (isLegacyContextProvider(Component)) {
    
  1274.     hasContext = true;
    
  1275.     pushLegacyContextProvider(workInProgress);
    
  1276.   } else {
    
  1277.     hasContext = false;
    
  1278.   }
    
  1279.   prepareToReadContext(workInProgress, renderLanes);
    
  1280. 
    
  1281.   const instance = workInProgress.stateNode;
    
  1282.   let shouldUpdate;
    
  1283.   if (instance === null) {
    
  1284.     resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress);
    
  1285. 
    
  1286.     // In the initial pass we might need to construct the instance.
    
  1287.     constructClassInstance(workInProgress, Component, nextProps);
    
  1288.     mountClassInstance(workInProgress, Component, nextProps, renderLanes);
    
  1289.     shouldUpdate = true;
    
  1290.   } else if (current === null) {
    
  1291.     // In a resume, we'll already have an instance we can reuse.
    
  1292.     shouldUpdate = resumeMountClassInstance(
    
  1293.       workInProgress,
    
  1294.       Component,
    
  1295.       nextProps,
    
  1296.       renderLanes,
    
  1297.     );
    
  1298.   } else {
    
  1299.     shouldUpdate = updateClassInstance(
    
  1300.       current,
    
  1301.       workInProgress,
    
  1302.       Component,
    
  1303.       nextProps,
    
  1304.       renderLanes,
    
  1305.     );
    
  1306.   }
    
  1307.   const nextUnitOfWork = finishClassComponent(
    
  1308.     current,
    
  1309.     workInProgress,
    
  1310.     Component,
    
  1311.     shouldUpdate,
    
  1312.     hasContext,
    
  1313.     renderLanes,
    
  1314.   );
    
  1315.   if (__DEV__) {
    
  1316.     const inst = workInProgress.stateNode;
    
  1317.     if (shouldUpdate && inst.props !== nextProps) {
    
  1318.       if (!didWarnAboutReassigningProps) {
    
  1319.         console.error(
    
  1320.           'It looks like %s is reassigning its own `this.props` while rendering. ' +
    
  1321.             'This is not supported and can lead to confusing bugs.',
    
  1322.           getComponentNameFromFiber(workInProgress) || 'a component',
    
  1323.         );
    
  1324.       }
    
  1325.       didWarnAboutReassigningProps = true;
    
  1326.     }
    
  1327.   }
    
  1328.   return nextUnitOfWork;
    
  1329. }
    
  1330. 
    
  1331. function finishClassComponent(
    
  1332.   current: Fiber | null,
    
  1333.   workInProgress: Fiber,
    
  1334.   Component: any,
    
  1335.   shouldUpdate: boolean,
    
  1336.   hasContext: boolean,
    
  1337.   renderLanes: Lanes,
    
  1338. ) {
    
  1339.   // Refs should update even if shouldComponentUpdate returns false
    
  1340.   markRef(current, workInProgress);
    
  1341. 
    
  1342.   const didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags;
    
  1343. 
    
  1344.   if (!shouldUpdate && !didCaptureError) {
    
  1345.     // Context providers should defer to sCU for rendering
    
  1346.     if (hasContext) {
    
  1347.       invalidateContextProvider(workInProgress, Component, false);
    
  1348.     }
    
  1349. 
    
  1350.     return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
    
  1351.   }
    
  1352. 
    
  1353.   const instance = workInProgress.stateNode;
    
  1354. 
    
  1355.   // Rerender
    
  1356.   ReactCurrentOwner.current = workInProgress;
    
  1357.   let nextChildren;
    
  1358.   if (
    
  1359.     didCaptureError &&
    
  1360.     typeof Component.getDerivedStateFromError !== 'function'
    
  1361.   ) {
    
  1362.     // If we captured an error, but getDerivedStateFromError is not defined,
    
  1363.     // unmount all the children. componentDidCatch will schedule an update to
    
  1364.     // re-render a fallback. This is temporary until we migrate everyone to
    
  1365.     // the new API.
    
  1366.     // TODO: Warn in a future release.
    
  1367.     nextChildren = null;
    
  1368. 
    
  1369.     if (enableProfilerTimer) {
    
  1370.       stopProfilerTimerIfRunning(workInProgress);
    
  1371.     }
    
  1372.   } else {
    
  1373.     if (enableSchedulingProfiler) {
    
  1374.       markComponentRenderStarted(workInProgress);
    
  1375.     }
    
  1376.     if (__DEV__) {
    
  1377.       setIsRendering(true);
    
  1378.       nextChildren = instance.render();
    
  1379.       if (
    
  1380.         debugRenderPhaseSideEffectsForStrictMode &&
    
  1381.         workInProgress.mode & StrictLegacyMode
    
  1382.       ) {
    
  1383.         setIsStrictModeForDevtools(true);
    
  1384.         try {
    
  1385.           instance.render();
    
  1386.         } finally {
    
  1387.           setIsStrictModeForDevtools(false);
    
  1388.         }
    
  1389.       }
    
  1390.       setIsRendering(false);
    
  1391.     } else {
    
  1392.       nextChildren = instance.render();
    
  1393.     }
    
  1394.     if (enableSchedulingProfiler) {
    
  1395.       markComponentRenderStopped();
    
  1396.     }
    
  1397.   }
    
  1398. 
    
  1399.   // React DevTools reads this flag.
    
  1400.   workInProgress.flags |= PerformedWork;
    
  1401.   if (current !== null && didCaptureError) {
    
  1402.     // If we're recovering from an error, reconcile without reusing any of
    
  1403.     // the existing children. Conceptually, the normal children and the children
    
  1404.     // that are shown on error are two different sets, so we shouldn't reuse
    
  1405.     // normal children even if their identities match.
    
  1406.     forceUnmountCurrentAndReconcile(
    
  1407.       current,
    
  1408.       workInProgress,
    
  1409.       nextChildren,
    
  1410.       renderLanes,
    
  1411.     );
    
  1412.   } else {
    
  1413.     reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1414.   }
    
  1415. 
    
  1416.   // Memoize state using the values we just used to render.
    
  1417.   // TODO: Restructure so we never read values from the instance.
    
  1418.   workInProgress.memoizedState = instance.state;
    
  1419. 
    
  1420.   // The context might have changed so we need to recalculate it.
    
  1421.   if (hasContext) {
    
  1422.     invalidateContextProvider(workInProgress, Component, true);
    
  1423.   }
    
  1424. 
    
  1425.   return workInProgress.child;
    
  1426. }
    
  1427. 
    
  1428. function pushHostRootContext(workInProgress: Fiber) {
    
  1429.   const root = (workInProgress.stateNode: FiberRoot);
    
  1430.   if (root.pendingContext) {
    
  1431.     pushTopLevelContextObject(
    
  1432.       workInProgress,
    
  1433.       root.pendingContext,
    
  1434.       root.pendingContext !== root.context,
    
  1435.     );
    
  1436.   } else if (root.context) {
    
  1437.     // Should always be set
    
  1438.     pushTopLevelContextObject(workInProgress, root.context, false);
    
  1439.   }
    
  1440.   pushHostContainer(workInProgress, root.containerInfo);
    
  1441. }
    
  1442. 
    
  1443. function updateHostRoot(
    
  1444.   current: null | Fiber,
    
  1445.   workInProgress: Fiber,
    
  1446.   renderLanes: Lanes,
    
  1447. ) {
    
  1448.   pushHostRootContext(workInProgress);
    
  1449. 
    
  1450.   if (current === null) {
    
  1451.     throw new Error('Should have a current fiber. This is a bug in React.');
    
  1452.   }
    
  1453. 
    
  1454.   const nextProps = workInProgress.pendingProps;
    
  1455.   const prevState = workInProgress.memoizedState;
    
  1456.   const prevChildren = prevState.element;
    
  1457.   cloneUpdateQueue(current, workInProgress);
    
  1458.   processUpdateQueue(workInProgress, nextProps, null, renderLanes);
    
  1459. 
    
  1460.   const nextState: RootState = workInProgress.memoizedState;
    
  1461.   const root: FiberRoot = workInProgress.stateNode;
    
  1462.   pushRootTransition(workInProgress, root, renderLanes);
    
  1463. 
    
  1464.   if (enableTransitionTracing) {
    
  1465.     pushRootMarkerInstance(workInProgress);
    
  1466.   }
    
  1467. 
    
  1468.   if (enableCache) {
    
  1469.     const nextCache: Cache = nextState.cache;
    
  1470.     pushCacheProvider(workInProgress, nextCache);
    
  1471.     if (nextCache !== prevState.cache) {
    
  1472.       // The root cache refreshed.
    
  1473.       propagateContextChange(workInProgress, CacheContext, renderLanes);
    
  1474.     }
    
  1475.   }
    
  1476. 
    
  1477.   // Caution: React DevTools currently depends on this property
    
  1478.   // being called "element".
    
  1479.   const nextChildren = nextState.element;
    
  1480.   if (supportsHydration && prevState.isDehydrated) {
    
  1481.     // This is a hydration root whose shell has not yet hydrated. We should
    
  1482.     // attempt to hydrate.
    
  1483. 
    
  1484.     // Flip isDehydrated to false to indicate that when this render
    
  1485.     // finishes, the root will no longer be dehydrated.
    
  1486.     const overrideState: RootState = {
    
  1487.       element: nextChildren,
    
  1488.       isDehydrated: false,
    
  1489.       cache: nextState.cache,
    
  1490.     };
    
  1491.     const updateQueue: UpdateQueue<RootState> =
    
  1492.       (workInProgress.updateQueue: any);
    
  1493.     // `baseState` can always be the last state because the root doesn't
    
  1494.     // have reducer functions so it doesn't need rebasing.
    
  1495.     updateQueue.baseState = overrideState;
    
  1496.     workInProgress.memoizedState = overrideState;
    
  1497. 
    
  1498.     if (workInProgress.flags & ForceClientRender) {
    
  1499.       // Something errored during a previous attempt to hydrate the shell, so we
    
  1500.       // forced a client render.
    
  1501.       const recoverableError = createCapturedValueAtFiber<mixed>(
    
  1502.         new Error(
    
  1503.           'There was an error while hydrating. Because the error happened outside ' +
    
  1504.             'of a Suspense boundary, the entire root will switch to ' +
    
  1505.             'client rendering.',
    
  1506.         ),
    
  1507.         workInProgress,
    
  1508.       );
    
  1509.       return mountHostRootWithoutHydrating(
    
  1510.         current,
    
  1511.         workInProgress,
    
  1512.         nextChildren,
    
  1513.         renderLanes,
    
  1514.         recoverableError,
    
  1515.       );
    
  1516.     } else if (nextChildren !== prevChildren) {
    
  1517.       const recoverableError = createCapturedValueAtFiber<mixed>(
    
  1518.         new Error(
    
  1519.           'This root received an early update, before anything was able ' +
    
  1520.             'hydrate. Switched the entire root to client rendering.',
    
  1521.         ),
    
  1522.         workInProgress,
    
  1523.       );
    
  1524.       return mountHostRootWithoutHydrating(
    
  1525.         current,
    
  1526.         workInProgress,
    
  1527.         nextChildren,
    
  1528.         renderLanes,
    
  1529.         recoverableError,
    
  1530.       );
    
  1531.     } else {
    
  1532.       // The outermost shell has not hydrated yet. Start hydrating.
    
  1533.       enterHydrationState(workInProgress);
    
  1534. 
    
  1535.       const child = mountChildFibers(
    
  1536.         workInProgress,
    
  1537.         null,
    
  1538.         nextChildren,
    
  1539.         renderLanes,
    
  1540.       );
    
  1541.       workInProgress.child = child;
    
  1542. 
    
  1543.       let node = child;
    
  1544.       while (node) {
    
  1545.         // Mark each child as hydrating. This is a fast path to know whether this
    
  1546.         // tree is part of a hydrating tree. This is used to determine if a child
    
  1547.         // node has fully mounted yet, and for scheduling event replaying.
    
  1548.         // Conceptually this is similar to Placement in that a new subtree is
    
  1549.         // inserted into the React tree here. It just happens to not need DOM
    
  1550.         // mutations because it already exists.
    
  1551.         node.flags = (node.flags & ~Placement) | Hydrating;
    
  1552.         node = node.sibling;
    
  1553.       }
    
  1554.     }
    
  1555.   } else {
    
  1556.     // Root is not dehydrated. Either this is a client-only root, or it
    
  1557.     // already hydrated.
    
  1558.     resetHydrationState();
    
  1559.     if (nextChildren === prevChildren) {
    
  1560.       return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
    
  1561.     }
    
  1562.     reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1563.   }
    
  1564.   return workInProgress.child;
    
  1565. }
    
  1566. 
    
  1567. function mountHostRootWithoutHydrating(
    
  1568.   current: Fiber,
    
  1569.   workInProgress: Fiber,
    
  1570.   nextChildren: ReactNodeList,
    
  1571.   renderLanes: Lanes,
    
  1572.   recoverableError: CapturedValue<mixed>,
    
  1573. ) {
    
  1574.   // Revert to client rendering.
    
  1575.   resetHydrationState();
    
  1576. 
    
  1577.   queueHydrationError(recoverableError);
    
  1578. 
    
  1579.   workInProgress.flags |= ForceClientRender;
    
  1580. 
    
  1581.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1582.   return workInProgress.child;
    
  1583. }
    
  1584. 
    
  1585. function updateHostComponent(
    
  1586.   current: Fiber | null,
    
  1587.   workInProgress: Fiber,
    
  1588.   renderLanes: Lanes,
    
  1589. ) {
    
  1590.   pushHostContext(workInProgress);
    
  1591. 
    
  1592.   if (current === null) {
    
  1593.     tryToClaimNextHydratableInstance(workInProgress);
    
  1594.   }
    
  1595. 
    
  1596.   const type = workInProgress.type;
    
  1597.   const nextProps = workInProgress.pendingProps;
    
  1598.   const prevProps = current !== null ? current.memoizedProps : null;
    
  1599. 
    
  1600.   let nextChildren = nextProps.children;
    
  1601.   const isDirectTextChild = shouldSetTextContent(type, nextProps);
    
  1602. 
    
  1603.   if (isDirectTextChild) {
    
  1604.     // We special case a direct text child of a host node. This is a common
    
  1605.     // case. We won't handle it as a reified child. We will instead handle
    
  1606.     // this in the host environment that also has access to this prop. That
    
  1607.     // avoids allocating another HostText fiber and traversing it.
    
  1608.     nextChildren = null;
    
  1609.   } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) {
    
  1610.     // If we're switching from a direct text child to a normal child, or to
    
  1611.     // empty, we need to schedule the text content to be reset.
    
  1612.     workInProgress.flags |= ContentReset;
    
  1613.   }
    
  1614. 
    
  1615.   if (enableFormActions && enableAsyncActions) {
    
  1616.     const memoizedState = workInProgress.memoizedState;
    
  1617.     if (memoizedState !== null) {
    
  1618.       // This fiber has been upgraded to a stateful component. The only way
    
  1619.       // happens currently is for form actions. We use hooks to track the
    
  1620.       // pending and error state of the form.
    
  1621.       //
    
  1622.       // Once a fiber is upgraded to be stateful, it remains stateful for the
    
  1623.       // rest of its lifetime.
    
  1624.       const newState = renderTransitionAwareHostComponentWithHooks(
    
  1625.         current,
    
  1626.         workInProgress,
    
  1627.         renderLanes,
    
  1628.       );
    
  1629. 
    
  1630.       // If the transition state changed, propagate the change to all the
    
  1631.       // descendents. We use Context as an implementation detail for this.
    
  1632.       //
    
  1633.       // This is intentionally set here instead of pushHostContext because
    
  1634.       // pushHostContext gets called before we process the state hook, to avoid
    
  1635.       // a state mismatch in the event that something suspends.
    
  1636.       //
    
  1637.       // NOTE: This assumes that there cannot be nested transition providers,
    
  1638.       // because the only renderer that implements this feature is React DOM,
    
  1639.       // and forms cannot be nested. If we did support nested providers, then
    
  1640.       // we would need to push a context value even for host fibers that
    
  1641.       // haven't been upgraded yet.
    
  1642.       if (isPrimaryRenderer) {
    
  1643.         HostTransitionContext._currentValue = newState;
    
  1644.       } else {
    
  1645.         HostTransitionContext._currentValue2 = newState;
    
  1646.       }
    
  1647.       if (enableLazyContextPropagation) {
    
  1648.         // In the lazy propagation implementation, we don't scan for matching
    
  1649.         // consumers until something bails out.
    
  1650.       } else {
    
  1651.         if (didReceiveUpdate) {
    
  1652.           if (current !== null) {
    
  1653.             const oldStateHook: Hook = current.memoizedState;
    
  1654.             const oldState: TransitionStatus = oldStateHook.memoizedState;
    
  1655.             // This uses regular equality instead of Object.is because we assume
    
  1656.             // that host transition state doesn't include NaN as a valid type.
    
  1657.             if (oldState !== newState) {
    
  1658.               propagateContextChange(
    
  1659.                 workInProgress,
    
  1660.                 HostTransitionContext,
    
  1661.                 renderLanes,
    
  1662.               );
    
  1663.             }
    
  1664.           }
    
  1665.         }
    
  1666.       }
    
  1667.     }
    
  1668.   }
    
  1669. 
    
  1670.   markRef(current, workInProgress);
    
  1671.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1672.   return workInProgress.child;
    
  1673. }
    
  1674. 
    
  1675. function updateHostHoistable(
    
  1676.   current: null | Fiber,
    
  1677.   workInProgress: Fiber,
    
  1678.   renderLanes: Lanes,
    
  1679. ) {
    
  1680.   markRef(current, workInProgress);
    
  1681.   const currentProps = current === null ? null : current.memoizedProps;
    
  1682.   const resource = (workInProgress.memoizedState = getResource(
    
  1683.     workInProgress.type,
    
  1684.     currentProps,
    
  1685.     workInProgress.pendingProps,
    
  1686.   ));
    
  1687.   if (current === null) {
    
  1688.     if (!getIsHydrating() && resource === null) {
    
  1689.       // This is not a Resource Hoistable and we aren't hydrating so we construct the instance.
    
  1690.       workInProgress.stateNode = createHoistableInstance(
    
  1691.         workInProgress.type,
    
  1692.         workInProgress.pendingProps,
    
  1693.         getRootHostContainer(),
    
  1694.         workInProgress,
    
  1695.       );
    
  1696.     }
    
  1697.   }
    
  1698. 
    
  1699.   // Resources never have reconciler managed children. It is possible for
    
  1700.   // the host implementation of getResource to consider children in the
    
  1701.   // resource construction but they will otherwise be discarded. In practice
    
  1702.   // this precludes all but the simplest children and Host specific warnings
    
  1703.   // should be implemented to warn when children are passsed when otherwise not
    
  1704.   // expected
    
  1705.   return null;
    
  1706. }
    
  1707. 
    
  1708. function updateHostSingleton(
    
  1709.   current: Fiber | null,
    
  1710.   workInProgress: Fiber,
    
  1711.   renderLanes: Lanes,
    
  1712. ) {
    
  1713.   pushHostContext(workInProgress);
    
  1714. 
    
  1715.   if (current === null) {
    
  1716.     claimHydratableSingleton(workInProgress);
    
  1717.   }
    
  1718. 
    
  1719.   const nextChildren = workInProgress.pendingProps.children;
    
  1720. 
    
  1721.   if (current === null && !getIsHydrating()) {
    
  1722.     // Similar to Portals we append Singleton children in the commit phase. So we
    
  1723.     // Track insertions even on mount.
    
  1724.     // TODO: Consider unifying this with how the root works.
    
  1725.     workInProgress.child = reconcileChildFibers(
    
  1726.       workInProgress,
    
  1727.       null,
    
  1728.       nextChildren,
    
  1729.       renderLanes,
    
  1730.     );
    
  1731.   } else {
    
  1732.     reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  1733.   }
    
  1734.   markRef(current, workInProgress);
    
  1735.   return workInProgress.child;
    
  1736. }
    
  1737. 
    
  1738. function updateHostText(current: null | Fiber, workInProgress: Fiber) {
    
  1739.   if (current === null) {
    
  1740.     tryToClaimNextHydratableTextInstance(workInProgress);
    
  1741.   }
    
  1742.   // Nothing to do here. This is terminal. We'll do the completion step
    
  1743.   // immediately after.
    
  1744.   return null;
    
  1745. }
    
  1746. 
    
  1747. function mountLazyComponent(
    
  1748.   _current: null | Fiber,
    
  1749.   workInProgress: Fiber,
    
  1750.   elementType: any,
    
  1751.   renderLanes: Lanes,
    
  1752. ) {
    
  1753.   resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress);
    
  1754. 
    
  1755.   const props = workInProgress.pendingProps;
    
  1756.   const lazyComponent: LazyComponentType<any, any> = elementType;
    
  1757.   const payload = lazyComponent._payload;
    
  1758.   const init = lazyComponent._init;
    
  1759.   let Component = init(payload);
    
  1760.   // Store the unwrapped component in the type.
    
  1761.   workInProgress.type = Component;
    
  1762.   const resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component));
    
  1763.   const resolvedProps = resolveDefaultProps(Component, props);
    
  1764.   let child;
    
  1765.   switch (resolvedTag) {
    
  1766.     case FunctionComponent: {
    
  1767.       if (__DEV__) {
    
  1768.         validateFunctionComponentInDev(workInProgress, Component);
    
  1769.         workInProgress.type = Component =
    
  1770.           resolveFunctionForHotReloading(Component);
    
  1771.       }
    
  1772.       child = updateFunctionComponent(
    
  1773.         null,
    
  1774.         workInProgress,
    
  1775.         Component,
    
  1776.         resolvedProps,
    
  1777.         renderLanes,
    
  1778.       );
    
  1779.       return child;
    
  1780.     }
    
  1781.     case ClassComponent: {
    
  1782.       if (__DEV__) {
    
  1783.         workInProgress.type = Component =
    
  1784.           resolveClassForHotReloading(Component);
    
  1785.       }
    
  1786.       child = updateClassComponent(
    
  1787.         null,
    
  1788.         workInProgress,
    
  1789.         Component,
    
  1790.         resolvedProps,
    
  1791.         renderLanes,
    
  1792.       );
    
  1793.       return child;
    
  1794.     }
    
  1795.     case ForwardRef: {
    
  1796.       if (__DEV__) {
    
  1797.         workInProgress.type = Component =
    
  1798.           resolveForwardRefForHotReloading(Component);
    
  1799.       }
    
  1800.       child = updateForwardRef(
    
  1801.         null,
    
  1802.         workInProgress,
    
  1803.         Component,
    
  1804.         resolvedProps,
    
  1805.         renderLanes,
    
  1806.       );
    
  1807.       return child;
    
  1808.     }
    
  1809.     case MemoComponent: {
    
  1810.       if (__DEV__) {
    
  1811.         if (workInProgress.type !== workInProgress.elementType) {
    
  1812.           const outerPropTypes = Component.propTypes;
    
  1813.           if (outerPropTypes) {
    
  1814.             checkPropTypes(
    
  1815.               outerPropTypes,
    
  1816.               resolvedProps, // Resolved for outer only
    
  1817.               'prop',
    
  1818.               getComponentNameFromType(Component),
    
  1819.             );
    
  1820.           }
    
  1821.         }
    
  1822.       }
    
  1823.       child = updateMemoComponent(
    
  1824.         null,
    
  1825.         workInProgress,
    
  1826.         Component,
    
  1827.         resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too
    
  1828.         renderLanes,
    
  1829.       );
    
  1830.       return child;
    
  1831.     }
    
  1832.   }
    
  1833.   let hint = '';
    
  1834.   if (__DEV__) {
    
  1835.     if (
    
  1836.       Component !== null &&
    
  1837.       typeof Component === 'object' &&
    
  1838.       Component.$$typeof === REACT_LAZY_TYPE
    
  1839.     ) {
    
  1840.       hint = ' Did you wrap a component in React.lazy() more than once?';
    
  1841.     }
    
  1842.   }
    
  1843. 
    
  1844.   // This message intentionally doesn't mention ForwardRef or MemoComponent
    
  1845.   // because the fact that it's a separate type of work is an
    
  1846.   // implementation detail.
    
  1847.   throw new Error(
    
  1848.     `Element type is invalid. Received a promise that resolves to: ${Component}. ` +
    
  1849.       `Lazy element type must resolve to a class or function.${hint}`,
    
  1850.   );
    
  1851. }
    
  1852. 
    
  1853. function mountIncompleteClassComponent(
    
  1854.   _current: null | Fiber,
    
  1855.   workInProgress: Fiber,
    
  1856.   Component: any,
    
  1857.   nextProps: any,
    
  1858.   renderLanes: Lanes,
    
  1859. ) {
    
  1860.   resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress);
    
  1861. 
    
  1862.   // Promote the fiber to a class and try rendering again.
    
  1863.   workInProgress.tag = ClassComponent;
    
  1864. 
    
  1865.   // The rest of this function is a fork of `updateClassComponent`
    
  1866. 
    
  1867.   // Push context providers early to prevent context stack mismatches.
    
  1868.   // During mounting we don't know the child context yet as the instance doesn't exist.
    
  1869.   // We will invalidate the child context in finishClassComponent() right after rendering.
    
  1870.   let hasContext;
    
  1871.   if (isLegacyContextProvider(Component)) {
    
  1872.     hasContext = true;
    
  1873.     pushLegacyContextProvider(workInProgress);
    
  1874.   } else {
    
  1875.     hasContext = false;
    
  1876.   }
    
  1877.   prepareToReadContext(workInProgress, renderLanes);
    
  1878. 
    
  1879.   constructClassInstance(workInProgress, Component, nextProps);
    
  1880.   mountClassInstance(workInProgress, Component, nextProps, renderLanes);
    
  1881. 
    
  1882.   return finishClassComponent(
    
  1883.     null,
    
  1884.     workInProgress,
    
  1885.     Component,
    
  1886.     true,
    
  1887.     hasContext,
    
  1888.     renderLanes,
    
  1889.   );
    
  1890. }
    
  1891. 
    
  1892. function mountIndeterminateComponent(
    
  1893.   _current: null | Fiber,
    
  1894.   workInProgress: Fiber,
    
  1895.   Component: $FlowFixMe,
    
  1896.   renderLanes: Lanes,
    
  1897. ) {
    
  1898.   resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress);
    
  1899. 
    
  1900.   const props = workInProgress.pendingProps;
    
  1901.   let context;
    
  1902.   if (!disableLegacyContext) {
    
  1903.     const unmaskedContext = getUnmaskedContext(
    
  1904.       workInProgress,
    
  1905.       Component,
    
  1906.       false,
    
  1907.     );
    
  1908.     context = getMaskedContext(workInProgress, unmaskedContext);
    
  1909.   }
    
  1910. 
    
  1911.   prepareToReadContext(workInProgress, renderLanes);
    
  1912.   let value;
    
  1913.   let hasId;
    
  1914. 
    
  1915.   if (enableSchedulingProfiler) {
    
  1916.     markComponentRenderStarted(workInProgress);
    
  1917.   }
    
  1918.   if (__DEV__) {
    
  1919.     if (
    
  1920.       Component.prototype &&
    
  1921.       typeof Component.prototype.render === 'function'
    
  1922.     ) {
    
  1923.       const componentName = getComponentNameFromType(Component) || 'Unknown';
    
  1924. 
    
  1925.       if (!didWarnAboutBadClass[componentName]) {
    
  1926.         console.error(
    
  1927.           "The <%s /> component appears to have a render method, but doesn't extend React.Component. " +
    
  1928.             'This is likely to cause errors. Change %s to extend React.Component instead.',
    
  1929.           componentName,
    
  1930.           componentName,
    
  1931.         );
    
  1932.         didWarnAboutBadClass[componentName] = true;
    
  1933.       }
    
  1934.     }
    
  1935. 
    
  1936.     if (workInProgress.mode & StrictLegacyMode) {
    
  1937.       ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null);
    
  1938.     }
    
  1939. 
    
  1940.     setIsRendering(true);
    
  1941.     ReactCurrentOwner.current = workInProgress;
    
  1942.     value = renderWithHooks(
    
  1943.       null,
    
  1944.       workInProgress,
    
  1945.       Component,
    
  1946.       props,
    
  1947.       context,
    
  1948.       renderLanes,
    
  1949.     );
    
  1950.     hasId = checkDidRenderIdHook();
    
  1951.     setIsRendering(false);
    
  1952.   } else {
    
  1953.     value = renderWithHooks(
    
  1954.       null,
    
  1955.       workInProgress,
    
  1956.       Component,
    
  1957.       props,
    
  1958.       context,
    
  1959.       renderLanes,
    
  1960.     );
    
  1961.     hasId = checkDidRenderIdHook();
    
  1962.   }
    
  1963.   if (enableSchedulingProfiler) {
    
  1964.     markComponentRenderStopped();
    
  1965.   }
    
  1966. 
    
  1967.   // React DevTools reads this flag.
    
  1968.   workInProgress.flags |= PerformedWork;
    
  1969. 
    
  1970.   if (__DEV__) {
    
  1971.     // Support for module components is deprecated and is removed behind a flag.
    
  1972.     // Whether or not it would crash later, we want to show a good message in DEV first.
    
  1973.     if (
    
  1974.       typeof value === 'object' &&
    
  1975.       value !== null &&
    
  1976.       typeof value.render === 'function' &&
    
  1977.       value.$$typeof === undefined
    
  1978.     ) {
    
  1979.       const componentName = getComponentNameFromType(Component) || 'Unknown';
    
  1980.       if (!didWarnAboutModulePatternComponent[componentName]) {
    
  1981.         console.error(
    
  1982.           'The <%s /> component appears to be a function component that returns a class instance. ' +
    
  1983.             'Change %s to a class that extends React.Component instead. ' +
    
  1984.             "If you can't use a class try assigning the prototype on the function as a workaround. " +
    
  1985.             "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " +
    
  1986.             'cannot be called with `new` by React.',
    
  1987.           componentName,
    
  1988.           componentName,
    
  1989.           componentName,
    
  1990.         );
    
  1991.         didWarnAboutModulePatternComponent[componentName] = true;
    
  1992.       }
    
  1993.     }
    
  1994.   }
    
  1995. 
    
  1996.   if (
    
  1997.     // Run these checks in production only if the flag is off.
    
  1998.     // Eventually we'll delete this branch altogether.
    
  1999.     !disableModulePatternComponents &&
    
  2000.     typeof value === 'object' &&
    
  2001.     value !== null &&
    
  2002.     typeof value.render === 'function' &&
    
  2003.     value.$$typeof === undefined
    
  2004.   ) {
    
  2005.     if (__DEV__) {
    
  2006.       const componentName = getComponentNameFromType(Component) || 'Unknown';
    
  2007.       if (!didWarnAboutModulePatternComponent[componentName]) {
    
  2008.         console.error(
    
  2009.           'The <%s /> component appears to be a function component that returns a class instance. ' +
    
  2010.             'Change %s to a class that extends React.Component instead. ' +
    
  2011.             "If you can't use a class try assigning the prototype on the function as a workaround. " +
    
  2012.             "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " +
    
  2013.             'cannot be called with `new` by React.',
    
  2014.           componentName,
    
  2015.           componentName,
    
  2016.           componentName,
    
  2017.         );
    
  2018.         didWarnAboutModulePatternComponent[componentName] = true;
    
  2019.       }
    
  2020.     }
    
  2021. 
    
  2022.     // Proceed under the assumption that this is a class instance
    
  2023.     workInProgress.tag = ClassComponent;
    
  2024. 
    
  2025.     // Throw out any hooks that were used.
    
  2026.     workInProgress.memoizedState = null;
    
  2027.     workInProgress.updateQueue = null;
    
  2028. 
    
  2029.     // Push context providers early to prevent context stack mismatches.
    
  2030.     // During mounting we don't know the child context yet as the instance doesn't exist.
    
  2031.     // We will invalidate the child context in finishClassComponent() right after rendering.
    
  2032.     let hasContext = false;
    
  2033.     if (isLegacyContextProvider(Component)) {
    
  2034.       hasContext = true;
    
  2035.       pushLegacyContextProvider(workInProgress);
    
  2036.     } else {
    
  2037.       hasContext = false;
    
  2038.     }
    
  2039. 
    
  2040.     workInProgress.memoizedState =
    
  2041.       value.state !== null && value.state !== undefined ? value.state : null;
    
  2042. 
    
  2043.     initializeUpdateQueue(workInProgress);
    
  2044. 
    
  2045.     adoptClassInstance(workInProgress, value);
    
  2046.     mountClassInstance(workInProgress, Component, props, renderLanes);
    
  2047.     return finishClassComponent(
    
  2048.       null,
    
  2049.       workInProgress,
    
  2050.       Component,
    
  2051.       true,
    
  2052.       hasContext,
    
  2053.       renderLanes,
    
  2054.     );
    
  2055.   } else {
    
  2056.     // Proceed under the assumption that this is a function component
    
  2057.     workInProgress.tag = FunctionComponent;
    
  2058.     if (__DEV__) {
    
  2059.       if (disableLegacyContext && Component.contextTypes) {
    
  2060.         console.error(
    
  2061.           '%s uses the legacy contextTypes API which is no longer supported. ' +
    
  2062.             'Use React.createContext() with React.useContext() instead.',
    
  2063.           getComponentNameFromType(Component) || 'Unknown',
    
  2064.         );
    
  2065.       }
    
  2066.     }
    
  2067. 
    
  2068.     if (getIsHydrating() && hasId) {
    
  2069.       pushMaterializedTreeId(workInProgress);
    
  2070.     }
    
  2071. 
    
  2072.     reconcileChildren(null, workInProgress, value, renderLanes);
    
  2073.     if (__DEV__) {
    
  2074.       validateFunctionComponentInDev(workInProgress, Component);
    
  2075.     }
    
  2076.     return workInProgress.child;
    
  2077.   }
    
  2078. }
    
  2079. 
    
  2080. function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {
    
  2081.   if (__DEV__) {
    
  2082.     if (Component) {
    
  2083.       if (Component.childContextTypes) {
    
  2084.         console.error(
    
  2085.           '%s(...): childContextTypes cannot be defined on a function component.',
    
  2086.           Component.displayName || Component.name || 'Component',
    
  2087.         );
    
  2088.       }
    
  2089.     }
    
  2090.     if (workInProgress.ref !== null) {
    
  2091.       let info = '';
    
  2092.       const ownerName = getCurrentFiberOwnerNameInDevOrNull();
    
  2093.       if (ownerName) {
    
  2094.         info += '\n\nCheck the render method of `' + ownerName + '`.';
    
  2095.       }
    
  2096. 
    
  2097.       let warningKey = ownerName || '';
    
  2098.       const debugSource = workInProgress._debugSource;
    
  2099.       if (debugSource) {
    
  2100.         warningKey = debugSource.fileName + ':' + debugSource.lineNumber;
    
  2101.       }
    
  2102.       if (!didWarnAboutFunctionRefs[warningKey]) {
    
  2103.         didWarnAboutFunctionRefs[warningKey] = true;
    
  2104.         console.error(
    
  2105.           'Function components cannot be given refs. ' +
    
  2106.             'Attempts to access this ref will fail. ' +
    
  2107.             'Did you mean to use React.forwardRef()?%s',
    
  2108.           info,
    
  2109.         );
    
  2110.       }
    
  2111.     }
    
  2112. 
    
  2113.     if (Component.defaultProps !== undefined) {
    
  2114.       const componentName = getComponentNameFromType(Component) || 'Unknown';
    
  2115. 
    
  2116.       if (!didWarnAboutDefaultPropsOnFunctionComponent[componentName]) {
    
  2117.         console.error(
    
  2118.           '%s: Support for defaultProps will be removed from function components ' +
    
  2119.             'in a future major release. Use JavaScript default parameters instead.',
    
  2120.           componentName,
    
  2121.         );
    
  2122.         didWarnAboutDefaultPropsOnFunctionComponent[componentName] = true;
    
  2123.       }
    
  2124.     }
    
  2125. 
    
  2126.     if (typeof Component.getDerivedStateFromProps === 'function') {
    
  2127.       const componentName = getComponentNameFromType(Component) || 'Unknown';
    
  2128. 
    
  2129.       if (!didWarnAboutGetDerivedStateOnFunctionComponent[componentName]) {
    
  2130.         console.error(
    
  2131.           '%s: Function components do not support getDerivedStateFromProps.',
    
  2132.           componentName,
    
  2133.         );
    
  2134.         didWarnAboutGetDerivedStateOnFunctionComponent[componentName] = true;
    
  2135.       }
    
  2136.     }
    
  2137. 
    
  2138.     if (
    
  2139.       typeof Component.contextType === 'object' &&
    
  2140.       Component.contextType !== null
    
  2141.     ) {
    
  2142.       const componentName = getComponentNameFromType(Component) || 'Unknown';
    
  2143. 
    
  2144.       if (!didWarnAboutContextTypeOnFunctionComponent[componentName]) {
    
  2145.         console.error(
    
  2146.           '%s: Function components do not support contextType.',
    
  2147.           componentName,
    
  2148.         );
    
  2149.         didWarnAboutContextTypeOnFunctionComponent[componentName] = true;
    
  2150.       }
    
  2151.     }
    
  2152.   }
    
  2153. }
    
  2154. 
    
  2155. const SUSPENDED_MARKER: SuspenseState = {
    
  2156.   dehydrated: null,
    
  2157.   treeContext: null,
    
  2158.   retryLane: NoLane,
    
  2159. };
    
  2160. 
    
  2161. function mountSuspenseOffscreenState(renderLanes: Lanes): OffscreenState {
    
  2162.   return {
    
  2163.     baseLanes: renderLanes,
    
  2164.     cachePool: getSuspendedCache(),
    
  2165.   };
    
  2166. }
    
  2167. 
    
  2168. function updateSuspenseOffscreenState(
    
  2169.   prevOffscreenState: OffscreenState,
    
  2170.   renderLanes: Lanes,
    
  2171. ): OffscreenState {
    
  2172.   let cachePool: SpawnedCachePool | null = null;
    
  2173.   if (enableCache) {
    
  2174.     const prevCachePool: SpawnedCachePool | null = prevOffscreenState.cachePool;
    
  2175.     if (prevCachePool !== null) {
    
  2176.       const parentCache = isPrimaryRenderer
    
  2177.         ? CacheContext._currentValue
    
  2178.         : CacheContext._currentValue2;
    
  2179.       if (prevCachePool.parent !== parentCache) {
    
  2180.         // Detected a refresh in the parent. This overrides any previously
    
  2181.         // suspended cache.
    
  2182.         cachePool = {
    
  2183.           parent: parentCache,
    
  2184.           pool: parentCache,
    
  2185.         };
    
  2186.       } else {
    
  2187.         // We can reuse the cache from last time. The only thing that would have
    
  2188.         // overridden it is a parent refresh, which we checked for above.
    
  2189.         cachePool = prevCachePool;
    
  2190.       }
    
  2191.     } else {
    
  2192.       // If there's no previous cache pool, grab the current one.
    
  2193.       cachePool = getSuspendedCache();
    
  2194.     }
    
  2195.   }
    
  2196.   return {
    
  2197.     baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes),
    
  2198.     cachePool,
    
  2199.   };
    
  2200. }
    
  2201. 
    
  2202. // TODO: Probably should inline this back
    
  2203. function shouldRemainOnFallback(
    
  2204.   current: null | Fiber,
    
  2205.   workInProgress: Fiber,
    
  2206.   renderLanes: Lanes,
    
  2207. ) {
    
  2208.   // If we're already showing a fallback, there are cases where we need to
    
  2209.   // remain on that fallback regardless of whether the content has resolved.
    
  2210.   // For example, SuspenseList coordinates when nested content appears.
    
  2211.   // TODO: For compatibility with offscreen prerendering, this should also check
    
  2212.   // whether the current fiber (if it exists) was visible in the previous tree.
    
  2213.   if (current !== null) {
    
  2214.     const suspenseState: SuspenseState = current.memoizedState;
    
  2215.     if (suspenseState === null) {
    
  2216.       // Currently showing content. Don't hide it, even if ForceSuspenseFallback
    
  2217.       // is true. More precise name might be "ForceRemainSuspenseFallback".
    
  2218.       // Note: This is a factoring smell. Can't remain on a fallback if there's
    
  2219.       // no fallback to remain on.
    
  2220.       return false;
    
  2221.     }
    
  2222.   }
    
  2223. 
    
  2224.   // Not currently showing content. Consult the Suspense context.
    
  2225.   const suspenseContext: SuspenseContext = suspenseStackCursor.current;
    
  2226.   return hasSuspenseListContext(
    
  2227.     suspenseContext,
    
  2228.     (ForceSuspenseFallback: SuspenseContext),
    
  2229.   );
    
  2230. }
    
  2231. 
    
  2232. function getRemainingWorkInPrimaryTree(current: Fiber, renderLanes: Lanes) {
    
  2233.   // TODO: Should not remove render lanes that were pinged during this render
    
  2234.   return removeLanes(current.childLanes, renderLanes);
    
  2235. }
    
  2236. 
    
  2237. function updateSuspenseComponent(
    
  2238.   current: null | Fiber,
    
  2239.   workInProgress: Fiber,
    
  2240.   renderLanes: Lanes,
    
  2241. ) {
    
  2242.   const nextProps = workInProgress.pendingProps;
    
  2243. 
    
  2244.   // This is used by DevTools to force a boundary to suspend.
    
  2245.   if (__DEV__) {
    
  2246.     if (shouldSuspend(workInProgress)) {
    
  2247.       workInProgress.flags |= DidCapture;
    
  2248.     }
    
  2249.   }
    
  2250. 
    
  2251.   let showFallback = false;
    
  2252.   const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;
    
  2253.   if (
    
  2254.     didSuspend ||
    
  2255.     shouldRemainOnFallback(current, workInProgress, renderLanes)
    
  2256.   ) {
    
  2257.     // Something in this boundary's subtree already suspended. Switch to
    
  2258.     // rendering the fallback children.
    
  2259.     showFallback = true;
    
  2260.     workInProgress.flags &= ~DidCapture;
    
  2261.   }
    
  2262. 
    
  2263.   // OK, the next part is confusing. We're about to reconcile the Suspense
    
  2264.   // boundary's children. This involves some custom reconciliation logic. Two
    
  2265.   // main reasons this is so complicated.
    
  2266.   //
    
  2267.   // First, Legacy Mode has different semantics for backwards compatibility. The
    
  2268.   // primary tree will commit in an inconsistent state, so when we do the
    
  2269.   // second pass to render the fallback, we do some exceedingly, uh, clever
    
  2270.   // hacks to make that not totally break. Like transferring effects and
    
  2271.   // deletions from hidden tree. In Concurrent Mode, it's much simpler,
    
  2272.   // because we bailout on the primary tree completely and leave it in its old
    
  2273.   // state, no effects. Same as what we do for Offscreen (except that
    
  2274.   // Offscreen doesn't have the first render pass).
    
  2275.   //
    
  2276.   // Second is hydration. During hydration, the Suspense fiber has a slightly
    
  2277.   // different layout, where the child points to a dehydrated fragment, which
    
  2278.   // contains the DOM rendered by the server.
    
  2279.   //
    
  2280.   // Third, even if you set all that aside, Suspense is like error boundaries in
    
  2281.   // that we first we try to render one tree, and if that fails, we render again
    
  2282.   // and switch to a different tree. Like a try/catch block. So we have to track
    
  2283.   // which branch we're currently rendering. Ideally we would model this using
    
  2284.   // a stack.
    
  2285.   if (current === null) {
    
  2286.     // Initial mount
    
  2287. 
    
  2288.     // Special path for hydration
    
  2289.     // If we're currently hydrating, try to hydrate this boundary.
    
  2290.     if (getIsHydrating()) {
    
  2291.       // We must push the suspense handler context *before* attempting to
    
  2292.       // hydrate, to avoid a mismatch in case it errors.
    
  2293.       if (showFallback) {
    
  2294.         pushPrimaryTreeSuspenseHandler(workInProgress);
    
  2295.       } else {
    
  2296.         pushFallbackTreeSuspenseHandler(workInProgress);
    
  2297.       }
    
  2298.       tryToClaimNextHydratableSuspenseInstance(workInProgress);
    
  2299.       // This could've been a dehydrated suspense component.
    
  2300.       const suspenseState: null | SuspenseState = workInProgress.memoizedState;
    
  2301.       if (suspenseState !== null) {
    
  2302.         const dehydrated = suspenseState.dehydrated;
    
  2303.         if (dehydrated !== null) {
    
  2304.           return mountDehydratedSuspenseComponent(
    
  2305.             workInProgress,
    
  2306.             dehydrated,
    
  2307.             renderLanes,
    
  2308.           );
    
  2309.         }
    
  2310.       }
    
  2311.       // If hydration didn't succeed, fall through to the normal Suspense path.
    
  2312.       // To avoid a stack mismatch we need to pop the Suspense handler that we
    
  2313.       // pushed above. This will become less awkward when move the hydration
    
  2314.       // logic to its own fiber.
    
  2315.       popSuspenseHandler(workInProgress);
    
  2316.     }
    
  2317. 
    
  2318.     const nextPrimaryChildren = nextProps.children;
    
  2319.     const nextFallbackChildren = nextProps.fallback;
    
  2320. 
    
  2321.     if (showFallback) {
    
  2322.       pushFallbackTreeSuspenseHandler(workInProgress);
    
  2323. 
    
  2324.       const fallbackFragment = mountSuspenseFallbackChildren(
    
  2325.         workInProgress,
    
  2326.         nextPrimaryChildren,
    
  2327.         nextFallbackChildren,
    
  2328.         renderLanes,
    
  2329.       );
    
  2330.       const primaryChildFragment: Fiber = (workInProgress.child: any);
    
  2331.       primaryChildFragment.memoizedState =
    
  2332.         mountSuspenseOffscreenState(renderLanes);
    
  2333.       workInProgress.memoizedState = SUSPENDED_MARKER;
    
  2334.       if (enableTransitionTracing) {
    
  2335.         const currentTransitions = getPendingTransitions();
    
  2336.         if (currentTransitions !== null) {
    
  2337.           const parentMarkerInstances = getMarkerInstances();
    
  2338.           const offscreenQueue: OffscreenQueue | null =
    
  2339.             (primaryChildFragment.updateQueue: any);
    
  2340.           if (offscreenQueue === null) {
    
  2341.             const newOffscreenQueue: OffscreenQueue = {
    
  2342.               transitions: currentTransitions,
    
  2343.               markerInstances: parentMarkerInstances,
    
  2344.               retryQueue: null,
    
  2345.             };
    
  2346.             primaryChildFragment.updateQueue = newOffscreenQueue;
    
  2347.           } else {
    
  2348.             offscreenQueue.transitions = currentTransitions;
    
  2349.             offscreenQueue.markerInstances = parentMarkerInstances;
    
  2350.           }
    
  2351.         }
    
  2352.       }
    
  2353. 
    
  2354.       return fallbackFragment;
    
  2355.     } else if (
    
  2356.       enableCPUSuspense &&
    
  2357.       typeof nextProps.unstable_expectedLoadTime === 'number'
    
  2358.     ) {
    
  2359.       // This is a CPU-bound tree. Skip this tree and show a placeholder to
    
  2360.       // unblock the surrounding content. Then immediately retry after the
    
  2361.       // initial commit.
    
  2362.       pushFallbackTreeSuspenseHandler(workInProgress);
    
  2363.       const fallbackFragment = mountSuspenseFallbackChildren(
    
  2364.         workInProgress,
    
  2365.         nextPrimaryChildren,
    
  2366.         nextFallbackChildren,
    
  2367.         renderLanes,
    
  2368.       );
    
  2369.       const primaryChildFragment: Fiber = (workInProgress.child: any);
    
  2370.       primaryChildFragment.memoizedState =
    
  2371.         mountSuspenseOffscreenState(renderLanes);
    
  2372.       workInProgress.memoizedState = SUSPENDED_MARKER;
    
  2373. 
    
  2374.       // TODO: Transition Tracing is not yet implemented for CPU Suspense.
    
  2375. 
    
  2376.       // Since nothing actually suspended, there will nothing to ping this to
    
  2377.       // get it started back up to attempt the next item. While in terms of
    
  2378.       // priority this work has the same priority as this current render, it's
    
  2379.       // not part of the same transition once the transition has committed. If
    
  2380.       // it's sync, we still want to yield so that it can be painted.
    
  2381.       // Conceptually, this is really the same as pinging. We can use any
    
  2382.       // RetryLane even if it's the one currently rendering since we're leaving
    
  2383.       // it behind on this node.
    
  2384.       workInProgress.lanes = SomeRetryLane;
    
  2385.       return fallbackFragment;
    
  2386.     } else {
    
  2387.       pushPrimaryTreeSuspenseHandler(workInProgress);
    
  2388.       return mountSuspensePrimaryChildren(
    
  2389.         workInProgress,
    
  2390.         nextPrimaryChildren,
    
  2391.         renderLanes,
    
  2392.       );
    
  2393.     }
    
  2394.   } else {
    
  2395.     // This is an update.
    
  2396. 
    
  2397.     // Special path for hydration
    
  2398.     const prevState: null | SuspenseState = current.memoizedState;
    
  2399.     if (prevState !== null) {
    
  2400.       const dehydrated = prevState.dehydrated;
    
  2401.       if (dehydrated !== null) {
    
  2402.         return updateDehydratedSuspenseComponent(
    
  2403.           current,
    
  2404.           workInProgress,
    
  2405.           didSuspend,
    
  2406.           nextProps,
    
  2407.           dehydrated,
    
  2408.           prevState,
    
  2409.           renderLanes,
    
  2410.         );
    
  2411.       }
    
  2412.     }
    
  2413. 
    
  2414.     if (showFallback) {
    
  2415.       pushFallbackTreeSuspenseHandler(workInProgress);
    
  2416. 
    
  2417.       const nextFallbackChildren = nextProps.fallback;
    
  2418.       const nextPrimaryChildren = nextProps.children;
    
  2419.       const fallbackChildFragment = updateSuspenseFallbackChildren(
    
  2420.         current,
    
  2421.         workInProgress,
    
  2422.         nextPrimaryChildren,
    
  2423.         nextFallbackChildren,
    
  2424.         renderLanes,
    
  2425.       );
    
  2426.       const primaryChildFragment: Fiber = (workInProgress.child: any);
    
  2427.       const prevOffscreenState: OffscreenState | null = (current.child: any)
    
  2428.         .memoizedState;
    
  2429.       primaryChildFragment.memoizedState =
    
  2430.         prevOffscreenState === null
    
  2431.           ? mountSuspenseOffscreenState(renderLanes)
    
  2432.           : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);
    
  2433.       if (enableTransitionTracing) {
    
  2434.         const currentTransitions = getPendingTransitions();
    
  2435.         if (currentTransitions !== null) {
    
  2436.           const parentMarkerInstances = getMarkerInstances();
    
  2437.           const offscreenQueue: OffscreenQueue | null =
    
  2438.             (primaryChildFragment.updateQueue: any);
    
  2439.           const currentOffscreenQueue: OffscreenQueue | null =
    
  2440.             (current.updateQueue: any);
    
  2441.           if (offscreenQueue === null) {
    
  2442.             const newOffscreenQueue: OffscreenQueue = {
    
  2443.               transitions: currentTransitions,
    
  2444.               markerInstances: parentMarkerInstances,
    
  2445.               retryQueue: null,
    
  2446.             };
    
  2447.             primaryChildFragment.updateQueue = newOffscreenQueue;
    
  2448.           } else if (offscreenQueue === currentOffscreenQueue) {
    
  2449.             // If the work-in-progress queue is the same object as current, we
    
  2450.             // can't modify it without cloning it first.
    
  2451.             const newOffscreenQueue: OffscreenQueue = {
    
  2452.               transitions: currentTransitions,
    
  2453.               markerInstances: parentMarkerInstances,
    
  2454.               retryQueue:
    
  2455.                 currentOffscreenQueue !== null
    
  2456.                   ? currentOffscreenQueue.retryQueue
    
  2457.                   : null,
    
  2458.             };
    
  2459.             primaryChildFragment.updateQueue = newOffscreenQueue;
    
  2460.           } else {
    
  2461.             offscreenQueue.transitions = currentTransitions;
    
  2462.             offscreenQueue.markerInstances = parentMarkerInstances;
    
  2463.           }
    
  2464.         }
    
  2465.       }
    
  2466.       primaryChildFragment.childLanes = getRemainingWorkInPrimaryTree(
    
  2467.         current,
    
  2468.         renderLanes,
    
  2469.       );
    
  2470.       workInProgress.memoizedState = SUSPENDED_MARKER;
    
  2471.       return fallbackChildFragment;
    
  2472.     } else {
    
  2473.       pushPrimaryTreeSuspenseHandler(workInProgress);
    
  2474. 
    
  2475.       const nextPrimaryChildren = nextProps.children;
    
  2476.       const primaryChildFragment = updateSuspensePrimaryChildren(
    
  2477.         current,
    
  2478.         workInProgress,
    
  2479.         nextPrimaryChildren,
    
  2480.         renderLanes,
    
  2481.       );
    
  2482.       workInProgress.memoizedState = null;
    
  2483.       return primaryChildFragment;
    
  2484.     }
    
  2485.   }
    
  2486. }
    
  2487. 
    
  2488. function mountSuspensePrimaryChildren(
    
  2489.   workInProgress: Fiber,
    
  2490.   primaryChildren: $FlowFixMe,
    
  2491.   renderLanes: Lanes,
    
  2492. ) {
    
  2493.   const mode = workInProgress.mode;
    
  2494.   const primaryChildProps: OffscreenProps = {
    
  2495.     mode: 'visible',
    
  2496.     children: primaryChildren,
    
  2497.   };
    
  2498.   const primaryChildFragment = mountWorkInProgressOffscreenFiber(
    
  2499.     primaryChildProps,
    
  2500.     mode,
    
  2501.     renderLanes,
    
  2502.   );
    
  2503.   primaryChildFragment.return = workInProgress;
    
  2504.   workInProgress.child = primaryChildFragment;
    
  2505.   return primaryChildFragment;
    
  2506. }
    
  2507. 
    
  2508. function mountSuspenseFallbackChildren(
    
  2509.   workInProgress: Fiber,
    
  2510.   primaryChildren: $FlowFixMe,
    
  2511.   fallbackChildren: $FlowFixMe,
    
  2512.   renderLanes: Lanes,
    
  2513. ) {
    
  2514.   const mode = workInProgress.mode;
    
  2515.   const progressedPrimaryFragment: Fiber | null = workInProgress.child;
    
  2516. 
    
  2517.   const primaryChildProps: OffscreenProps = {
    
  2518.     mode: 'hidden',
    
  2519.     children: primaryChildren,
    
  2520.   };
    
  2521. 
    
  2522.   let primaryChildFragment;
    
  2523.   let fallbackChildFragment;
    
  2524.   if (
    
  2525.     (mode & ConcurrentMode) === NoMode &&
    
  2526.     progressedPrimaryFragment !== null
    
  2527.   ) {
    
  2528.     // In legacy mode, we commit the primary tree as if it successfully
    
  2529.     // completed, even though it's in an inconsistent state.
    
  2530.     primaryChildFragment = progressedPrimaryFragment;
    
  2531.     primaryChildFragment.childLanes = NoLanes;
    
  2532.     primaryChildFragment.pendingProps = primaryChildProps;
    
  2533. 
    
  2534.     if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
    
  2535.       // Reset the durations from the first pass so they aren't included in the
    
  2536.       // final amounts. This seems counterintuitive, since we're intentionally
    
  2537.       // not measuring part of the render phase, but this makes it match what we
    
  2538.       // do in Concurrent Mode.
    
  2539.       primaryChildFragment.actualDuration = 0;
    
  2540.       primaryChildFragment.actualStartTime = -1;
    
  2541.       primaryChildFragment.selfBaseDuration = 0;
    
  2542.       primaryChildFragment.treeBaseDuration = 0;
    
  2543.     }
    
  2544. 
    
  2545.     fallbackChildFragment = createFiberFromFragment(
    
  2546.       fallbackChildren,
    
  2547.       mode,
    
  2548.       renderLanes,
    
  2549.       null,
    
  2550.     );
    
  2551.   } else {
    
  2552.     primaryChildFragment = mountWorkInProgressOffscreenFiber(
    
  2553.       primaryChildProps,
    
  2554.       mode,
    
  2555.       NoLanes,
    
  2556.     );
    
  2557.     fallbackChildFragment = createFiberFromFragment(
    
  2558.       fallbackChildren,
    
  2559.       mode,
    
  2560.       renderLanes,
    
  2561.       null,
    
  2562.     );
    
  2563.   }
    
  2564. 
    
  2565.   primaryChildFragment.return = workInProgress;
    
  2566.   fallbackChildFragment.return = workInProgress;
    
  2567.   primaryChildFragment.sibling = fallbackChildFragment;
    
  2568.   workInProgress.child = primaryChildFragment;
    
  2569.   return fallbackChildFragment;
    
  2570. }
    
  2571. 
    
  2572. function mountWorkInProgressOffscreenFiber(
    
  2573.   offscreenProps: OffscreenProps,
    
  2574.   mode: TypeOfMode,
    
  2575.   renderLanes: Lanes,
    
  2576. ) {
    
  2577.   // The props argument to `createFiberFromOffscreen` is `any` typed, so we use
    
  2578.   // this wrapper function to constrain it.
    
  2579.   return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null);
    
  2580. }
    
  2581. 
    
  2582. function updateWorkInProgressOffscreenFiber(
    
  2583.   current: Fiber,
    
  2584.   offscreenProps: OffscreenProps,
    
  2585. ) {
    
  2586.   // The props argument to `createWorkInProgress` is `any` typed, so we use this
    
  2587.   // wrapper function to constrain it.
    
  2588.   return createWorkInProgress(current, offscreenProps);
    
  2589. }
    
  2590. 
    
  2591. function updateSuspensePrimaryChildren(
    
  2592.   current: Fiber,
    
  2593.   workInProgress: Fiber,
    
  2594.   primaryChildren: $FlowFixMe,
    
  2595.   renderLanes: Lanes,
    
  2596. ) {
    
  2597.   const currentPrimaryChildFragment: Fiber = (current.child: any);
    
  2598.   const currentFallbackChildFragment: Fiber | null =
    
  2599.     currentPrimaryChildFragment.sibling;
    
  2600. 
    
  2601.   const primaryChildFragment = updateWorkInProgressOffscreenFiber(
    
  2602.     currentPrimaryChildFragment,
    
  2603.     {
    
  2604.       mode: 'visible',
    
  2605.       children: primaryChildren,
    
  2606.     },
    
  2607.   );
    
  2608.   if ((workInProgress.mode & ConcurrentMode) === NoMode) {
    
  2609.     primaryChildFragment.lanes = renderLanes;
    
  2610.   }
    
  2611.   primaryChildFragment.return = workInProgress;
    
  2612.   primaryChildFragment.sibling = null;
    
  2613.   if (currentFallbackChildFragment !== null) {
    
  2614.     // Delete the fallback child fragment
    
  2615.     const deletions = workInProgress.deletions;
    
  2616.     if (deletions === null) {
    
  2617.       workInProgress.deletions = [currentFallbackChildFragment];
    
  2618.       workInProgress.flags |= ChildDeletion;
    
  2619.     } else {
    
  2620.       deletions.push(currentFallbackChildFragment);
    
  2621.     }
    
  2622.   }
    
  2623. 
    
  2624.   workInProgress.child = primaryChildFragment;
    
  2625.   return primaryChildFragment;
    
  2626. }
    
  2627. 
    
  2628. function updateSuspenseFallbackChildren(
    
  2629.   current: Fiber,
    
  2630.   workInProgress: Fiber,
    
  2631.   primaryChildren: $FlowFixMe,
    
  2632.   fallbackChildren: $FlowFixMe,
    
  2633.   renderLanes: Lanes,
    
  2634. ) {
    
  2635.   const mode = workInProgress.mode;
    
  2636.   const currentPrimaryChildFragment: Fiber = (current.child: any);
    
  2637.   const currentFallbackChildFragment: Fiber | null =
    
  2638.     currentPrimaryChildFragment.sibling;
    
  2639. 
    
  2640.   const primaryChildProps: OffscreenProps = {
    
  2641.     mode: 'hidden',
    
  2642.     children: primaryChildren,
    
  2643.   };
    
  2644. 
    
  2645.   let primaryChildFragment;
    
  2646.   if (
    
  2647.     // In legacy mode, we commit the primary tree as if it successfully
    
  2648.     // completed, even though it's in an inconsistent state.
    
  2649.     (mode & ConcurrentMode) === NoMode &&
    
  2650.     // Make sure we're on the second pass, i.e. the primary child fragment was
    
  2651.     // already cloned. In legacy mode, the only case where this isn't true is
    
  2652.     // when DevTools forces us to display a fallback; we skip the first render
    
  2653.     // pass entirely and go straight to rendering the fallback. (In Concurrent
    
  2654.     // Mode, SuspenseList can also trigger this scenario, but this is a legacy-
    
  2655.     // only codepath.)
    
  2656.     workInProgress.child !== currentPrimaryChildFragment
    
  2657.   ) {
    
  2658.     const progressedPrimaryFragment: Fiber = (workInProgress.child: any);
    
  2659.     primaryChildFragment = progressedPrimaryFragment;
    
  2660.     primaryChildFragment.childLanes = NoLanes;
    
  2661.     primaryChildFragment.pendingProps = primaryChildProps;
    
  2662. 
    
  2663.     if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
    
  2664.       // Reset the durations from the first pass so they aren't included in the
    
  2665.       // final amounts. This seems counterintuitive, since we're intentionally
    
  2666.       // not measuring part of the render phase, but this makes it match what we
    
  2667.       // do in Concurrent Mode.
    
  2668.       primaryChildFragment.actualDuration = 0;
    
  2669.       primaryChildFragment.actualStartTime = -1;
    
  2670.       primaryChildFragment.selfBaseDuration =
    
  2671.         currentPrimaryChildFragment.selfBaseDuration;
    
  2672.       primaryChildFragment.treeBaseDuration =
    
  2673.         currentPrimaryChildFragment.treeBaseDuration;
    
  2674.     }
    
  2675. 
    
  2676.     // The fallback fiber was added as a deletion during the first pass.
    
  2677.     // However, since we're going to remain on the fallback, we no longer want
    
  2678.     // to delete it.
    
  2679.     workInProgress.deletions = null;
    
  2680.   } else {
    
  2681.     primaryChildFragment = updateWorkInProgressOffscreenFiber(
    
  2682.       currentPrimaryChildFragment,
    
  2683.       primaryChildProps,
    
  2684.     );
    
  2685.     // Since we're reusing a current tree, we need to reuse the flags, too.
    
  2686.     // (We don't do this in legacy mode, because in legacy mode we don't re-use
    
  2687.     // the current tree; see previous branch.)
    
  2688.     primaryChildFragment.subtreeFlags =
    
  2689.       currentPrimaryChildFragment.subtreeFlags & StaticMask;
    
  2690.   }
    
  2691.   let fallbackChildFragment;
    
  2692.   if (currentFallbackChildFragment !== null) {
    
  2693.     fallbackChildFragment = createWorkInProgress(
    
  2694.       currentFallbackChildFragment,
    
  2695.       fallbackChildren,
    
  2696.     );
    
  2697.   } else {
    
  2698.     fallbackChildFragment = createFiberFromFragment(
    
  2699.       fallbackChildren,
    
  2700.       mode,
    
  2701.       renderLanes,
    
  2702.       null,
    
  2703.     );
    
  2704.     // Needs a placement effect because the parent (the Suspense boundary) already
    
  2705.     // mounted but this is a new fiber.
    
  2706.     fallbackChildFragment.flags |= Placement;
    
  2707.   }
    
  2708. 
    
  2709.   fallbackChildFragment.return = workInProgress;
    
  2710.   primaryChildFragment.return = workInProgress;
    
  2711.   primaryChildFragment.sibling = fallbackChildFragment;
    
  2712.   workInProgress.child = primaryChildFragment;
    
  2713. 
    
  2714.   return fallbackChildFragment;
    
  2715. }
    
  2716. 
    
  2717. function retrySuspenseComponentWithoutHydrating(
    
  2718.   current: Fiber,
    
  2719.   workInProgress: Fiber,
    
  2720.   renderLanes: Lanes,
    
  2721.   recoverableError: CapturedValue<mixed> | null,
    
  2722. ) {
    
  2723.   // Falling back to client rendering. Because this has performance
    
  2724.   // implications, it's considered a recoverable error, even though the user
    
  2725.   // likely won't observe anything wrong with the UI.
    
  2726.   //
    
  2727.   // The error is passed in as an argument to enforce that every caller provide
    
  2728.   // a custom message, or explicitly opt out (currently the only path that opts
    
  2729.   // out is legacy mode; every concurrent path provides an error).
    
  2730.   if (recoverableError !== null) {
    
  2731.     queueHydrationError(recoverableError);
    
  2732.   }
    
  2733. 
    
  2734.   // This will add the old fiber to the deletion list
    
  2735.   reconcileChildFibers(workInProgress, current.child, null, renderLanes);
    
  2736. 
    
  2737.   // We're now not suspended nor dehydrated.
    
  2738.   const nextProps = workInProgress.pendingProps;
    
  2739.   const primaryChildren = nextProps.children;
    
  2740.   const primaryChildFragment = mountSuspensePrimaryChildren(
    
  2741.     workInProgress,
    
  2742.     primaryChildren,
    
  2743.     renderLanes,
    
  2744.   );
    
  2745.   // Needs a placement effect because the parent (the Suspense boundary) already
    
  2746.   // mounted but this is a new fiber.
    
  2747.   primaryChildFragment.flags |= Placement;
    
  2748.   workInProgress.memoizedState = null;
    
  2749. 
    
  2750.   return primaryChildFragment;
    
  2751. }
    
  2752. 
    
  2753. function mountSuspenseFallbackAfterRetryWithoutHydrating(
    
  2754.   current: Fiber,
    
  2755.   workInProgress: Fiber,
    
  2756.   primaryChildren: $FlowFixMe,
    
  2757.   fallbackChildren: $FlowFixMe,
    
  2758.   renderLanes: Lanes,
    
  2759. ) {
    
  2760.   const fiberMode = workInProgress.mode;
    
  2761.   const primaryChildProps: OffscreenProps = {
    
  2762.     mode: 'visible',
    
  2763.     children: primaryChildren,
    
  2764.   };
    
  2765.   const primaryChildFragment = mountWorkInProgressOffscreenFiber(
    
  2766.     primaryChildProps,
    
  2767.     fiberMode,
    
  2768.     NoLanes,
    
  2769.   );
    
  2770.   const fallbackChildFragment = createFiberFromFragment(
    
  2771.     fallbackChildren,
    
  2772.     fiberMode,
    
  2773.     renderLanes,
    
  2774.     null,
    
  2775.   );
    
  2776.   // Needs a placement effect because the parent (the Suspense
    
  2777.   // boundary) already mounted but this is a new fiber.
    
  2778.   fallbackChildFragment.flags |= Placement;
    
  2779. 
    
  2780.   primaryChildFragment.return = workInProgress;
    
  2781.   fallbackChildFragment.return = workInProgress;
    
  2782.   primaryChildFragment.sibling = fallbackChildFragment;
    
  2783.   workInProgress.child = primaryChildFragment;
    
  2784. 
    
  2785.   if ((workInProgress.mode & ConcurrentMode) !== NoMode) {
    
  2786.     // We will have dropped the effect list which contains the
    
  2787.     // deletion. We need to reconcile to delete the current child.
    
  2788.     reconcileChildFibers(workInProgress, current.child, null, renderLanes);
    
  2789.   }
    
  2790. 
    
  2791.   return fallbackChildFragment;
    
  2792. }
    
  2793. 
    
  2794. function mountDehydratedSuspenseComponent(
    
  2795.   workInProgress: Fiber,
    
  2796.   suspenseInstance: SuspenseInstance,
    
  2797.   renderLanes: Lanes,
    
  2798. ): null | Fiber {
    
  2799.   // During the first pass, we'll bail out and not drill into the children.
    
  2800.   // Instead, we'll leave the content in place and try to hydrate it later.
    
  2801.   if ((workInProgress.mode & ConcurrentMode) === NoMode) {
    
  2802.     if (__DEV__) {
    
  2803.       console.error(
    
  2804.         'Cannot hydrate Suspense in legacy mode. Switch from ' +
    
  2805.           'ReactDOM.hydrate(element, container) to ' +
    
  2806.           'ReactDOMClient.hydrateRoot(container, <App />)' +
    
  2807.           '.render(element) or remove the Suspense components from ' +
    
  2808.           'the server rendered components.',
    
  2809.       );
    
  2810.     }
    
  2811.     workInProgress.lanes = laneToLanes(SyncLane);
    
  2812.   } else if (isSuspenseInstanceFallback(suspenseInstance)) {
    
  2813.     // This is a client-only boundary. Since we won't get any content from the server
    
  2814.     // for this, we need to schedule that at a higher priority based on when it would
    
  2815.     // have timed out. In theory we could render it in this pass but it would have the
    
  2816.     // wrong priority associated with it and will prevent hydration of parent path.
    
  2817.     // Instead, we'll leave work left on it to render it in a separate commit.
    
  2818. 
    
  2819.     // TODO This time should be the time at which the server rendered response that is
    
  2820.     // a parent to this boundary was displayed. However, since we currently don't have
    
  2821.     // a protocol to transfer that time, we'll just estimate it by using the current
    
  2822.     // time. This will mean that Suspense timeouts are slightly shifted to later than
    
  2823.     // they should be.
    
  2824.     // Schedule a normal pri update to render this content.
    
  2825.     workInProgress.lanes = laneToLanes(DefaultHydrationLane);
    
  2826.   } else {
    
  2827.     // We'll continue hydrating the rest at offscreen priority since we'll already
    
  2828.     // be showing the right content coming from the server, it is no rush.
    
  2829.     workInProgress.lanes = laneToLanes(OffscreenLane);
    
  2830.   }
    
  2831.   return null;
    
  2832. }
    
  2833. 
    
  2834. function updateDehydratedSuspenseComponent(
    
  2835.   current: Fiber,
    
  2836.   workInProgress: Fiber,
    
  2837.   didSuspend: boolean,
    
  2838.   nextProps: any,
    
  2839.   suspenseInstance: SuspenseInstance,
    
  2840.   suspenseState: SuspenseState,
    
  2841.   renderLanes: Lanes,
    
  2842. ): null | Fiber {
    
  2843.   if (!didSuspend) {
    
  2844.     // This is the first render pass. Attempt to hydrate.
    
  2845.     pushPrimaryTreeSuspenseHandler(workInProgress);
    
  2846. 
    
  2847.     // We should never be hydrating at this point because it is the first pass,
    
  2848.     // but after we've already committed once.
    
  2849.     warnIfHydrating();
    
  2850. 
    
  2851.     if ((workInProgress.mode & ConcurrentMode) === NoMode) {
    
  2852.       return retrySuspenseComponentWithoutHydrating(
    
  2853.         current,
    
  2854.         workInProgress,
    
  2855.         renderLanes,
    
  2856.         null,
    
  2857.       );
    
  2858.     }
    
  2859. 
    
  2860.     if (isSuspenseInstanceFallback(suspenseInstance)) {
    
  2861.       // This boundary is in a permanent fallback state. In this case, we'll never
    
  2862.       // get an update and we'll never be able to hydrate the final content. Let's just try the
    
  2863.       // client side render instead.
    
  2864.       let digest: ?string;
    
  2865.       let message, stack;
    
  2866.       if (__DEV__) {
    
  2867.         ({digest, message, stack} =
    
  2868.           getSuspenseInstanceFallbackErrorDetails(suspenseInstance));
    
  2869.       } else {
    
  2870.         ({digest} = getSuspenseInstanceFallbackErrorDetails(suspenseInstance));
    
  2871.       }
    
  2872. 
    
  2873.       let capturedValue = null;
    
  2874.       // TODO: Figure out a better signal than encoding a magic digest value.
    
  2875.       if (!enablePostpone || digest !== 'POSTPONE') {
    
  2876.         let error;
    
  2877.         if (message) {
    
  2878.           // eslint-disable-next-line react-internal/prod-error-codes
    
  2879.           error = new Error(message);
    
  2880.         } else {
    
  2881.           error = new Error(
    
  2882.             'The server could not finish this Suspense boundary, likely ' +
    
  2883.               'due to an error during server rendering. Switched to ' +
    
  2884.               'client rendering.',
    
  2885.           );
    
  2886.         }
    
  2887.         (error: any).digest = digest;
    
  2888.         capturedValue = createCapturedValue<mixed>(error, digest, stack);
    
  2889.       }
    
  2890.       return retrySuspenseComponentWithoutHydrating(
    
  2891.         current,
    
  2892.         workInProgress,
    
  2893.         renderLanes,
    
  2894.         capturedValue,
    
  2895.       );
    
  2896.     }
    
  2897. 
    
  2898.     if (
    
  2899.       enableLazyContextPropagation &&
    
  2900.       // TODO: Factoring is a little weird, since we check this right below, too.
    
  2901.       // But don't want to re-arrange the if-else chain until/unless this
    
  2902.       // feature lands.
    
  2903.       !didReceiveUpdate
    
  2904.     ) {
    
  2905.       // We need to check if any children have context before we decide to bail
    
  2906.       // out, so propagate the changes now.
    
  2907.       lazilyPropagateParentContextChanges(current, workInProgress, renderLanes);
    
  2908.     }
    
  2909. 
    
  2910.     // We use lanes to indicate that a child might depend on context, so if
    
  2911.     // any context has changed, we need to treat is as if the input might have changed.
    
  2912.     const hasContextChanged = includesSomeLane(renderLanes, current.childLanes);
    
  2913.     if (didReceiveUpdate || hasContextChanged) {
    
  2914.       // This boundary has changed since the first render. This means that we are now unable to
    
  2915.       // hydrate it. We might still be able to hydrate it using a higher priority lane.
    
  2916.       const root = getWorkInProgressRoot();
    
  2917.       if (root !== null) {
    
  2918.         const attemptHydrationAtLane = getBumpedLaneForHydration(
    
  2919.           root,
    
  2920.           renderLanes,
    
  2921.         );
    
  2922.         if (
    
  2923.           attemptHydrationAtLane !== NoLane &&
    
  2924.           attemptHydrationAtLane !== suspenseState.retryLane
    
  2925.         ) {
    
  2926.           // Intentionally mutating since this render will get interrupted. This
    
  2927.           // is one of the very rare times where we mutate the current tree
    
  2928.           // during the render phase.
    
  2929.           suspenseState.retryLane = attemptHydrationAtLane;
    
  2930.           enqueueConcurrentRenderForLane(current, attemptHydrationAtLane);
    
  2931.           scheduleUpdateOnFiber(root, current, attemptHydrationAtLane);
    
  2932. 
    
  2933.           // Throw a special object that signals to the work loop that it should
    
  2934.           // interrupt the current render.
    
  2935.           //
    
  2936.           // Because we're inside a React-only execution stack, we don't
    
  2937.           // strictly need to throw here — we could instead modify some internal
    
  2938.           // work loop state. But using an exception means we don't need to
    
  2939.           // check for this case on every iteration of the work loop. So doing
    
  2940.           // it this way moves the check out of the fast path.
    
  2941.           throw SelectiveHydrationException;
    
  2942.         } else {
    
  2943.           // We have already tried to ping at a higher priority than we're rendering with
    
  2944.           // so if we got here, we must have failed to hydrate at those levels. We must
    
  2945.           // now give up. Instead, we're going to delete the whole subtree and instead inject
    
  2946.           // a new real Suspense boundary to take its place, which may render content
    
  2947.           // or fallback. This might suspend for a while and if it does we might still have
    
  2948.           // an opportunity to hydrate before this pass commits.
    
  2949.         }
    
  2950.       }
    
  2951. 
    
  2952.       // If we did not selectively hydrate, we'll continue rendering without
    
  2953.       // hydrating. Mark this tree as suspended to prevent it from committing
    
  2954.       // outside a transition.
    
  2955.       //
    
  2956.       // This path should only happen if the hydration lane already suspended.
    
  2957.       // Currently, it also happens during sync updates because there is no
    
  2958.       // hydration lane for sync updates.
    
  2959.       // TODO: We should ideally have a sync hydration lane that we can apply to do
    
  2960.       // a pass where we hydrate this subtree in place using the previous Context and then
    
  2961.       // reapply the update afterwards.
    
  2962.       if (isSuspenseInstancePending(suspenseInstance)) {
    
  2963.         // This is a dehydrated suspense instance. We don't need to suspend
    
  2964.         // because we're already showing a fallback.
    
  2965.         // TODO: The Fizz runtime might still stream in completed HTML, out-of-
    
  2966.         // band. Should we fix this? There's a version of this bug that happens
    
  2967.         // during client rendering, too. Needs more consideration.
    
  2968.       } else {
    
  2969.         renderDidSuspendDelayIfPossible();
    
  2970.       }
    
  2971.       return retrySuspenseComponentWithoutHydrating(
    
  2972.         current,
    
  2973.         workInProgress,
    
  2974.         renderLanes,
    
  2975.         null,
    
  2976.       );
    
  2977.     } else if (isSuspenseInstancePending(suspenseInstance)) {
    
  2978.       // This component is still pending more data from the server, so we can't hydrate its
    
  2979.       // content. We treat it as if this component suspended itself. It might seem as if
    
  2980.       // we could just try to render it client-side instead. However, this will perform a
    
  2981.       // lot of unnecessary work and is unlikely to complete since it often will suspend
    
  2982.       // on missing data anyway. Additionally, the server might be able to render more
    
  2983.       // than we can on the client yet. In that case we'd end up with more fallback states
    
  2984.       // on the client than if we just leave it alone. If the server times out or errors
    
  2985.       // these should update this boundary to the permanent Fallback state instead.
    
  2986.       // Mark it as having captured (i.e. suspended).
    
  2987.       workInProgress.flags |= DidCapture;
    
  2988.       // Leave the child in place. I.e. the dehydrated fragment.
    
  2989.       workInProgress.child = current.child;
    
  2990.       // Register a callback to retry this boundary once the server has sent the result.
    
  2991.       const retry = retryDehydratedSuspenseBoundary.bind(null, current);
    
  2992.       registerSuspenseInstanceRetry(suspenseInstance, retry);
    
  2993.       return null;
    
  2994.     } else {
    
  2995.       // This is the first attempt.
    
  2996.       reenterHydrationStateFromDehydratedSuspenseInstance(
    
  2997.         workInProgress,
    
  2998.         suspenseInstance,
    
  2999.         suspenseState.treeContext,
    
  3000.       );
    
  3001.       const primaryChildren = nextProps.children;
    
  3002.       const primaryChildFragment = mountSuspensePrimaryChildren(
    
  3003.         workInProgress,
    
  3004.         primaryChildren,
    
  3005.         renderLanes,
    
  3006.       );
    
  3007.       // Mark the children as hydrating. This is a fast path to know whether this
    
  3008.       // tree is part of a hydrating tree. This is used to determine if a child
    
  3009.       // node has fully mounted yet, and for scheduling event replaying.
    
  3010.       // Conceptually this is similar to Placement in that a new subtree is
    
  3011.       // inserted into the React tree here. It just happens to not need DOM
    
  3012.       // mutations because it already exists.
    
  3013.       primaryChildFragment.flags |= Hydrating;
    
  3014.       return primaryChildFragment;
    
  3015.     }
    
  3016.   } else {
    
  3017.     // This is the second render pass. We already attempted to hydrated, but
    
  3018.     // something either suspended or errored.
    
  3019. 
    
  3020.     if (workInProgress.flags & ForceClientRender) {
    
  3021.       // Something errored during hydration. Try again without hydrating.
    
  3022.       pushPrimaryTreeSuspenseHandler(workInProgress);
    
  3023. 
    
  3024.       workInProgress.flags &= ~ForceClientRender;
    
  3025.       const capturedValue = createCapturedValue<mixed>(
    
  3026.         new Error(
    
  3027.           'There was an error while hydrating this Suspense boundary. ' +
    
  3028.             'Switched to client rendering.',
    
  3029.         ),
    
  3030.       );
    
  3031.       return retrySuspenseComponentWithoutHydrating(
    
  3032.         current,
    
  3033.         workInProgress,
    
  3034.         renderLanes,
    
  3035.         capturedValue,
    
  3036.       );
    
  3037.     } else if ((workInProgress.memoizedState: null | SuspenseState) !== null) {
    
  3038.       // Something suspended and we should still be in dehydrated mode.
    
  3039.       // Leave the existing child in place.
    
  3040. 
    
  3041.       // Push to avoid a mismatch
    
  3042.       pushFallbackTreeSuspenseHandler(workInProgress);
    
  3043. 
    
  3044.       workInProgress.child = current.child;
    
  3045.       // The dehydrated completion pass expects this flag to be there
    
  3046.       // but the normal suspense pass doesn't.
    
  3047.       workInProgress.flags |= DidCapture;
    
  3048.       return null;
    
  3049.     } else {
    
  3050.       // Suspended but we should no longer be in dehydrated mode.
    
  3051.       // Therefore we now have to render the fallback.
    
  3052.       pushFallbackTreeSuspenseHandler(workInProgress);
    
  3053. 
    
  3054.       const nextPrimaryChildren = nextProps.children;
    
  3055.       const nextFallbackChildren = nextProps.fallback;
    
  3056.       const fallbackChildFragment =
    
  3057.         mountSuspenseFallbackAfterRetryWithoutHydrating(
    
  3058.           current,
    
  3059.           workInProgress,
    
  3060.           nextPrimaryChildren,
    
  3061.           nextFallbackChildren,
    
  3062.           renderLanes,
    
  3063.         );
    
  3064.       const primaryChildFragment: Fiber = (workInProgress.child: any);
    
  3065.       primaryChildFragment.memoizedState =
    
  3066.         mountSuspenseOffscreenState(renderLanes);
    
  3067.       workInProgress.memoizedState = SUSPENDED_MARKER;
    
  3068.       return fallbackChildFragment;
    
  3069.     }
    
  3070.   }
    
  3071. }
    
  3072. 
    
  3073. function scheduleSuspenseWorkOnFiber(
    
  3074.   fiber: Fiber,
    
  3075.   renderLanes: Lanes,
    
  3076.   propagationRoot: Fiber,
    
  3077. ) {
    
  3078.   fiber.lanes = mergeLanes(fiber.lanes, renderLanes);
    
  3079.   const alternate = fiber.alternate;
    
  3080.   if (alternate !== null) {
    
  3081.     alternate.lanes = mergeLanes(alternate.lanes, renderLanes);
    
  3082.   }
    
  3083.   scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot);
    
  3084. }
    
  3085. 
    
  3086. function propagateSuspenseContextChange(
    
  3087.   workInProgress: Fiber,
    
  3088.   firstChild: null | Fiber,
    
  3089.   renderLanes: Lanes,
    
  3090. ): void {
    
  3091.   // Mark any Suspense boundaries with fallbacks as having work to do.
    
  3092.   // If they were previously forced into fallbacks, they may now be able
    
  3093.   // to unblock.
    
  3094.   let node = firstChild;
    
  3095.   while (node !== null) {
    
  3096.     if (node.tag === SuspenseComponent) {
    
  3097.       const state: SuspenseState | null = node.memoizedState;
    
  3098.       if (state !== null) {
    
  3099.         scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress);
    
  3100.       }
    
  3101.     } else if (node.tag === SuspenseListComponent) {
    
  3102.       // If the tail is hidden there might not be an Suspense boundaries
    
  3103.       // to schedule work on. In this case we have to schedule it on the
    
  3104.       // list itself.
    
  3105.       // We don't have to traverse to the children of the list since
    
  3106.       // the list will propagate the change when it rerenders.
    
  3107.       scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress);
    
  3108.     } else if (node.child !== null) {
    
  3109.       node.child.return = node;
    
  3110.       node = node.child;
    
  3111.       continue;
    
  3112.     }
    
  3113.     if (node === workInProgress) {
    
  3114.       return;
    
  3115.     }
    
  3116.     // $FlowFixMe[incompatible-use] found when upgrading Flow
    
  3117.     while (node.sibling === null) {
    
  3118.       // $FlowFixMe[incompatible-use] found when upgrading Flow
    
  3119.       if (node.return === null || node.return === workInProgress) {
    
  3120.         return;
    
  3121.       }
    
  3122.       node = node.return;
    
  3123.     }
    
  3124.     // $FlowFixMe[incompatible-use] found when upgrading Flow
    
  3125.     node.sibling.return = node.return;
    
  3126.     node = node.sibling;
    
  3127.   }
    
  3128. }
    
  3129. 
    
  3130. function findLastContentRow(firstChild: null | Fiber): null | Fiber {
    
  3131.   // This is going to find the last row among these children that is already
    
  3132.   // showing content on the screen, as opposed to being in fallback state or
    
  3133.   // new. If a row has multiple Suspense boundaries, any of them being in the
    
  3134.   // fallback state, counts as the whole row being in a fallback state.
    
  3135.   // Note that the "rows" will be workInProgress, but any nested children
    
  3136.   // will still be current since we haven't rendered them yet. The mounted
    
  3137.   // order may not be the same as the new order. We use the new order.
    
  3138.   let row = firstChild;
    
  3139.   let lastContentRow: null | Fiber = null;
    
  3140.   while (row !== null) {
    
  3141.     const currentRow = row.alternate;
    
  3142.     // New rows can't be content rows.
    
  3143.     if (currentRow !== null && findFirstSuspended(currentRow) === null) {
    
  3144.       lastContentRow = row;
    
  3145.     }
    
  3146.     row = row.sibling;
    
  3147.   }
    
  3148.   return lastContentRow;
    
  3149. }
    
  3150. 
    
  3151. type SuspenseListRevealOrder = 'forwards' | 'backwards' | 'together' | void;
    
  3152. 
    
  3153. function validateRevealOrder(revealOrder: SuspenseListRevealOrder) {
    
  3154.   if (__DEV__) {
    
  3155.     if (
    
  3156.       revealOrder !== undefined &&
    
  3157.       revealOrder !== 'forwards' &&
    
  3158.       revealOrder !== 'backwards' &&
    
  3159.       revealOrder !== 'together' &&
    
  3160.       !didWarnAboutRevealOrder[revealOrder]
    
  3161.     ) {
    
  3162.       didWarnAboutRevealOrder[revealOrder] = true;
    
  3163.       if (typeof revealOrder === 'string') {
    
  3164.         switch (revealOrder.toLowerCase()) {
    
  3165.           case 'together':
    
  3166.           case 'forwards':
    
  3167.           case 'backwards': {
    
  3168.             console.error(
    
  3169.               '"%s" is not a valid value for revealOrder on <SuspenseList />. ' +
    
  3170.                 'Use lowercase "%s" instead.',
    
  3171.               revealOrder,
    
  3172.               revealOrder.toLowerCase(),
    
  3173.             );
    
  3174.             break;
    
  3175.           }
    
  3176.           case 'forward':
    
  3177.           case 'backward': {
    
  3178.             console.error(
    
  3179.               '"%s" is not a valid value for revealOrder on <SuspenseList />. ' +
    
  3180.                 'React uses the -s suffix in the spelling. Use "%ss" instead.',
    
  3181.               revealOrder,
    
  3182.               revealOrder.toLowerCase(),
    
  3183.             );
    
  3184.             break;
    
  3185.           }
    
  3186.           default:
    
  3187.             console.error(
    
  3188.               '"%s" is not a supported revealOrder on <SuspenseList />. ' +
    
  3189.                 'Did you mean "together", "forwards" or "backwards"?',
    
  3190.               revealOrder,
    
  3191.             );
    
  3192.             break;
    
  3193.         }
    
  3194.       } else {
    
  3195.         console.error(
    
  3196.           '%s is not a supported value for revealOrder on <SuspenseList />. ' +
    
  3197.             'Did you mean "together", "forwards" or "backwards"?',
    
  3198.           revealOrder,
    
  3199.         );
    
  3200.       }
    
  3201.     }
    
  3202.   }
    
  3203. }
    
  3204. 
    
  3205. function validateTailOptions(
    
  3206.   tailMode: SuspenseListTailMode,
    
  3207.   revealOrder: SuspenseListRevealOrder,
    
  3208. ) {
    
  3209.   if (__DEV__) {
    
  3210.     if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) {
    
  3211.       if (tailMode !== 'collapsed' && tailMode !== 'hidden') {
    
  3212.         didWarnAboutTailOptions[tailMode] = true;
    
  3213.         console.error(
    
  3214.           '"%s" is not a supported value for tail on <SuspenseList />. ' +
    
  3215.             'Did you mean "collapsed" or "hidden"?',
    
  3216.           tailMode,
    
  3217.         );
    
  3218.       } else if (revealOrder !== 'forwards' && revealOrder !== 'backwards') {
    
  3219.         didWarnAboutTailOptions[tailMode] = true;
    
  3220.         console.error(
    
  3221.           '<SuspenseList tail="%s" /> is only valid if revealOrder is ' +
    
  3222.             '"forwards" or "backwards". ' +
    
  3223.             'Did you mean to specify revealOrder="forwards"?',
    
  3224.           tailMode,
    
  3225.         );
    
  3226.       }
    
  3227.     }
    
  3228.   }
    
  3229. }
    
  3230. 
    
  3231. function validateSuspenseListNestedChild(childSlot: mixed, index: number) {
    
  3232.   if (__DEV__) {
    
  3233.     const isAnArray = isArray(childSlot);
    
  3234.     const isIterable =
    
  3235.       !isAnArray && typeof getIteratorFn(childSlot) === 'function';
    
  3236.     if (isAnArray || isIterable) {
    
  3237.       const type = isAnArray ? 'array' : 'iterable';
    
  3238.       console.error(
    
  3239.         'A nested %s was passed to row #%s in <SuspenseList />. Wrap it in ' +
    
  3240.           'an additional SuspenseList to configure its revealOrder: ' +
    
  3241.           '<SuspenseList revealOrder=...> ... ' +
    
  3242.           '<SuspenseList revealOrder=...>{%s}</SuspenseList> ... ' +
    
  3243.           '</SuspenseList>',
    
  3244.         type,
    
  3245.         index,
    
  3246.         type,
    
  3247.       );
    
  3248.       return false;
    
  3249.     }
    
  3250.   }
    
  3251.   return true;
    
  3252. }
    
  3253. 
    
  3254. function validateSuspenseListChildren(
    
  3255.   children: mixed,
    
  3256.   revealOrder: SuspenseListRevealOrder,
    
  3257. ) {
    
  3258.   if (__DEV__) {
    
  3259.     if (
    
  3260.       (revealOrder === 'forwards' || revealOrder === 'backwards') &&
    
  3261.       children !== undefined &&
    
  3262.       children !== null &&
    
  3263.       children !== false
    
  3264.     ) {
    
  3265.       if (isArray(children)) {
    
  3266.         for (let i = 0; i < children.length; i++) {
    
  3267.           if (!validateSuspenseListNestedChild(children[i], i)) {
    
  3268.             return;
    
  3269.           }
    
  3270.         }
    
  3271.       } else {
    
  3272.         const iteratorFn = getIteratorFn(children);
    
  3273.         if (typeof iteratorFn === 'function') {
    
  3274.           const childrenIterator = iteratorFn.call(children);
    
  3275.           if (childrenIterator) {
    
  3276.             let step = childrenIterator.next();
    
  3277.             let i = 0;
    
  3278.             for (; !step.done; step = childrenIterator.next()) {
    
  3279.               if (!validateSuspenseListNestedChild(step.value, i)) {
    
  3280.                 return;
    
  3281.               }
    
  3282.               i++;
    
  3283.             }
    
  3284.           }
    
  3285.         } else {
    
  3286.           console.error(
    
  3287.             'A single row was passed to a <SuspenseList revealOrder="%s" />. ' +
    
  3288.               'This is not useful since it needs multiple rows. ' +
    
  3289.               'Did you mean to pass multiple children or an array?',
    
  3290.             revealOrder,
    
  3291.           );
    
  3292.         }
    
  3293.       }
    
  3294.     }
    
  3295.   }
    
  3296. }
    
  3297. 
    
  3298. function initSuspenseListRenderState(
    
  3299.   workInProgress: Fiber,
    
  3300.   isBackwards: boolean,
    
  3301.   tail: null | Fiber,
    
  3302.   lastContentRow: null | Fiber,
    
  3303.   tailMode: SuspenseListTailMode,
    
  3304. ): void {
    
  3305.   const renderState: null | SuspenseListRenderState =
    
  3306.     workInProgress.memoizedState;
    
  3307.   if (renderState === null) {
    
  3308.     workInProgress.memoizedState = ({
    
  3309.       isBackwards: isBackwards,
    
  3310.       rendering: null,
    
  3311.       renderingStartTime: 0,
    
  3312.       last: lastContentRow,
    
  3313.       tail: tail,
    
  3314.       tailMode: tailMode,
    
  3315.     }: SuspenseListRenderState);
    
  3316.   } else {
    
  3317.     // We can reuse the existing object from previous renders.
    
  3318.     renderState.isBackwards = isBackwards;
    
  3319.     renderState.rendering = null;
    
  3320.     renderState.renderingStartTime = 0;
    
  3321.     renderState.last = lastContentRow;
    
  3322.     renderState.tail = tail;
    
  3323.     renderState.tailMode = tailMode;
    
  3324.   }
    
  3325. }
    
  3326. 
    
  3327. // This can end up rendering this component multiple passes.
    
  3328. // The first pass splits the children fibers into two sets. A head and tail.
    
  3329. // We first render the head. If anything is in fallback state, we do another
    
  3330. // pass through beginWork to rerender all children (including the tail) with
    
  3331. // the force suspend context. If the first render didn't have anything in
    
  3332. // in fallback state. Then we render each row in the tail one-by-one.
    
  3333. // That happens in the completeWork phase without going back to beginWork.
    
  3334. function updateSuspenseListComponent(
    
  3335.   current: Fiber | null,
    
  3336.   workInProgress: Fiber,
    
  3337.   renderLanes: Lanes,
    
  3338. ) {
    
  3339.   const nextProps = workInProgress.pendingProps;
    
  3340.   const revealOrder: SuspenseListRevealOrder = nextProps.revealOrder;
    
  3341.   const tailMode: SuspenseListTailMode = nextProps.tail;
    
  3342.   const newChildren = nextProps.children;
    
  3343. 
    
  3344.   validateRevealOrder(revealOrder);
    
  3345.   validateTailOptions(tailMode, revealOrder);
    
  3346.   validateSuspenseListChildren(newChildren, revealOrder);
    
  3347. 
    
  3348.   reconcileChildren(current, workInProgress, newChildren, renderLanes);
    
  3349. 
    
  3350.   let suspenseContext: SuspenseContext = suspenseStackCursor.current;
    
  3351. 
    
  3352.   const shouldForceFallback = hasSuspenseListContext(
    
  3353.     suspenseContext,
    
  3354.     (ForceSuspenseFallback: SuspenseContext),
    
  3355.   );
    
  3356.   if (shouldForceFallback) {
    
  3357.     suspenseContext = setShallowSuspenseListContext(
    
  3358.       suspenseContext,
    
  3359.       ForceSuspenseFallback,
    
  3360.     );
    
  3361.     workInProgress.flags |= DidCapture;
    
  3362.   } else {
    
  3363.     const didSuspendBefore =
    
  3364.       current !== null && (current.flags & DidCapture) !== NoFlags;
    
  3365.     if (didSuspendBefore) {
    
  3366.       // If we previously forced a fallback, we need to schedule work
    
  3367.       // on any nested boundaries to let them know to try to render
    
  3368.       // again. This is the same as context updating.
    
  3369.       propagateSuspenseContextChange(
    
  3370.         workInProgress,
    
  3371.         workInProgress.child,
    
  3372.         renderLanes,
    
  3373.       );
    
  3374.     }
    
  3375.     suspenseContext = setDefaultShallowSuspenseListContext(suspenseContext);
    
  3376.   }
    
  3377.   pushSuspenseListContext(workInProgress, suspenseContext);
    
  3378. 
    
  3379.   if ((workInProgress.mode & ConcurrentMode) === NoMode) {
    
  3380.     // In legacy mode, SuspenseList doesn't work so we just
    
  3381.     // use make it a noop by treating it as the default revealOrder.
    
  3382.     workInProgress.memoizedState = null;
    
  3383.   } else {
    
  3384.     switch (revealOrder) {
    
  3385.       case 'forwards': {
    
  3386.         const lastContentRow = findLastContentRow(workInProgress.child);
    
  3387.         let tail;
    
  3388.         if (lastContentRow === null) {
    
  3389.           // The whole list is part of the tail.
    
  3390.           // TODO: We could fast path by just rendering the tail now.
    
  3391.           tail = workInProgress.child;
    
  3392.           workInProgress.child = null;
    
  3393.         } else {
    
  3394.           // Disconnect the tail rows after the content row.
    
  3395.           // We're going to render them separately later.
    
  3396.           tail = lastContentRow.sibling;
    
  3397.           lastContentRow.sibling = null;
    
  3398.         }
    
  3399.         initSuspenseListRenderState(
    
  3400.           workInProgress,
    
  3401.           false, // isBackwards
    
  3402.           tail,
    
  3403.           lastContentRow,
    
  3404.           tailMode,
    
  3405.         );
    
  3406.         break;
    
  3407.       }
    
  3408.       case 'backwards': {
    
  3409.         // We're going to find the first row that has existing content.
    
  3410.         // At the same time we're going to reverse the list of everything
    
  3411.         // we pass in the meantime. That's going to be our tail in reverse
    
  3412.         // order.
    
  3413.         let tail = null;
    
  3414.         let row = workInProgress.child;
    
  3415.         workInProgress.child = null;
    
  3416.         while (row !== null) {
    
  3417.           const currentRow = row.alternate;
    
  3418.           // New rows can't be content rows.
    
  3419.           if (currentRow !== null && findFirstSuspended(currentRow) === null) {
    
  3420.             // This is the beginning of the main content.
    
  3421.             workInProgress.child = row;
    
  3422.             break;
    
  3423.           }
    
  3424.           const nextRow = row.sibling;
    
  3425.           row.sibling = tail;
    
  3426.           tail = row;
    
  3427.           row = nextRow;
    
  3428.         }
    
  3429.         // TODO: If workInProgress.child is null, we can continue on the tail immediately.
    
  3430.         initSuspenseListRenderState(
    
  3431.           workInProgress,
    
  3432.           true, // isBackwards
    
  3433.           tail,
    
  3434.           null, // last
    
  3435.           tailMode,
    
  3436.         );
    
  3437.         break;
    
  3438.       }
    
  3439.       case 'together': {
    
  3440.         initSuspenseListRenderState(
    
  3441.           workInProgress,
    
  3442.           false, // isBackwards
    
  3443.           null, // tail
    
  3444.           null, // last
    
  3445.           undefined,
    
  3446.         );
    
  3447.         break;
    
  3448.       }
    
  3449.       default: {
    
  3450.         // The default reveal order is the same as not having
    
  3451.         // a boundary.
    
  3452.         workInProgress.memoizedState = null;
    
  3453.       }
    
  3454.     }
    
  3455.   }
    
  3456.   return workInProgress.child;
    
  3457. }
    
  3458. 
    
  3459. function updatePortalComponent(
    
  3460.   current: Fiber | null,
    
  3461.   workInProgress: Fiber,
    
  3462.   renderLanes: Lanes,
    
  3463. ) {
    
  3464.   pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
    
  3465.   const nextChildren = workInProgress.pendingProps;
    
  3466.   if (current === null) {
    
  3467.     // Portals are special because we don't append the children during mount
    
  3468.     // but at commit. Therefore we need to track insertions which the normal
    
  3469.     // flow doesn't do during mount. This doesn't happen at the root because
    
  3470.     // the root always starts with a "current" with a null child.
    
  3471.     // TODO: Consider unifying this with how the root works.
    
  3472.     workInProgress.child = reconcileChildFibers(
    
  3473.       workInProgress,
    
  3474.       null,
    
  3475.       nextChildren,
    
  3476.       renderLanes,
    
  3477.     );
    
  3478.   } else {
    
  3479.     reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  3480.   }
    
  3481.   return workInProgress.child;
    
  3482. }
    
  3483. 
    
  3484. let hasWarnedAboutUsingNoValuePropOnContextProvider = false;
    
  3485. 
    
  3486. function updateContextProvider(
    
  3487.   current: Fiber | null,
    
  3488.   workInProgress: Fiber,
    
  3489.   renderLanes: Lanes,
    
  3490. ) {
    
  3491.   const providerType: ReactProviderType<any> = workInProgress.type;
    
  3492.   const context: ReactContext<any> = providerType._context;
    
  3493. 
    
  3494.   const newProps = workInProgress.pendingProps;
    
  3495.   const oldProps = workInProgress.memoizedProps;
    
  3496. 
    
  3497.   const newValue = newProps.value;
    
  3498. 
    
  3499.   if (__DEV__) {
    
  3500.     if (!('value' in newProps)) {
    
  3501.       if (!hasWarnedAboutUsingNoValuePropOnContextProvider) {
    
  3502.         hasWarnedAboutUsingNoValuePropOnContextProvider = true;
    
  3503.         console.error(
    
  3504.           'The `value` prop is required for the `<Context.Provider>`. Did you misspell it or forget to pass it?',
    
  3505.         );
    
  3506.       }
    
  3507.     }
    
  3508.     const providerPropTypes = workInProgress.type.propTypes;
    
  3509. 
    
  3510.     if (providerPropTypes) {
    
  3511.       checkPropTypes(providerPropTypes, newProps, 'prop', 'Context.Provider');
    
  3512.     }
    
  3513.   }
    
  3514. 
    
  3515.   pushProvider(workInProgress, context, newValue);
    
  3516. 
    
  3517.   if (enableLazyContextPropagation) {
    
  3518.     // In the lazy propagation implementation, we don't scan for matching
    
  3519.     // consumers until something bails out, because until something bails out
    
  3520.     // we're going to visit those nodes, anyway. The trade-off is that it shifts
    
  3521.     // responsibility to the consumer to track whether something has changed.
    
  3522.   } else {
    
  3523.     if (oldProps !== null) {
    
  3524.       const oldValue = oldProps.value;
    
  3525.       if (is(oldValue, newValue)) {
    
  3526.         // No change. Bailout early if children are the same.
    
  3527.         if (
    
  3528.           oldProps.children === newProps.children &&
    
  3529.           !hasLegacyContextChanged()
    
  3530.         ) {
    
  3531.           return bailoutOnAlreadyFinishedWork(
    
  3532.             current,
    
  3533.             workInProgress,
    
  3534.             renderLanes,
    
  3535.           );
    
  3536.         }
    
  3537.       } else {
    
  3538.         // The context value changed. Search for matching consumers and schedule
    
  3539.         // them to update.
    
  3540.         propagateContextChange(workInProgress, context, renderLanes);
    
  3541.       }
    
  3542.     }
    
  3543.   }
    
  3544. 
    
  3545.   const newChildren = newProps.children;
    
  3546.   reconcileChildren(current, workInProgress, newChildren, renderLanes);
    
  3547.   return workInProgress.child;
    
  3548. }
    
  3549. 
    
  3550. let hasWarnedAboutUsingContextAsConsumer = false;
    
  3551. 
    
  3552. function updateContextConsumer(
    
  3553.   current: Fiber | null,
    
  3554.   workInProgress: Fiber,
    
  3555.   renderLanes: Lanes,
    
  3556. ) {
    
  3557.   let context: ReactContext<any> = workInProgress.type;
    
  3558.   // The logic below for Context differs depending on PROD or DEV mode. In
    
  3559.   // DEV mode, we create a separate object for Context.Consumer that acts
    
  3560.   // like a proxy to Context. This proxy object adds unnecessary code in PROD
    
  3561.   // so we use the old behaviour (Context.Consumer references Context) to
    
  3562.   // reduce size and overhead. The separate object references context via
    
  3563.   // a property called "_context", which also gives us the ability to check
    
  3564.   // in DEV mode if this property exists or not and warn if it does not.
    
  3565.   if (__DEV__) {
    
  3566.     if ((context: any)._context === undefined) {
    
  3567.       // This may be because it's a Context (rather than a Consumer).
    
  3568.       // Or it may be because it's older React where they're the same thing.
    
  3569.       // We only want to warn if we're sure it's a new React.
    
  3570.       if (context !== context.Consumer) {
    
  3571.         if (!hasWarnedAboutUsingContextAsConsumer) {
    
  3572.           hasWarnedAboutUsingContextAsConsumer = true;
    
  3573.           console.error(
    
  3574.             'Rendering <Context> directly is not supported and will be removed in ' +
    
  3575.               'a future major release. Did you mean to render <Context.Consumer> instead?',
    
  3576.           );
    
  3577.         }
    
  3578.       }
    
  3579.     } else {
    
  3580.       context = (context: any)._context;
    
  3581.     }
    
  3582.   }
    
  3583.   const newProps = workInProgress.pendingProps;
    
  3584.   const render = newProps.children;
    
  3585. 
    
  3586.   if (__DEV__) {
    
  3587.     if (typeof render !== 'function') {
    
  3588.       console.error(
    
  3589.         'A context consumer was rendered with multiple children, or a child ' +
    
  3590.           "that isn't a function. A context consumer expects a single child " +
    
  3591.           'that is a function. If you did pass a function, make sure there ' +
    
  3592.           'is no trailing or leading whitespace around it.',
    
  3593.       );
    
  3594.     }
    
  3595.   }
    
  3596. 
    
  3597.   prepareToReadContext(workInProgress, renderLanes);
    
  3598.   const newValue = readContext(context);
    
  3599.   if (enableSchedulingProfiler) {
    
  3600.     markComponentRenderStarted(workInProgress);
    
  3601.   }
    
  3602.   let newChildren;
    
  3603.   if (__DEV__) {
    
  3604.     ReactCurrentOwner.current = workInProgress;
    
  3605.     setIsRendering(true);
    
  3606.     newChildren = render(newValue);
    
  3607.     setIsRendering(false);
    
  3608.   } else {
    
  3609.     newChildren = render(newValue);
    
  3610.   }
    
  3611.   if (enableSchedulingProfiler) {
    
  3612.     markComponentRenderStopped();
    
  3613.   }
    
  3614. 
    
  3615.   // React DevTools reads this flag.
    
  3616.   workInProgress.flags |= PerformedWork;
    
  3617.   reconcileChildren(current, workInProgress, newChildren, renderLanes);
    
  3618.   return workInProgress.child;
    
  3619. }
    
  3620. 
    
  3621. function updateScopeComponent(
    
  3622.   current: null | Fiber,
    
  3623.   workInProgress: Fiber,
    
  3624.   renderLanes: Lanes,
    
  3625. ) {
    
  3626.   const nextProps = workInProgress.pendingProps;
    
  3627.   const nextChildren = nextProps.children;
    
  3628. 
    
  3629.   reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    
  3630.   return workInProgress.child;
    
  3631. }
    
  3632. 
    
  3633. export function markWorkInProgressReceivedUpdate() {
    
  3634.   didReceiveUpdate = true;
    
  3635. }
    
  3636. 
    
  3637. export function checkIfWorkInProgressReceivedUpdate(): boolean {
    
  3638.   return didReceiveUpdate;
    
  3639. }
    
  3640. 
    
  3641. function resetSuspendedCurrentOnMountInLegacyMode(
    
  3642.   current: null | Fiber,
    
  3643.   workInProgress: Fiber,
    
  3644. ) {
    
  3645.   if ((workInProgress.mode & ConcurrentMode) === NoMode) {
    
  3646.     if (current !== null) {
    
  3647.       // A lazy component only mounts if it suspended inside a non-
    
  3648.       // concurrent tree, in an inconsistent state. We want to treat it like
    
  3649.       // a new mount, even though an empty version of it already committed.
    
  3650.       // Disconnect the alternate pointers.
    
  3651.       current.alternate = null;
    
  3652.       workInProgress.alternate = null;
    
  3653.       // Since this is conceptually a new fiber, schedule a Placement effect
    
  3654.       workInProgress.flags |= Placement;
    
  3655.     }
    
  3656.   }
    
  3657. }
    
  3658. 
    
  3659. function bailoutOnAlreadyFinishedWork(
    
  3660.   current: Fiber | null,
    
  3661.   workInProgress: Fiber,
    
  3662.   renderLanes: Lanes,
    
  3663. ): Fiber | null {
    
  3664.   if (current !== null) {
    
  3665.     // Reuse previous dependencies
    
  3666.     workInProgress.dependencies = current.dependencies;
    
  3667.   }
    
  3668. 
    
  3669.   if (enableProfilerTimer) {
    
  3670.     // Don't update "base" render times for bailouts.
    
  3671.     stopProfilerTimerIfRunning(workInProgress);
    
  3672.   }
    
  3673. 
    
  3674.   markSkippedUpdateLanes(workInProgress.lanes);
    
  3675. 
    
  3676.   // Check if the children have any pending work.
    
  3677.   if (!includesSomeLane(renderLanes, workInProgress.childLanes)) {
    
  3678.     // The children don't have any work either. We can skip them.
    
  3679.     // TODO: Once we add back resuming, we should check if the children are
    
  3680.     // a work-in-progress set. If so, we need to transfer their effects.
    
  3681. 
    
  3682.     if (enableLazyContextPropagation && current !== null) {
    
  3683.       // Before bailing out, check if there are any context changes in
    
  3684.       // the children.
    
  3685.       lazilyPropagateParentContextChanges(current, workInProgress, renderLanes);
    
  3686.       if (!includesSomeLane(renderLanes, workInProgress.childLanes)) {
    
  3687.         return null;
    
  3688.       }
    
  3689.     } else {
    
  3690.       return null;
    
  3691.     }
    
  3692.   }
    
  3693. 
    
  3694.   // This fiber doesn't have work, but its subtree does. Clone the child
    
  3695.   // fibers and continue.
    
  3696.   cloneChildFibers(current, workInProgress);
    
  3697.   return workInProgress.child;
    
  3698. }
    
  3699. 
    
  3700. function remountFiber(
    
  3701.   current: Fiber,
    
  3702.   oldWorkInProgress: Fiber,
    
  3703.   newWorkInProgress: Fiber,
    
  3704. ): Fiber | null {
    
  3705.   if (__DEV__) {
    
  3706.     const returnFiber = oldWorkInProgress.return;
    
  3707.     if (returnFiber === null) {
    
  3708.       // eslint-disable-next-line react-internal/prod-error-codes
    
  3709.       throw new Error('Cannot swap the root fiber.');
    
  3710.     }
    
  3711. 
    
  3712.     // Disconnect from the old current.
    
  3713.     // It will get deleted.
    
  3714.     current.alternate = null;
    
  3715.     oldWorkInProgress.alternate = null;
    
  3716. 
    
  3717.     // Connect to the new tree.
    
  3718.     newWorkInProgress.index = oldWorkInProgress.index;
    
  3719.     newWorkInProgress.sibling = oldWorkInProgress.sibling;
    
  3720.     newWorkInProgress.return = oldWorkInProgress.return;
    
  3721.     newWorkInProgress.ref = oldWorkInProgress.ref;
    
  3722. 
    
  3723.     // Replace the child/sibling pointers above it.
    
  3724.     if (oldWorkInProgress === returnFiber.child) {
    
  3725.       returnFiber.child = newWorkInProgress;
    
  3726.     } else {
    
  3727.       let prevSibling = returnFiber.child;
    
  3728.       if (prevSibling === null) {
    
  3729.         // eslint-disable-next-line react-internal/prod-error-codes
    
  3730.         throw new Error('Expected parent to have a child.');
    
  3731.       }
    
  3732.       // $FlowFixMe[incompatible-use] found when upgrading Flow
    
  3733.       while (prevSibling.sibling !== oldWorkInProgress) {
    
  3734.         // $FlowFixMe[incompatible-use] found when upgrading Flow
    
  3735.         prevSibling = prevSibling.sibling;
    
  3736.         if (prevSibling === null) {
    
  3737.           // eslint-disable-next-line react-internal/prod-error-codes
    
  3738.           throw new Error('Expected to find the previous sibling.');
    
  3739.         }
    
  3740.       }
    
  3741.       // $FlowFixMe[incompatible-use] found when upgrading Flow
    
  3742.       prevSibling.sibling = newWorkInProgress;
    
  3743.     }
    
  3744. 
    
  3745.     // Delete the old fiber and place the new one.
    
  3746.     // Since the old fiber is disconnected, we have to schedule it manually.
    
  3747.     const deletions = returnFiber.deletions;
    
  3748.     if (deletions === null) {
    
  3749.       returnFiber.deletions = [current];
    
  3750.       returnFiber.flags |= ChildDeletion;
    
  3751.     } else {
    
  3752.       deletions.push(current);
    
  3753.     }
    
  3754. 
    
  3755.     newWorkInProgress.flags |= Placement;
    
  3756. 
    
  3757.     // Restart work from the new fiber.
    
  3758.     return newWorkInProgress;
    
  3759.   } else {
    
  3760.     throw new Error(
    
  3761.       'Did not expect this call in production. ' +
    
  3762.         'This is a bug in React. Please file an issue.',
    
  3763.     );
    
  3764.   }
    
  3765. }
    
  3766. 
    
  3767. function checkScheduledUpdateOrContext(
    
  3768.   current: Fiber,
    
  3769.   renderLanes: Lanes,
    
  3770. ): boolean {
    
  3771.   // Before performing an early bailout, we must check if there are pending
    
  3772.   // updates or context.
    
  3773.   const updateLanes = current.lanes;
    
  3774.   if (includesSomeLane(updateLanes, renderLanes)) {
    
  3775.     return true;
    
  3776.   }
    
  3777.   // No pending update, but because context is propagated lazily, we need
    
  3778.   // to check for a context change before we bail out.
    
  3779.   if (enableLazyContextPropagation) {
    
  3780.     const dependencies = current.dependencies;
    
  3781.     if (dependencies !== null && checkIfContextChanged(dependencies)) {
    
  3782.       return true;
    
  3783.     }
    
  3784.   }
    
  3785.   return false;
    
  3786. }
    
  3787. 
    
  3788. function attemptEarlyBailoutIfNoScheduledUpdate(
    
  3789.   current: Fiber,
    
  3790.   workInProgress: Fiber,
    
  3791.   renderLanes: Lanes,
    
  3792. ) {
    
  3793.   // This fiber does not have any pending work. Bailout without entering
    
  3794.   // the begin phase. There's still some bookkeeping we that needs to be done
    
  3795.   // in this optimized path, mostly pushing stuff onto the stack.
    
  3796.   switch (workInProgress.tag) {
    
  3797.     case HostRoot:
    
  3798.       pushHostRootContext(workInProgress);
    
  3799.       const root: FiberRoot = workInProgress.stateNode;
    
  3800.       pushRootTransition(workInProgress, root, renderLanes);
    
  3801. 
    
  3802.       if (enableTransitionTracing) {
    
  3803.         pushRootMarkerInstance(workInProgress);
    
  3804.       }
    
  3805. 
    
  3806.       if (enableCache) {
    
  3807.         const cache: Cache = current.memoizedState.cache;
    
  3808.         pushCacheProvider(workInProgress, cache);
    
  3809.       }
    
  3810.       resetHydrationState();
    
  3811.       break;
    
  3812.     case HostSingleton:
    
  3813.     case HostComponent:
    
  3814.       pushHostContext(workInProgress);
    
  3815.       break;
    
  3816.     case ClassComponent: {
    
  3817.       const Component = workInProgress.type;
    
  3818.       if (isLegacyContextProvider(Component)) {
    
  3819.         pushLegacyContextProvider(workInProgress);
    
  3820.       }
    
  3821.       break;
    
  3822.     }
    
  3823.     case HostPortal:
    
  3824.       pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
    
  3825.       break;
    
  3826.     case ContextProvider: {
    
  3827.       const newValue = workInProgress.memoizedProps.value;
    
  3828.       const context: ReactContext<any> = workInProgress.type._context;
    
  3829.       pushProvider(workInProgress, context, newValue);
    
  3830.       break;
    
  3831.     }
    
  3832.     case Profiler:
    
  3833.       if (enableProfilerTimer) {
    
  3834.         // Profiler should only call onRender when one of its descendants actually rendered.
    
  3835.         const hasChildWork = includesSomeLane(
    
  3836.           renderLanes,
    
  3837.           workInProgress.childLanes,
    
  3838.         );
    
  3839.         if (hasChildWork) {
    
  3840.           workInProgress.flags |= Update;
    
  3841.         }
    
  3842. 
    
  3843.         if (enableProfilerCommitHooks) {
    
  3844.           // Reset effect durations for the next eventual effect phase.
    
  3845.           // These are reset during render to allow the DevTools commit hook a chance to read them,
    
  3846.           const stateNode = workInProgress.stateNode;
    
  3847.           stateNode.effectDuration = 0;
    
  3848.           stateNode.passiveEffectDuration = 0;
    
  3849.         }
    
  3850.       }
    
  3851.       break;
    
  3852.     case SuspenseComponent: {
    
  3853.       const state: SuspenseState | null = workInProgress.memoizedState;
    
  3854.       if (state !== null) {
    
  3855.         if (state.dehydrated !== null) {
    
  3856.           // We're not going to render the children, so this is just to maintain
    
  3857.           // push/pop symmetry
    
  3858.           pushPrimaryTreeSuspenseHandler(workInProgress);
    
  3859.           // We know that this component will suspend again because if it has
    
  3860.           // been unsuspended it has committed as a resolved Suspense component.
    
  3861.           // If it needs to be retried, it should have work scheduled on it.
    
  3862.           workInProgress.flags |= DidCapture;
    
  3863.           // We should never render the children of a dehydrated boundary until we
    
  3864.           // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork.
    
  3865.           return null;
    
  3866.         }
    
  3867. 
    
  3868.         // If this boundary is currently timed out, we need to decide
    
  3869.         // whether to retry the primary children, or to skip over it and
    
  3870.         // go straight to the fallback. Check the priority of the primary
    
  3871.         // child fragment.
    
  3872.         const primaryChildFragment: Fiber = (workInProgress.child: any);
    
  3873.         const primaryChildLanes = primaryChildFragment.childLanes;
    
  3874.         if (includesSomeLane(renderLanes, primaryChildLanes)) {
    
  3875.           // The primary children have pending work. Use the normal path
    
  3876.           // to attempt to render the primary children again.
    
  3877.           return updateSuspenseComponent(current, workInProgress, renderLanes);
    
  3878.         } else {
    
  3879.           // The primary child fragment does not have pending work marked
    
  3880.           // on it
    
  3881.           pushPrimaryTreeSuspenseHandler(workInProgress);
    
  3882.           // The primary children do not have pending work with sufficient
    
  3883.           // priority. Bailout.
    
  3884.           const child = bailoutOnAlreadyFinishedWork(
    
  3885.             current,
    
  3886.             workInProgress,
    
  3887.             renderLanes,
    
  3888.           );
    
  3889.           if (child !== null) {
    
  3890.             // The fallback children have pending work. Skip over the
    
  3891.             // primary children and work on the fallback.
    
  3892.             return child.sibling;
    
  3893.           } else {
    
  3894.             // Note: We can return `null` here because we already checked
    
  3895.             // whether there were nested context consumers, via the call to
    
  3896.             // `bailoutOnAlreadyFinishedWork` above.
    
  3897.             return null;
    
  3898.           }
    
  3899.         }
    
  3900.       } else {
    
  3901.         pushPrimaryTreeSuspenseHandler(workInProgress);
    
  3902.       }
    
  3903.       break;
    
  3904.     }
    
  3905.     case SuspenseListComponent: {
    
  3906.       const didSuspendBefore = (current.flags & DidCapture) !== NoFlags;
    
  3907. 
    
  3908.       let hasChildWork = includesSomeLane(
    
  3909.         renderLanes,
    
  3910.         workInProgress.childLanes,
    
  3911.       );
    
  3912. 
    
  3913.       if (enableLazyContextPropagation && !hasChildWork) {
    
  3914.         // Context changes may not have been propagated yet. We need to do
    
  3915.         // that now, before we can decide whether to bail out.
    
  3916.         // TODO: We use `childLanes` as a heuristic for whether there is
    
  3917.         // remaining work in a few places, including
    
  3918.         // `bailoutOnAlreadyFinishedWork` and
    
  3919.         // `updateDehydratedSuspenseComponent`. We should maybe extract this
    
  3920.         // into a dedicated function.
    
  3921.         lazilyPropagateParentContextChanges(
    
  3922.           current,
    
  3923.           workInProgress,
    
  3924.           renderLanes,
    
  3925.         );
    
  3926.         hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes);
    
  3927.       }
    
  3928. 
    
  3929.       if (didSuspendBefore) {
    
  3930.         if (hasChildWork) {
    
  3931.           // If something was in fallback state last time, and we have all the
    
  3932.           // same children then we're still in progressive loading state.
    
  3933.           // Something might get unblocked by state updates or retries in the
    
  3934.           // tree which will affect the tail. So we need to use the normal
    
  3935.           // path to compute the correct tail.
    
  3936.           return updateSuspenseListComponent(
    
  3937.             current,
    
  3938.             workInProgress,
    
  3939.             renderLanes,
    
  3940.           );
    
  3941.         }
    
  3942.         // If none of the children had any work, that means that none of
    
  3943.         // them got retried so they'll still be blocked in the same way
    
  3944.         // as before. We can fast bail out.
    
  3945.         workInProgress.flags |= DidCapture;
    
  3946.       }
    
  3947. 
    
  3948.       // If nothing suspended before and we're rendering the same children,
    
  3949.       // then the tail doesn't matter. Anything new that suspends will work
    
  3950.       // in the "together" mode, so we can continue from the state we had.
    
  3951.       const renderState = workInProgress.memoizedState;
    
  3952.       if (renderState !== null) {
    
  3953.         // Reset to the "together" mode in case we've started a different
    
  3954.         // update in the past but didn't complete it.
    
  3955.         renderState.rendering = null;
    
  3956.         renderState.tail = null;
    
  3957.         renderState.lastEffect = null;
    
  3958.       }
    
  3959.       pushSuspenseListContext(workInProgress, suspenseStackCursor.current);
    
  3960. 
    
  3961.       if (hasChildWork) {
    
  3962.         break;
    
  3963.       } else {
    
  3964.         // If none of the children had any work, that means that none of
    
  3965.         // them got retried so they'll still be blocked in the same way
    
  3966.         // as before. We can fast bail out.
    
  3967.         return null;
    
  3968.       }
    
  3969.     }
    
  3970.     case OffscreenComponent:
    
  3971.     case LegacyHiddenComponent: {
    
  3972.       // Need to check if the tree still needs to be deferred. This is
    
  3973.       // almost identical to the logic used in the normal update path,
    
  3974.       // so we'll just enter that. The only difference is we'll bail out
    
  3975.       // at the next level instead of this one, because the child props
    
  3976.       // have not changed. Which is fine.
    
  3977.       // TODO: Probably should refactor `beginWork` to split the bailout
    
  3978.       // path from the normal path. I'm tempted to do a labeled break here
    
  3979.       // but I won't :)
    
  3980.       workInProgress.lanes = NoLanes;
    
  3981.       return updateOffscreenComponent(current, workInProgress, renderLanes);
    
  3982.     }
    
  3983.     case CacheComponent: {
    
  3984.       if (enableCache) {
    
  3985.         const cache: Cache = current.memoizedState.cache;
    
  3986.         pushCacheProvider(workInProgress, cache);
    
  3987.       }
    
  3988.       break;
    
  3989.     }
    
  3990.     case TracingMarkerComponent: {
    
  3991.       if (enableTransitionTracing) {
    
  3992.         const instance: TracingMarkerInstance | null = workInProgress.stateNode;
    
  3993.         if (instance !== null) {
    
  3994.           pushMarkerInstance(workInProgress, instance);
    
  3995.         }
    
  3996.       }
    
  3997.     }
    
  3998.   }
    
  3999.   return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
    
  4000. }
    
  4001. 
    
  4002. function beginWork(
    
  4003.   current: Fiber | null,
    
  4004.   workInProgress: Fiber,
    
  4005.   renderLanes: Lanes,
    
  4006. ): Fiber | null {
    
  4007.   if (__DEV__) {
    
  4008.     if (workInProgress._debugNeedsRemount && current !== null) {
    
  4009.       // This will restart the begin phase with a new fiber.
    
  4010.       return remountFiber(
    
  4011.         current,
    
  4012.         workInProgress,
    
  4013.         createFiberFromTypeAndProps(
    
  4014.           workInProgress.type,
    
  4015.           workInProgress.key,
    
  4016.           workInProgress.pendingProps,
    
  4017.           workInProgress._debugSource || null,
    
  4018.           workInProgress._debugOwner || null,
    
  4019.           workInProgress.mode,
    
  4020.           workInProgress.lanes,
    
  4021.         ),
    
  4022.       );
    
  4023.     }
    
  4024.   }
    
  4025. 
    
  4026.   if (current !== null) {
    
  4027.     const oldProps = current.memoizedProps;
    
  4028.     const newProps = workInProgress.pendingProps;
    
  4029. 
    
  4030.     if (
    
  4031.       oldProps !== newProps ||
    
  4032.       hasLegacyContextChanged() ||
    
  4033.       // Force a re-render if the implementation changed due to hot reload:
    
  4034.       (__DEV__ ? workInProgress.type !== current.type : false)
    
  4035.     ) {
    
  4036.       // If props or context changed, mark the fiber as having performed work.
    
  4037.       // This may be unset if the props are determined to be equal later (memo).
    
  4038.       didReceiveUpdate = true;
    
  4039.     } else {
    
  4040.       // Neither props nor legacy context changes. Check if there's a pending
    
  4041.       // update or context change.
    
  4042.       const hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(
    
  4043.         current,
    
  4044.         renderLanes,
    
  4045.       );
    
  4046.       if (
    
  4047.         !hasScheduledUpdateOrContext &&
    
  4048.         // If this is the second pass of an error or suspense boundary, there
    
  4049.         // may not be work scheduled on `current`, so we check for this flag.
    
  4050.         (workInProgress.flags & DidCapture) === NoFlags
    
  4051.       ) {
    
  4052.         // No pending updates or context. Bail out now.
    
  4053.         didReceiveUpdate = false;
    
  4054.         return attemptEarlyBailoutIfNoScheduledUpdate(
    
  4055.           current,
    
  4056.           workInProgress,
    
  4057.           renderLanes,
    
  4058.         );
    
  4059.       }
    
  4060.       if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) {
    
  4061.         // This is a special case that only exists for legacy mode.
    
  4062.         // See https://github.com/facebook/react/pull/19216.
    
  4063.         didReceiveUpdate = true;
    
  4064.       } else {
    
  4065.         // An update was scheduled on this fiber, but there are no new props
    
  4066.         // nor legacy context. Set this to false. If an update queue or context
    
  4067.         // consumer produces a changed value, it will set this to true. Otherwise,
    
  4068.         // the component will assume the children have not changed and bail out.
    
  4069.         didReceiveUpdate = false;
    
  4070.       }
    
  4071.     }
    
  4072.   } else {
    
  4073.     didReceiveUpdate = false;
    
  4074. 
    
  4075.     if (getIsHydrating() && isForkedChild(workInProgress)) {
    
  4076.       // Check if this child belongs to a list of muliple children in
    
  4077.       // its parent.
    
  4078.       //
    
  4079.       // In a true multi-threaded implementation, we would render children on
    
  4080.       // parallel threads. This would represent the beginning of a new render
    
  4081.       // thread for this subtree.
    
  4082.       //
    
  4083.       // We only use this for id generation during hydration, which is why the
    
  4084.       // logic is located in this special branch.
    
  4085.       const slotIndex = workInProgress.index;
    
  4086.       const numberOfForks = getForksAtLevel(workInProgress);
    
  4087.       pushTreeId(workInProgress, numberOfForks, slotIndex);
    
  4088.     }
    
  4089.   }
    
  4090. 
    
  4091.   // Before entering the begin phase, clear pending update priority.
    
  4092.   // TODO: This assumes that we're about to evaluate the component and process
    
  4093.   // the update queue. However, there's an exception: SimpleMemoComponent
    
  4094.   // sometimes bails out later in the begin phase. This indicates that we should
    
  4095.   // move this assignment out of the common path and into each branch.
    
  4096.   workInProgress.lanes = NoLanes;
    
  4097. 
    
  4098.   switch (workInProgress.tag) {
    
  4099.     case IndeterminateComponent: {
    
  4100.       return mountIndeterminateComponent(
    
  4101.         current,
    
  4102.         workInProgress,
    
  4103.         workInProgress.type,
    
  4104.         renderLanes,
    
  4105.       );
    
  4106.     }
    
  4107.     case LazyComponent: {
    
  4108.       const elementType = workInProgress.elementType;
    
  4109.       return mountLazyComponent(
    
  4110.         current,
    
  4111.         workInProgress,
    
  4112.         elementType,
    
  4113.         renderLanes,
    
  4114.       );
    
  4115.     }
    
  4116.     case FunctionComponent: {
    
  4117.       const Component = workInProgress.type;
    
  4118.       const unresolvedProps = workInProgress.pendingProps;
    
  4119.       const resolvedProps =
    
  4120.         workInProgress.elementType === Component
    
  4121.           ? unresolvedProps
    
  4122.           : resolveDefaultProps(Component, unresolvedProps);
    
  4123.       return updateFunctionComponent(
    
  4124.         current,
    
  4125.         workInProgress,
    
  4126.         Component,
    
  4127.         resolvedProps,
    
  4128.         renderLanes,
    
  4129.       );
    
  4130.     }
    
  4131.     case ClassComponent: {
    
  4132.       const Component = workInProgress.type;
    
  4133.       const unresolvedProps = workInProgress.pendingProps;
    
  4134.       const resolvedProps =
    
  4135.         workInProgress.elementType === Component
    
  4136.           ? unresolvedProps
    
  4137.           : resolveDefaultProps(Component, unresolvedProps);
    
  4138.       return updateClassComponent(
    
  4139.         current,
    
  4140.         workInProgress,
    
  4141.         Component,
    
  4142.         resolvedProps,
    
  4143.         renderLanes,
    
  4144.       );
    
  4145.     }
    
  4146.     case HostRoot:
    
  4147.       return updateHostRoot(current, workInProgress, renderLanes);
    
  4148.     case HostHoistable:
    
  4149.       if (enableFloat && supportsResources) {
    
  4150.         return updateHostHoistable(current, workInProgress, renderLanes);
    
  4151.       }
    
  4152.     // Fall through
    
  4153.     case HostSingleton:
    
  4154.       if (enableHostSingletons && supportsSingletons) {
    
  4155.         return updateHostSingleton(current, workInProgress, renderLanes);
    
  4156.       }
    
  4157.     // Fall through
    
  4158.     case HostComponent:
    
  4159.       return updateHostComponent(current, workInProgress, renderLanes);
    
  4160.     case HostText:
    
  4161.       return updateHostText(current, workInProgress);
    
  4162.     case SuspenseComponent:
    
  4163.       return updateSuspenseComponent(current, workInProgress, renderLanes);
    
  4164.     case HostPortal:
    
  4165.       return updatePortalComponent(current, workInProgress, renderLanes);
    
  4166.     case ForwardRef: {
    
  4167.       const type = workInProgress.type;
    
  4168.       const unresolvedProps = workInProgress.pendingProps;
    
  4169.       const resolvedProps =
    
  4170.         workInProgress.elementType === type
    
  4171.           ? unresolvedProps
    
  4172.           : resolveDefaultProps(type, unresolvedProps);
    
  4173.       return updateForwardRef(
    
  4174.         current,
    
  4175.         workInProgress,
    
  4176.         type,
    
  4177.         resolvedProps,
    
  4178.         renderLanes,
    
  4179.       );
    
  4180.     }
    
  4181.     case Fragment:
    
  4182.       return updateFragment(current, workInProgress, renderLanes);
    
  4183.     case Mode:
    
  4184.       return updateMode(current, workInProgress, renderLanes);
    
  4185.     case Profiler:
    
  4186.       return updateProfiler(current, workInProgress, renderLanes);
    
  4187.     case ContextProvider:
    
  4188.       return updateContextProvider(current, workInProgress, renderLanes);
    
  4189.     case ContextConsumer:
    
  4190.       return updateContextConsumer(current, workInProgress, renderLanes);
    
  4191.     case MemoComponent: {
    
  4192.       const type = workInProgress.type;
    
  4193.       const unresolvedProps = workInProgress.pendingProps;
    
  4194.       // Resolve outer props first, then resolve inner props.
    
  4195.       let resolvedProps = resolveDefaultProps(type, unresolvedProps);
    
  4196.       if (__DEV__) {
    
  4197.         if (workInProgress.type !== workInProgress.elementType) {
    
  4198.           const outerPropTypes = type.propTypes;
    
  4199.           if (outerPropTypes) {
    
  4200.             checkPropTypes(
    
  4201.               outerPropTypes,
    
  4202.               resolvedProps, // Resolved for outer only
    
  4203.               'prop',
    
  4204.               getComponentNameFromType(type),
    
  4205.             );
    
  4206.           }
    
  4207.         }
    
  4208.       }
    
  4209.       resolvedProps = resolveDefaultProps(type.type, resolvedProps);
    
  4210.       return updateMemoComponent(
    
  4211.         current,
    
  4212.         workInProgress,
    
  4213.         type,
    
  4214.         resolvedProps,
    
  4215.         renderLanes,
    
  4216.       );
    
  4217.     }
    
  4218.     case SimpleMemoComponent: {
    
  4219.       return updateSimpleMemoComponent(
    
  4220.         current,
    
  4221.         workInProgress,
    
  4222.         workInProgress.type,
    
  4223.         workInProgress.pendingProps,
    
  4224.         renderLanes,
    
  4225.       );
    
  4226.     }
    
  4227.     case IncompleteClassComponent: {
    
  4228.       const Component = workInProgress.type;
    
  4229.       const unresolvedProps = workInProgress.pendingProps;
    
  4230.       const resolvedProps =
    
  4231.         workInProgress.elementType === Component
    
  4232.           ? unresolvedProps
    
  4233.           : resolveDefaultProps(Component, unresolvedProps);
    
  4234.       return mountIncompleteClassComponent(
    
  4235.         current,
    
  4236.         workInProgress,
    
  4237.         Component,
    
  4238.         resolvedProps,
    
  4239.         renderLanes,
    
  4240.       );
    
  4241.     }
    
  4242.     case SuspenseListComponent: {
    
  4243.       return updateSuspenseListComponent(current, workInProgress, renderLanes);
    
  4244.     }
    
  4245.     case ScopeComponent: {
    
  4246.       if (enableScopeAPI) {
    
  4247.         return updateScopeComponent(current, workInProgress, renderLanes);
    
  4248.       }
    
  4249.       break;
    
  4250.     }
    
  4251.     case OffscreenComponent: {
    
  4252.       return updateOffscreenComponent(current, workInProgress, renderLanes);
    
  4253.     }
    
  4254.     case LegacyHiddenComponent: {
    
  4255.       if (enableLegacyHidden) {
    
  4256.         return updateLegacyHiddenComponent(
    
  4257.           current,
    
  4258.           workInProgress,
    
  4259.           renderLanes,
    
  4260.         );
    
  4261.       }
    
  4262.       break;
    
  4263.     }
    
  4264.     case CacheComponent: {
    
  4265.       if (enableCache) {
    
  4266.         return updateCacheComponent(current, workInProgress, renderLanes);
    
  4267.       }
    
  4268.       break;
    
  4269.     }
    
  4270.     case TracingMarkerComponent: {
    
  4271.       if (enableTransitionTracing) {
    
  4272.         return updateTracingMarkerComponent(
    
  4273.           current,
    
  4274.           workInProgress,
    
  4275.           renderLanes,
    
  4276.         );
    
  4277.       }
    
  4278.       break;
    
  4279.     }
    
  4280.   }
    
  4281. 
    
  4282.   throw new Error(
    
  4283.     `Unknown unit of work tag (${workInProgress.tag}). This error is likely caused by a bug in ` +
    
  4284.       'React. Please file an issue.',
    
  4285.   );
    
  4286. }
    
  4287. 
    
  4288. export {beginWork};