From c94cb0b11d05771ac3486cd6ac833a1739e6d8e4 Mon Sep 17 00:00:00 2001 From: pedrofrxncx Date: Sun, 23 Aug 2026 18:51:23 -0300 Subject: [PATCH] fix(preview): stop flattenTree overflowing the stack on a huge directory --- .../sandbox/preview/file-explorer/utils.test.ts | 14 ++++++++++++++ .../sandbox/preview/file-explorer/utils.ts | 9 ++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/sandbox/preview/file-explorer/utils.test.ts b/apps/web/src/components/sandbox/preview/file-explorer/utils.test.ts index 41c7d82ee1..d5556f85d9 100644 --- a/apps/web/src/components/sandbox/preview/file-explorer/utils.test.ts +++ b/apps/web/src/components/sandbox/preview/file-explorer/utils.test.ts @@ -60,6 +60,20 @@ describe("file-explorer utils", () => { expect(rows.some((row) => row.node.name === "tavano-folder")).toBe(true); }); + it("flattenTree doesn't overflow the stack on a huge expanded directory", () => { + const children = Array.from({ length: 700_000 }, (_, i) => ({ + name: `f${i}`, + path: `/dir/f${i}`, + kind: "file" as const, + children: [], + })); + const tree = [ + { name: "dir", path: "/dir", kind: "directory" as const, children }, + ]; + const rows = flattenTree(tree, new Set(["/dir"])); + expect(rows).toHaveLength(700_001); + }); + it("decoBlockKeyFromTreePath decodes block keys", () => { expect(decoBlockKeyFromTreePath("/.deco/blocks/Header.json")).toBe( "Header", diff --git a/apps/web/src/components/sandbox/preview/file-explorer/utils.ts b/apps/web/src/components/sandbox/preview/file-explorer/utils.ts index 69d3a3a2bc..fcf5b7f843 100644 --- a/apps/web/src/components/sandbox/preview/file-explorer/utils.ts +++ b/apps/web/src/components/sandbox/preview/file-explorer/utils.ts @@ -332,7 +332,14 @@ export function flattenTree( node.children.length > 0 && expandedDirectories.has(node.path) ) { - rows.push(...flattenTree(node.children, expandedDirectories, depth + 1)); + // A loop, not `rows.push(...flattenTree(...))` — spreading a huge array as call args overflows the stack. + for (const row of flattenTree( + node.children, + expandedDirectories, + depth + 1, + )) { + rows.push(row); + } } }