From 01c698dc6849ae13b9498d07ee44570ac0e165ae Mon Sep 17 00:00:00 2001 From: Koji Wakayama Date: Mon, 10 Aug 2026 20:05:22 +0200 Subject: [PATCH 1/2] Prevent valid Bun watcher runs from failing on unrelated events The native watcher integration consumed exactly one filesystem event even though directory watchers may surface queued changes for another path. Keep reading until the file written by the test is observed and always clear the deadline timer. Constraint: Bun's Node-compatible fs.watch can coalesce or delay directory events on CI hosts. Rejected: Increase the timeout only | it would still fail when an unrelated event arrives first. Confidence: high Scope-risk: narrow Reversibility: clean Directive: Filesystem watcher tests must select their target event instead of assuming the first event is relevant. Tested: Reproduced both timeout and wrong-path failures; fmt, lint, typecheck, 100 consecutive Bun runs, npm build, and exact isolated Bun runner passed. Not-tested: Full Bun suite is delegated to PR CI. --- .../bun/filesystem-adapter.bun.test.ts | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/platform/adapters/runtime/bun/filesystem-adapter.bun.test.ts b/src/platform/adapters/runtime/bun/filesystem-adapter.bun.test.ts index 248d40c38a..1690b9ada1 100644 --- a/src/platform/adapters/runtime/bun/filesystem-adapter.bun.test.ts +++ b/src/platform/adapters/runtime/bun/filesystem-adapter.bun.test.ts @@ -9,16 +9,13 @@ import { join } from "node:path"; import { BunFileSystemAdapter } from "./filesystem-adapter.ts"; import { getBunRuntime } from "./types.ts"; -function delay(milliseconds: number): Promise { - return new Promise((resolve) => setTimeout(resolve, milliseconds)); -} - describe("BunFileSystemAdapter native integration", () => { it("reads, writes, and watches through the real Bun runtime", async () => { if (!getBunRuntime()) return; const root = await mkdtemp(join(tmpdir(), "veryfront-bun-fs-")); const adapter = new BunFileSystemAdapter(); let watcher: ReturnType | undefined; + let timeoutId: ReturnType | undefined; try { const file = join(root, "file.txt"); @@ -96,19 +93,29 @@ describe("BunFileSystemAdapter native integration", () => { } watcher = adapter.watch(root, { recursive: false }); - const eventPromise = watcher[Symbol.asyncIterator]().next(); + const iterator = watcher[Symbol.asyncIterator](); assertExists(watcher.ready); await watcher.ready; + const observed = (async () => { + while (true) { + const result = await iterator.next(); + if (result.done) throw new Error("Bun watcher closed before observing the file"); + if (result.value.paths.some((path) => path.endsWith("file.txt"))) { + return result.value; + } + } + })(); + const timeout = new Promise((_, reject) => { + timeoutId = setTimeout( + () => reject(new Error("Bun filesystem watcher integration timed out")), + 5_000, + ); + }); + await adapter.writeFile(file, "updated"); - const event = await Promise.race([ - eventPromise, - delay(3_000).then(() => { - throw new Error("Bun filesystem watcher integration timed out"); - }), - ]); - assertEquals(event.done, false); + const event = await Promise.race([observed, timeout]); assertEquals( - event.value?.paths.some((path: string) => path.endsWith("file.txt")), + event.paths.some((path: string) => path.endsWith("file.txt")), true, ); @@ -116,6 +123,7 @@ describe("BunFileSystemAdapter native integration", () => { assertExists(watcher.done); await watcher.done; } finally { + if (timeoutId !== undefined) clearTimeout(timeoutId); watcher?.close(); await watcher?.done; await rm(root, { recursive: true, force: true }); From 38ef8783769127f1b9e84b56ef00b060006dd105 Mon Sep 17 00:00:00 2001 From: Koji Wakayama Date: Mon, 10 Aug 2026 20:20:58 +0200 Subject: [PATCH 2/2] test(bun): watch a dedicated file creation --- .../adapters/runtime/bun/filesystem-adapter.bun.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/platform/adapters/runtime/bun/filesystem-adapter.bun.test.ts b/src/platform/adapters/runtime/bun/filesystem-adapter.bun.test.ts index 1690b9ada1..d2cc56bc56 100644 --- a/src/platform/adapters/runtime/bun/filesystem-adapter.bun.test.ts +++ b/src/platform/adapters/runtime/bun/filesystem-adapter.bun.test.ts @@ -19,6 +19,7 @@ describe("BunFileSystemAdapter native integration", () => { try { const file = join(root, "file.txt"); + const watchedFile = join(root, "watched.txt"); await adapter.writeFile(file, "hello"); assertEquals(await adapter.readFile(file), "hello"); assertEquals((await adapter.readFileBytes(file)).length, 5); @@ -100,7 +101,7 @@ describe("BunFileSystemAdapter native integration", () => { while (true) { const result = await iterator.next(); if (result.done) throw new Error("Bun watcher closed before observing the file"); - if (result.value.paths.some((path) => path.endsWith("file.txt"))) { + if (result.value.paths.includes(watchedFile)) { return result.value; } } @@ -112,10 +113,10 @@ describe("BunFileSystemAdapter native integration", () => { ); }); - await adapter.writeFile(file, "updated"); + await writeFile(watchedFile, "created"); const event = await Promise.race([observed, timeout]); assertEquals( - event.paths.some((path: string) => path.endsWith("file.txt")), + event.paths.includes(watchedFile), true, );