@samitouri / QOS-React-2 / commits / 72965f3615

[DevTools] Restore reconciling Suspense stack after fallback was reconciled (#34168)

Sebastian "Sebbie" Silbermann committed Aug 11, 2025 at 17:12 UTC 72965f361547da79fcd4310ae13e22d6abb274a6
1 file changed +37 -33
packages/react-devtools-shared/src/backend/fiber/renderer.js
+37 -33
@@ -4162,7 +4162,7 @@ export function attach(
4162 const stashedSuspenseParent = reconcilingParentSuspenseNode;
4163 const stashedSuspensePrevious = previouslyReconciledSiblingSuspenseNode;
4164 const stashedSuspenseRemaining = remainingReconcilingChildrenSuspenseNodes;
4165 - let shouldPopSuspenseNode = false;
4165 + let shouldMeasureSuspenseNode = false;
4166 let previousSuspendedBy = null;
4167 if (fiberInstance !== null) {
4168 previousSuspendedBy = fiberInstance.suspendedBy;
@@ -4192,7 +4192,7 @@ export function attach(
4192 previouslyReconciledSiblingSuspenseNode = null;
4193 remainingReconcilingChildrenSuspenseNodes = suspenseNode.firstChild;
4194 suspenseNode.firstChild = null;
4195 - shouldPopSuspenseNode = true;
4195 + shouldMeasureSuspenseNode = true;
4196 }
4197 }
4198 try {
@@ -4379,38 +4379,40 @@ export function attach(
4379 0,
4380 );
4381
4382 - // Next, we'll pop back out of the SuspenseNode that we added above and now we'll
4383 - // reconcile the fallback, reconciling anything by inserting into the parent SuspenseNode.
4384 - // Since the fallback conceptually blocks the parent.
4385 - reconcilingParentSuspenseNode = stashedSuspenseParent;
4386 - previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;
4387 - remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;
4388 - shouldPopSuspenseNode = false;
4382 + shouldMeasureSuspenseNode = false;
4383 if (nextFallbackFiber !== null) {
4390 - updateFlags |= updateVirtualChildrenRecursively(
4391 - nextFallbackFiber,
4392 - null,
4393 - prevFallbackFiber,
4394 - traceNearestHostComponentUpdate,
4395 - 0,
4396 - );
4397 - } else if (
4398 - nextFiber.memoizedState === null &&
4399 - fiberInstance.suspenseNode !== null
4400 - ) {
4401 - if (!isInDisconnectedSubtree) {
4402 - // Measure this Suspense node in case it changed. We don't update the rect while
4403 - // we're inside a disconnected subtree nor if we are the Suspense boundary that
4404 - // is suspended. This lets us keep the rectangle of the displayed content while
4405 - // we're suspended to visualize the resulting state.
4406 - const suspenseNode = fiberInstance.suspenseNode;
4407 - const prevRects = suspenseNode.rects;
4408 - const nextRects = measureInstance(fiberInstance);
4409 - if (!areEqualRects(prevRects, nextRects)) {
4410 - suspenseNode.rects = nextRects;
4411 - recordSuspenseResize(suspenseNode);
4412 - }
4384 + const fallbackStashedSuspenseParent = reconcilingParentSuspenseNode;
4385 + const fallbackStashedSuspensePrevious =
4386 + previouslyReconciledSiblingSuspenseNode;
4387 + const fallbackStashedSuspenseRemaining =
4388 + remainingReconcilingChildrenSuspenseNodes;
4389 + // Next, we'll pop back out of the SuspenseNode that we added above and now we'll
4390 + // reconcile the fallback, reconciling anything by inserting into the parent SuspenseNode.
4391 + // Since the fallback conceptually blocks the parent.
4392 + reconcilingParentSuspenseNode = stashedSuspenseParent;
4393 + previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;
4394 + remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;
4395 + try {
4396 + updateFlags |= updateVirtualChildrenRecursively(
4397 + nextFallbackFiber,
4398 + null,
4399 + prevFallbackFiber,
4400 + traceNearestHostComponentUpdate,
4401 + 0,
4402 + );
4403 + } finally {
4404 + reconcilingParentSuspenseNode = fallbackStashedSuspenseParent;
4405 + previouslyReconciledSiblingSuspenseNode =
4406 + fallbackStashedSuspensePrevious;
4407 + remainingReconcilingChildrenSuspenseNodes =
4408 + fallbackStashedSuspenseRemaining;
4409 }
4410 + } else if (nextFiber.memoizedState === null) {
4411 + // Measure this Suspense node in case it changed. We don't update the rect while
4412 + // we're inside a disconnected subtree nor if we are the Suspense boundary that
4413 + // is suspended. This lets us keep the rectangle of the displayed content while
4414 + // we're suspended to visualize the resulting state.
4415 + shouldMeasureSuspenseNode = !isInDisconnectedSubtree;
4416 }
4417 } else {
4418 // Common case: Primary -> Primary.
@@ -4519,7 +4521,7 @@ export function attach(
4521 reconcilingParent = stashedParent;
4522 previouslyReconciledSibling = stashedPrevious;
4523 remainingReconcilingChildren = stashedRemaining;
4522 - if (shouldPopSuspenseNode) {
4524 + if (shouldMeasureSuspenseNode) {
4525 if (
4526 !isInDisconnectedSubtree &&
4527 reconcilingParentSuspenseNode !== null
@@ -4535,6 +4537,8 @@ export function attach(
4537 recordSuspenseResize(suspenseNode);
4538 }
4539 }
4540 + }
4541 + if (fiberInstance.suspenseNode !== null) {
4542 reconcilingParentSuspenseNode = stashedSuspenseParent;
4543 previouslyReconciledSiblingSuspenseNode = stashedSuspensePrevious;
4544 remainingReconcilingChildrenSuspenseNodes = stashedSuspenseRemaining;