diff --git a/apps/host-daemon/src/command-handlers/file-list.test.ts b/apps/host-daemon/src/command-handlers/file-list.test.ts index 5ea132ca90..272968ae77 100644 --- a/apps/host-daemon/src/command-handlers/file-list.test.ts +++ b/apps/host-daemon/src/command-handlers/file-list.test.ts @@ -262,4 +262,33 @@ describe("listPathsRecursively", () => { "src/components/Button.tsx", ); }); + + it("does not overflow the call stack merging a large subdirectory", async () => { + const root = await fs.mkdtemp(path.join(os.tmpdir(), "bb-file-list-")); + try { + const nested = path.join(root, "many"); + await fs.mkdir(nested, { recursive: true }); + const fileCount = 150_000; + const batchSize = 500; + for (let start = 0; start < fileCount; start += batchSize) { + const end = Math.min(start + batchSize, fileCount); + await Promise.all( + Array.from({ length: end - start }, (_, offset) => + fs.writeFile(path.join(nested, `f${start + offset}.txt`), ""), + ), + ); + } + + const result = await listPathsRecursively({ + dir: root, + root, + includeFiles: true, + includeDirectories: false, + }); + + expect(result).toHaveLength(fileCount); + } finally { + await fs.rm(root, { recursive: true, force: true }); + } + }, 60_000); }); diff --git a/apps/host-daemon/src/command-handlers/file-list.ts b/apps/host-daemon/src/command-handlers/file-list.ts index 43120eee98..0541ca8be2 100644 --- a/apps/host-daemon/src/command-handlers/file-list.ts +++ b/apps/host-daemon/src/command-handlers/file-list.ts @@ -156,12 +156,11 @@ export async function listPathsRecursively( name: entry.name, }); } - results.push( - ...(await listPathsRecursively({ - ...args, - dir: fullPath, - })), - ); + const childResults = await listPathsRecursively({ + ...args, + dir: fullPath, + }); + for (const childResult of childResults) results.push(childResult); continue; }