diff --git a/src/router.zig b/src/router.zig index 875d7da9be..d3f735bf16 100644 --- a/src/router.zig +++ b/src/router.zig @@ -731,23 +731,22 @@ pub const Route = struct { if (abs_path_str.len == 0) { var file: std.fs.File = undefined; - var needs_close = false; + var needs_close = true; defer if (needs_close) file.close(); if (entry.cache.fd.unwrapValid()) |valid| { file = valid.stdFile(); + needs_close = false; } else { var parts = [_]string{ entry.dir, entry.base() }; abs_path_str = FileSystem.instance.absBuf(&parts, &route_file_buf); route_file_buf[abs_path_str.len] = 0; const buf = route_file_buf[0..abs_path_str.len :0]; file = std.fs.openFileAbsoluteZ(buf, .{ .mode = .read_only }) catch |err| { + needs_close = false; log.addErrorFmt(null, Logger.Loc.Empty, allocator, "{s} opening route: {s}", .{ @errorName(err), abs_path_str }) catch unreachable; return null; }; FileSystem.setMaxFd(file.handle); - - needs_close = FileSystem.instance.fs.needToCloseFiles(); - if (!needs_close) entry.cache.fd = .fromStdFile(file); } const _abs = bun.getFdPath(.fromStdFile(file), &route_file_buf) catch |err| { diff --git a/test/regression/issue/18242.test.ts b/test/regression/issue/18242.test.ts new file mode 100644 index 0000000000..ceefcbd096 --- /dev/null +++ b/test/regression/issue/18242.test.ts @@ -0,0 +1,62 @@ +import { expect, test } from "bun:test"; +import { bunEnv, bunExe, tempDir } from "harness"; + +test("Bun.build works multiple times after FileSystemRouter is created", async () => { + using dir = tempDir("issue-18242", { + "pages/index.ts": `console.log("Hello via Bun!");`, + "build.ts": ` +import path from "path"; + +const PAGES_DIR = path.resolve(process.cwd(), "pages"); + +const srcRouter = new Bun.FileSystemRouter({ + dir: PAGES_DIR, + style: "nextjs", +}); + +const entrypoints = Object.values(srcRouter.routes); + +const result1 = await Bun.build({ + entrypoints, + outdir: "dist/browser", +}); + +const result2 = await Bun.build({ + entrypoints, + outdir: "dist/bun", + target: "bun", +}); + +const result3 = await Bun.build({ + entrypoints, + outdir: "dist/third", +}); + +console.log(JSON.stringify({ + build1: result1.success, + build2: result2.success, + build3: result3.success, + build2Logs: result2.logs.map(String), + build3Logs: result3.logs.map(String), +})); +`, + }); + + await using proc = Bun.spawn({ + cmd: [bunExe(), "build.ts"], + env: bunEnv, + cwd: String(dir), + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + const result = JSON.parse(stdout.trim()); + + expect(result.build1).toBe(true); + expect(result.build2).toBe(true); + expect(result.build3).toBe(true); + expect(result.build2Logs).toEqual([]); + expect(result.build3Logs).toEqual([]); + expect(exitCode).toBe(0); +});