diff --git a/compiler/apps/playground/components/Editor/EditorImpl.tsx b/compiler/apps/playground/components/Editor/EditorImpl.tsx index d7229361d39c2..0c12b482a3b7d 100644 --- a/compiler/apps/playground/components/Editor/EditorImpl.tsx +++ b/compiler/apps/playground/components/Editor/EditorImpl.tsx @@ -13,7 +13,7 @@ import BabelPluginReactCompiler, { CompilerErrorDetail, CompilerDiagnostic, Effect, - ErrorSeverity, + ErrorCategory, parseConfigPragmaForTests, ValueKind, type Hook, @@ -258,7 +258,7 @@ function compile( console.error(err); error.details.push( new CompilerErrorDetail({ - severity: ErrorSeverity.Invariant, + category: ErrorCategory.Invariant, reason: `Unexpected failure when transforming input! ${err}`, loc: null, suggestions: null, diff --git a/compiler/packages/babel-plugin-react-compiler/src/index.ts b/compiler/packages/babel-plugin-react-compiler/src/index.ts index 2830d70d95c8d..a8b934160a023 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/index.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/index.ts @@ -12,6 +12,7 @@ export { CompilerDiagnostic, CompilerSuggestionOperation, ErrorSeverity, + ErrorCategory, LintRules, type CompilerErrorDetailOptions, type CompilerDiagnosticOptions, diff --git a/packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js b/packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js index a7c0893060b00..6716766b2794c 100644 --- a/packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js +++ b/packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js @@ -228,7 +228,7 @@ describe('commit tree', () => { [root] ▾ - [shell] + [suspense-root] rects={null} `); utils.act(() => modernRender()); @@ -237,7 +237,7 @@ describe('commit tree', () => { ▾ - [shell] + [suspense-root] rects={null} `); utils.act(() => modernRender()); @@ -303,7 +303,7 @@ describe('commit tree', () => { [root] ▾ - [shell] + [suspense-root] rects={null} `); utils.act(() => modernRender()); diff --git a/packages/react-devtools-shared/src/__tests__/store-test.js b/packages/react-devtools-shared/src/__tests__/store-test.js index d4c3fcd9cad4b..e6eddff8402f0 100644 --- a/packages/react-devtools-shared/src/__tests__/store-test.js +++ b/packages/react-devtools-shared/src/__tests__/store-test.js @@ -133,7 +133,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={null} `); }); @@ -492,7 +492,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:10,height:1}]} `); @@ -505,7 +505,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]} `); }); @@ -584,7 +584,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}]} @@ -612,7 +612,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -640,7 +640,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -668,7 +668,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -689,7 +689,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -717,7 +717,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -745,7 +745,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}]} @@ -773,7 +773,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -792,7 +792,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -813,7 +813,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -839,7 +839,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -865,7 +865,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:10,height:1}]} @@ -893,7 +893,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}]} @@ -948,7 +948,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]} @@ -981,7 +981,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]} @@ -1009,7 +1009,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]} @@ -1053,7 +1053,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:10,height:1}]} `); @@ -1068,7 +1068,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]} `); }); @@ -1406,7 +1406,7 @@ describe('Store', () => { expect(store).toMatchInlineSnapshot(` [root] ▸ - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:10,height:1}]} `); @@ -1423,7 +1423,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:10,height:1}]} `); @@ -1436,7 +1436,7 @@ describe('Store', () => { - [shell] + [suspense-root] rects={[{x:1,y:2,width:5,height:1}, {x:1,y:2,width:5,height:1}]} `); }); @@ -1662,7 +1662,7 @@ describe('Store', () => { expect(store).toMatchInlineSnapshot(` [root] ▸ - [shell] + [suspense-root] rects={null} `); @@ -1677,7 +1677,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={null} `); @@ -1696,7 +1696,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={null} `); @@ -1712,7 +1712,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={null} `); }); @@ -2017,7 +2017,7 @@ describe('Store', () => { [root] ▾ - [shell] + [suspense-root] rects={null} `); @@ -2031,7 +2031,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={null} `); @@ -2522,7 +2522,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={null} `); @@ -2533,7 +2533,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={null} `); }); @@ -2860,7 +2860,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:19,height:1}]} `); @@ -2874,7 +2874,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:10,height:1}]} `); @@ -2887,7 +2887,7 @@ describe('Store', () => { [root] ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:4,height:1}]} `); }); @@ -2990,7 +2990,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:19,height:1}, {x:1,y:2,width:19,height:1}]} @@ -3013,7 +3013,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:4,height:1}]} `); @@ -3043,7 +3043,7 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:4,height:1}]} @@ -3074,10 +3074,15 @@ describe('Store', () => { ▾ - [shell] + [suspense-root] rects={[{x:1,y:2,width:4,height:1}, {x:1,y:2,width:10,height:1}, {x:1,y:2,width:19,height:1}, {x:1,y:2,width:4,height:1}]} `); }); + + it('should handle an empty root', async () => { + await actAsync(() => render(null)); + expect(store).toMatchInlineSnapshot(`[root]`); + }); }); diff --git a/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js b/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js index c29bff05383c5..63ad3101d8246 100644 --- a/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js +++ b/packages/react-devtools-shared/src/__tests__/storeComponentFilters-test.js @@ -156,7 +156,7 @@ describe('Store component filters', () => {
- [shell] + [suspense-root] rects={[]} `); @@ -174,7 +174,7 @@ describe('Store component filters', () => {
- [shell] + [suspense-root] rects={[]} `); @@ -192,7 +192,7 @@ describe('Store component filters', () => {
- [shell] + [suspense-root] rects={[]} `); diff --git a/packages/react-devtools-shared/src/__tests__/treeContext-test.js b/packages/react-devtools-shared/src/__tests__/treeContext-test.js index e7042418053ea..6f382f976cb0a 100644 --- a/packages/react-devtools-shared/src/__tests__/treeContext-test.js +++ b/packages/react-devtools-shared/src/__tests__/treeContext-test.js @@ -1368,7 +1368,7 @@ describe('TreeListContext', () => { ▾ - [shell] + [suspense-root] rects={null} `); @@ -1410,7 +1410,7 @@ describe('TreeListContext', () => { ▾ - [shell] + [suspense-root] rects={null} `); @@ -2369,7 +2369,7 @@ describe('TreeListContext', () => { expect(state).toMatchInlineSnapshot(` [root] - [shell] + [suspense-root] rects={null} `); @@ -2378,7 +2378,7 @@ describe('TreeListContext', () => { expect(state).toMatchInlineSnapshot(` [root] - [shell] + [suspense-root] rects={null} `); }); @@ -2404,7 +2404,7 @@ describe('TreeListContext', () => { expect(state).toMatchInlineSnapshot(` [root] - [shell] + [suspense-root] rects={null} `); @@ -2426,7 +2426,7 @@ describe('TreeListContext', () => { ▾ - [shell] + [suspense-root] rects={null} `); }); @@ -2456,7 +2456,7 @@ describe('TreeListContext', () => { ▾ ✕ - [shell] + [suspense-root] rects={null} `); @@ -2475,7 +2475,7 @@ describe('TreeListContext', () => { [root] ▾ - [shell] + [suspense-root] rects={null} `); }); diff --git a/packages/react-devtools-shared/src/backend/fiber/renderer.js b/packages/react-devtools-shared/src/backend/fiber/renderer.js index 545725526d04a..2102dc1926bc3 100644 --- a/packages/react-devtools-shared/src/backend/fiber/renderer.js +++ b/packages/react-devtools-shared/src/backend/fiber/renderer.js @@ -3700,28 +3700,32 @@ export function attach( // just use the Fiber anyway. // Fallbacks get attributed to the parent so we only measure if we're // showing primary content. - if (OffscreenComponent === -1) { - const isTimedOut = fiber.memoizedState !== null; - if (!isTimedOut) { - newSuspenseNode.rects = measureInstance(newInstance); - } - } else { - const hydrated = isFiberHydrated(fiber); - if (hydrated) { - const contentFiber = fiber.child; - if (contentFiber === null) { - throw new Error( - 'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.', - ); + if (fiber.tag === SuspenseComponent) { + if (OffscreenComponent === -1) { + const isTimedOut = fiber.memoizedState !== null; + if (!isTimedOut) { + newSuspenseNode.rects = measureInstance(newInstance); } } else { - // This Suspense Fiber is still dehydrated. It won't have any children - // until hydration. - } - const isTimedOut = fiber.memoizedState !== null; - if (!isTimedOut) { - newSuspenseNode.rects = measureInstance(newInstance); + const hydrated = isFiberHydrated(fiber); + if (hydrated) { + const contentFiber = fiber.child; + if (contentFiber === null) { + throw new Error( + 'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.', + ); + } + } else { + // This Suspense Fiber is still dehydrated. It won't have any children + // until hydration. + } + const isTimedOut = fiber.memoizedState !== null; + if (!isTimedOut) { + newSuspenseNode.rects = measureInstance(newInstance); + } } + } else { + newSuspenseNode.rects = measureInstance(newInstance); } recordSuspenseMount(newSuspenseNode, reconcilingParentSuspenseNode); } diff --git a/packages/react-devtools-shared/src/devtools/utils.js b/packages/react-devtools-shared/src/devtools/utils.js index 0501e861bbd67..d5078679f44f9 100644 --- a/packages/react-devtools-shared/src/devtools/utils.js +++ b/packages/react-devtools-shared/src/devtools/utils.js @@ -54,22 +54,21 @@ export function printElement( }${key}${name}>${hocs}${suffix}`; } -function printSuspense( - suspense: SuspenseNode, - includeWeight: boolean = false, -): string { +function printRects(rects: SuspenseNode['rects']): string { + if (rects === null) { + return ' rects={null}'; + } else { + return ` rects={[${rects.map(rect => `{x:${rect.x},y:${rect.y},width:${rect.width},height:${rect.height}}`).join(', ')}]}`; + } +} + +function printSuspense(suspense: SuspenseNode): string { let name = ''; if (suspense.name !== null) { name = ` name="${suspense.name}"`; } - let printedRects = ''; - const rects = suspense.rects; - if (rects === null) { - printedRects = ' rects={null}'; - } else { - printedRects = ` rects={[${rects.map(rect => `{x:${rect.x},y:${rect.y},width:${rect.width},height:${rect.height}}`).join(', ')}]}`; - } + const printedRects = printRects(suspense.rects); return ``; } @@ -178,13 +177,13 @@ export function printStore( rootWeight += weight; if (includeSuspense) { - const shell = store.getSuspenseByID(rootID); + const root = store.getSuspenseByID(rootID); // Roots from legacy renderers don't have a separate Suspense tree - if (shell !== null) { - if (shell.children.length > 0) { - snapshotLines.push('[shell]'); - for (let i = 0; i < shell.children.length; i++) { - const childID = shell.children[i]; + if (root !== null) { + if (root.children.length > 0) { + snapshotLines.push('[suspense-root] ' + printRects(root.rects)); + for (let i = 0; i < root.children.length; i++) { + const childID = root.children[i]; const child = store.getSuspenseByID(childID); if (child === null) { throw new Error(