Skip to content

Commit 9784cb3

Browse files
authored
[DevTools] No suspending above the root (facebook#34055)
Follow up to facebook#34050. It's not actually possible to suspend *above* the root since even if you suspend in the first child position, you're still suspending the HostRoot which always has a corresponding FiberInstance and SuspenseNode.
1 parent dcf2a6f commit 9784cb3

File tree

1 file changed

+32
-29
lines changed
  • packages/react-devtools-shared/src/backend/fiber

1 file changed

+32
-29
lines changed

packages/react-devtools-shared/src/backend/fiber/renderer.js

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ type SuspenseNode = {
275275
parent: null | SuspenseNode,
276276
firstChild: null | SuspenseNode,
277277
nextSibling: null | SuspenseNode,
278-
suspendedBy: Map<ReactIOInfo, Set<DevToolsInstance | null>>, // Tracks which data we're suspended by and the children that suspend it.
278+
suspendedBy: Map<ReactIOInfo, Set<DevToolsInstance>>, // Tracks which data we're suspended by and the children that suspend it.
279279
// Track whether any of the items in suspendedBy are unique this this Suspense boundaries or if they're all
280280
// also in the parent sets. This determine whether this could contribute in the loading sequence.
281281
hasUniqueSuspenders: boolean,
@@ -2437,37 +2437,40 @@ export function attach(
24372437
parentSuspenseNode = parentSuspenseNode.parent;
24382438
}
24392439
const parentInstance = reconcilingParent;
2440-
if (parentSuspenseNode !== null) {
2441-
const suspendedBy = parentSuspenseNode.suspendedBy;
2442-
const ioInfo = asyncInfo.awaited;
2443-
let suspendedBySet = suspendedBy.get(ioInfo);
2444-
if (suspendedBySet === undefined) {
2445-
suspendedBySet = new Set();
2446-
suspendedBy.set(asyncInfo.awaited, suspendedBySet);
2447-
}
2448-
// The child of the Suspense boundary that was suspended on this, or null if suspended at the root.
2449-
// This is used to keep track of how many dependents are still alive and also to get information
2450-
// like owner instances to link down into the tree.
2451-
if (!suspendedBySet.has(parentInstance)) {
2452-
suspendedBySet.add(parentInstance);
2453-
if (
2454-
!parentSuspenseNode.hasUniqueSuspenders &&
2455-
!ioExistsInSuspenseAncestor(parentSuspenseNode, ioInfo)
2456-
) {
2457-
// This didn't exist in the parent before, so let's mark this boundary as having a unique suspender.
2458-
parentSuspenseNode.hasUniqueSuspenders = true;
2459-
}
2460-
}
2440+
if (parentInstance === null || parentSuspenseNode === null) {
2441+
throw new Error(
2442+
'It should not be possible to have suspended data outside the root. ' +
2443+
'Even suspending at the first position is still a child of the root.',
2444+
);
24612445
}
2462-
if (parentInstance !== null) {
2463-
// Suspending at the root is not attributed to any particular component other than the SuspenseNode.
2464-
const suspendedBy = parentInstance.suspendedBy;
2465-
if (suspendedBy === null) {
2466-
parentInstance.suspendedBy = [asyncInfo];
2467-
} else if (suspendedBy.indexOf(asyncInfo) === -1) {
2468-
suspendedBy.push(asyncInfo);
2446+
const suspenseNodeSuspendedBy = parentSuspenseNode.suspendedBy;
2447+
const ioInfo = asyncInfo.awaited;
2448+
let suspendedBySet = suspenseNodeSuspendedBy.get(ioInfo);
2449+
if (suspendedBySet === undefined) {
2450+
suspendedBySet = new Set();
2451+
suspenseNodeSuspendedBy.set(asyncInfo.awaited, suspendedBySet);
2452+
}
2453+
// The child of the Suspense boundary that was suspended on this, or null if suspended at the root.
2454+
// This is used to keep track of how many dependents are still alive and also to get information
2455+
// like owner instances to link down into the tree.
2456+
if (!suspendedBySet.has(parentInstance)) {
2457+
suspendedBySet.add(parentInstance);
2458+
if (
2459+
!parentSuspenseNode.hasUniqueSuspenders &&
2460+
!ioExistsInSuspenseAncestor(parentSuspenseNode, ioInfo)
2461+
) {
2462+
// This didn't exist in the parent before, so let's mark this boundary as having a unique suspender.
2463+
parentSuspenseNode.hasUniqueSuspenders = true;
24692464
}
24702465
}
2466+
// Suspending right below the root is not attributed to any particular component in UI
2467+
// other than the SuspenseNode and the HostRoot's FiberInstance.
2468+
const suspendedBy = parentInstance.suspendedBy;
2469+
if (suspendedBy === null) {
2470+
parentInstance.suspendedBy = [asyncInfo];
2471+
} else if (suspendedBy.indexOf(asyncInfo) === -1) {
2472+
suspendedBy.push(asyncInfo);
2473+
}
24712474
}
24722475
24732476
function getAwaitInSuspendedByFromIO(

0 commit comments

Comments
 (0)