@@ -69,7 +69,7 @@ function _assertThisInitialized(self) {
6969 return self;
7070}
7171
72- var ReactVersion = "18.3.0-www-classic-dfeb256e ";
72+ var ReactVersion = "18.3.0-www-classic-e4add0e3 ";
7373
7474var LegacyRoot = 0;
7575var ConcurrentRoot = 1;
@@ -543,11 +543,12 @@ var Visibility =
543543 8192;
544544var StoreConsistency =
545545 /* */
546- 16384; // It's OK to reuse this bit because these flags are mutually exclusive for
546+ 16384; // It's OK to reuse these bits because these flags are mutually exclusive for
547547// different fiber types. We should really be doing this for as many flags as
548548// possible, because we're about to run out of bits.
549549
550550var ScheduleRetry = StoreConsistency;
551+ var ShouldSuspendCommit = Visibility;
551552var LifecycleEffectMask =
552553 Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit)
553554
@@ -587,8 +588,8 @@ var LayoutStatic =
587588var PassiveStatic =
588589 /* */
589590 8388608;
590- var SuspenseyCommit =
591- /* */
591+ var MaySuspendCommit =
592+ /* */
592593 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`.
593594
594595var PlacementDEV =
@@ -624,7 +625,7 @@ var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that
624625// This allows certain concepts to persist without recalculating them,
625626// e.g. whether a subtree contains passive effects or portals.
626627
627- var StaticMask = LayoutStatic | PassiveStatic | RefStatic | SuspenseyCommit ;
628+ var StaticMask = LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit ;
628629
629630var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner;
630631function getNearestMountedFiber(fiber) {
@@ -2934,9 +2935,6 @@ function unhideTextInstance(textInstance, text) {
29342935function getInstanceFromNode(node) {
29352936 throw new Error("Not implemented.");
29362937}
2937- function maySuspendCommit(type, props) {
2938- return false;
2939- }
29402938function preloadInstance(type, props) {
29412939 // Return true to indicate it's already loaded
29422940 return true;
@@ -5590,13 +5588,6 @@ function trackUsedThenable(thenableState, thenable, index) {
55905588 }
55915589 }
55925590}
5593- function suspendCommit() {
5594- // This extra indirection only exists so it can handle passing
5595- // noopSuspenseyCommitThenable through to throwException.
5596- // TODO: Factor the thenable check out of throwException
5597- suspendedThenable = noopSuspenseyCommitThenable;
5598- throw SuspenseyCommitException;
5599- } // This is used to track the actual thenable that suspended so it can be
56005591// passed to the rest of the Suspense implementation — which, for historical
56015592// reasons, expects to receive a thenable.
56025593
@@ -17697,7 +17688,11 @@ function updateHostComponent(
1769717688 markUpdate(workInProgress);
1769817689 }
1769917690 }
17700- } // TODO: This should ideally move to begin phase, but currently the instance is
17691+ } // This function must be called at the very end of the complete phase, because
17692+ // it might throw to suspend, and if the resource immediately loads, the work
17693+ // loop will resume rendering as if the work-in-progress completed. So it must
17694+ // fully complete.
17695+ // TODO: This should ideally move to begin phase, but currently the instance is
1770117696// not created until the complete phase. For our existing use cases, host nodes
1770217697// that suspend don't have children, so it doesn't matter. But that might not
1770317698// always be true in the future.
@@ -17708,28 +17703,16 @@ function preloadInstanceAndSuspendIfNeeded(
1770817703 props,
1770917704 renderLanes
1771017705) {
17711- workInProgress.flags |= SuspenseyCommit; // Check if we're rendering at a "non-urgent" priority. This is the same
17712- // check that `useDeferredValue` does to determine whether it needs to
17713- // defer. This is partly for gradual adoption purposes (i.e. shouldn't start
17714- // suspending until you opt in with startTransition or Suspense) but it
17715- // also happens to be the desired behavior for the concrete use cases we've
17716- // thought of so far, like CSS loading, fonts, images, etc.
17717- // TODO: We may decide to expose a way to force a fallback even during a
17718- // sync update.
17719-
17720- if (!includesOnlyNonUrgentLanes(renderLanes));
17721- else {
17722- // Preload the instance
17723- var isReady = preloadInstance();
17724-
17725- if (!isReady) {
17726- if (shouldRemainOnPreviousScreen());
17727- else {
17728- // Trigger a fallback rather than block the render.
17729- suspendCommit();
17730- }
17731- }
17732- }
17706+ {
17707+ // If this flag was set previously, we can remove it. The flag
17708+ // represents whether this particular set of props might ever need to
17709+ // suspend. The safest thing to do is for maySuspendCommit to always
17710+ // return true, but if the renderer is reasonably confident that the
17711+ // underlying resource won't be evicted, it can return false as a
17712+ // performance optimization.
17713+ workInProgress.flags &= ~MaySuspendCommit;
17714+ return;
17715+ } // Mark this fiber with a flag. This gets set on all host instances
1773317716}
1773417717
1773517718function scheduleRetryEffect(workInProgress, retryQueue) {
@@ -18160,12 +18143,10 @@ function completeWork(current, workInProgress, renderLanes) {
1816018143
1816118144 case HostComponent: {
1816218145 popHostContext(workInProgress);
18163- var _type = workInProgress.type;
18164-
18165- var _maySuspend = maySuspendCommit();
18146+ var _type2 = workInProgress.type;
1816618147
1816718148 if (current !== null && workInProgress.stateNode != null) {
18168- updateHostComponent(current, workInProgress, _type , newProps);
18149+ updateHostComponent(current, workInProgress, _type2 , newProps);
1816918150
1817018151 if (current.ref !== workInProgress.ref) {
1817118152 markRef(workInProgress);
@@ -18201,7 +18182,7 @@ function completeWork(current, workInProgress, renderLanes) {
1820118182 } else {
1820218183 getRootHostContainer();
1820318184
18204- var _instance3 = createInstance(_type , newProps);
18185+ var _instance3 = createInstance(_type2 , newProps);
1820518186
1820618187 appendAllChildren(_instance3, workInProgress);
1820718188 workInProgress.stateNode = _instance3; // Certain renderers require commit-time effects for initial mount.
@@ -18218,17 +18199,7 @@ function completeWork(current, workInProgress, renderLanes) {
1821818199 // will resume rendering as if the work-in-progress completed. So it must
1821918200 // fully complete.
1822018201
18221- if (_maySuspend) {
18222- preloadInstanceAndSuspendIfNeeded(
18223- workInProgress,
18224- _type,
18225- newProps,
18226- renderLanes
18227- );
18228- } else {
18229- workInProgress.flags &= ~SuspenseyCommit;
18230- }
18231-
18202+ preloadInstanceAndSuspendIfNeeded(workInProgress);
1823218203 return null;
1823318204 }
1823418205
@@ -22603,13 +22574,24 @@ function commitPassiveUnmountEffects(finishedWork) {
2260322574 setCurrentFiber(finishedWork);
2260422575 commitPassiveUnmountOnFiber(finishedWork);
2260522576 resetCurrentFiber();
22606- }
22577+ } // If we're inside a brand new tree, or a tree that was already visible, then we
22578+ // should only suspend host components that have a ShouldSuspendCommit flag.
22579+ // Components without it haven't changed since the last commit, so we can skip
22580+ // over those.
22581+ //
22582+ // When we enter a tree that is being revealed (going from hidden -> visible),
22583+ // we need to suspend _any_ component that _may_ suspend. Even if they're
22584+ // already in the "current" tree. Because their visibility has changed, the
22585+ // browser may not have prerendered them yet. So we check the MaySuspendCommit
22586+ // flag instead.
22587+
22588+ var suspenseyCommitFlag = ShouldSuspendCommit;
2260722589function accumulateSuspenseyCommit(finishedWork) {
2260822590 accumulateSuspenseyCommitOnFiber(finishedWork);
2260922591}
2261022592
2261122593function recursivelyAccumulateSuspenseyCommit(parentFiber) {
22612- if (parentFiber.subtreeFlags & SuspenseyCommit ) {
22594+ if (parentFiber.subtreeFlags & suspenseyCommitFlag ) {
2261322595 var child = parentFiber.child;
2261422596
2261522597 while (child !== null) {
@@ -22624,7 +22606,7 @@ function accumulateSuspenseyCommitOnFiber(fiber) {
2262422606 case HostHoistable: {
2262522607 recursivelyAccumulateSuspenseyCommit(fiber);
2262622608
22627- if (fiber.flags & SuspenseyCommit ) {
22609+ if (fiber.flags & suspenseyCommitFlag ) {
2262822610 if (fiber.memoizedState !== null) {
2262922611 suspendResource();
2263022612 }
@@ -22640,8 +22622,36 @@ function accumulateSuspenseyCommitOnFiber(fiber) {
2264022622 }
2264122623
2264222624 case HostRoot:
22643- case HostPortal:
22644- // eslint-disable-next-line-no-fallthrough
22625+ case HostPortal: {
22626+ {
22627+ recursivelyAccumulateSuspenseyCommit(fiber);
22628+ }
22629+
22630+ break;
22631+ }
22632+
22633+ case OffscreenComponent: {
22634+ var isHidden = fiber.memoizedState !== null;
22635+
22636+ if (isHidden);
22637+ else {
22638+ var current = fiber.alternate;
22639+ var wasHidden = current !== null && current.memoizedState !== null;
22640+
22641+ if (wasHidden) {
22642+ // This tree is being revealed. Visit all newly visible suspensey
22643+ // instances, even if they're in the current tree.
22644+ var prevFlags = suspenseyCommitFlag;
22645+ suspenseyCommitFlag = MaySuspendCommit;
22646+ recursivelyAccumulateSuspenseyCommit(fiber);
22647+ suspenseyCommitFlag = prevFlags;
22648+ } else {
22649+ recursivelyAccumulateSuspenseyCommit(fiber);
22650+ }
22651+ }
22652+
22653+ break;
22654+ }
2264522655
2264622656 default: {
2264722657 recursivelyAccumulateSuspenseyCommit(fiber);
@@ -24707,15 +24717,24 @@ function shouldRemainOnPreviousScreen() {
2470724717
2470824718 if (handler === null);
2470924719 else {
24710- if (includesOnlyRetries(workInProgressRootRenderLanes)) {
24720+ if (
24721+ includesOnlyRetries(workInProgressRootRenderLanes) || // In this context, an OffscreenLane counts as a Retry
24722+ // TODO: It's become increasingly clear that Retries and Offscreen are
24723+ // deeply connected. They probably can be unified further.
24724+ includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
24725+ ) {
2471124726 // During a retry, we can suspend rendering if the nearest Suspense boundary
2471224727 // is the boundary of the "shell", because we're guaranteed not to block
2471324728 // any new content from appearing.
24729+ //
24730+ // The reason we must check if this is a retry is because it guarantees
24731+ // that suspending the work loop won't block an actual update, because
24732+ // retries don't "update" anything; they fill in fallbacks that were left
24733+ // behind by a previous transition.
2471424734 return handler === getShellBoundary();
2471524735 }
2471624736 } // For all other Lanes besides Transitions and Retries, we should not wait
2471724737 // for the data to load.
24718- // TODO: We should wait during Offscreen prerendering, too.
2471924738
2472024739 return false;
2472124740}
0 commit comments