diff --git a/packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap b/packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap
index cc44049dd9a51..a47598e92d522 100644
--- a/packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap
+++ b/packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap
@@ -2191,6 +2191,65 @@ Object {
}
`;
+exports[`ProfilingCache should handle unexpectedly shallow suspense trees: Empty Suspense node 1`] = `
+Object {
+ "commitData": Array [
+ Object {
+ "changeDescriptions": Map {},
+ "duration": 0,
+ "fiberActualDurations": Map {
+ 1 => 0,
+ 2 => 0,
+ },
+ "fiberSelfDurations": Map {
+ 1 => 0,
+ 2 => 0,
+ },
+ "interactionIDs": Array [],
+ "priorityLevel": "Normal",
+ "timestamp": 0,
+ },
+ ],
+ "displayName": "Suspense",
+ "initialTreeBaseDurations": Map {},
+ "interactionCommits": Map {},
+ "interactions": Map {},
+ "operations": Array [
+ Array [
+ 1,
+ 1,
+ 9,
+ 8,
+ 83,
+ 117,
+ 115,
+ 112,
+ 101,
+ 110,
+ 115,
+ 101,
+ 1,
+ 1,
+ 11,
+ 1,
+ 1,
+ 1,
+ 2,
+ 12,
+ 1,
+ 0,
+ 1,
+ 0,
+ 4,
+ 2,
+ 0,
+ ],
+ ],
+ "rootID": 1,
+ "snapshots": Map {},
+}
+`;
+
exports[`ProfilingCache should properly detect changed hooks: CommitDetails commitIndex: 0 1`] = `
Object {
"changeDescriptions": Map {
diff --git a/packages/react-devtools-shared/src/__tests__/profilingCache-test.js b/packages/react-devtools-shared/src/__tests__/profilingCache-test.js
index 149449b1176d4..817becdc0d0eb 100644
--- a/packages/react-devtools-shared/src/__tests__/profilingCache-test.js
+++ b/packages/react-devtools-shared/src/__tests__/profilingCache-test.js
@@ -696,4 +696,24 @@ describe('ProfilingCache', () => {
),
);
});
+
+ it('should handle unexpectedly shallow suspense trees', () => {
+ const container = document.createElement('div');
+
+ utils.act(() => store.profilerStore.startProfiling());
+ utils.act(() => ReactDOM.render(, container));
+ utils.act(() => store.profilerStore.stopProfiling());
+
+ function Validator({commitIndex, rootID}) {
+ const profilingDataForRoot = store.profilerStore.getDataForRoot(rootID);
+ expect(profilingDataForRoot).toMatchSnapshot('Empty Suspense node');
+ return null;
+ }
+
+ const rootID = store.roots[0];
+
+ utils.act(() => {
+ TestRenderer.create();
+ });
+ });
});
diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js
index 3a714ba5e1c0d..9e550da1dd8f0 100644
--- a/packages/react-devtools-shared/src/backend/renderer.js
+++ b/packages/react-devtools-shared/src/backend/renderer.js
@@ -1237,11 +1237,14 @@ export function attach(
);
}
} else {
+ let primaryChild: Fiber | null = null;
const areSuspenseChildrenConditionallyWrapped =
OffscreenComponent === -1;
- const primaryChild: Fiber | null = areSuspenseChildrenConditionallyWrapped
- ? fiber.child
- : (fiber.child: any).child;
+ if (areSuspenseChildrenConditionallyWrapped) {
+ primaryChild = fiber.child;
+ } else if (fiber.child !== null) {
+ primaryChild = fiber.child.child;
+ }
if (primaryChild !== null) {
mountFiberRecursively(
primaryChild,
diff --git a/packages/react-devtools-shell/src/app/SuspenseTree/index.js b/packages/react-devtools-shell/src/app/SuspenseTree/index.js
index d681092de9c3d..72fffe22b7833 100644
--- a/packages/react-devtools-shell/src/app/SuspenseTree/index.js
+++ b/packages/react-devtools-shell/src/app/SuspenseTree/index.js
@@ -25,10 +25,15 @@ function SuspenseTree() {
+
);
}
+function EmptySuspense() {
+ return ;
+}
+
function PrimaryFallbackTest({initialSuspend}) {
const [suspend, setSuspend] = useState(initialSuspend);
const fallbackStep = useTestSequence('fallback', Fallback1, Fallback2);