diff --git a/src/bun.js/webcore/FileReader.zig b/src/bun.js/webcore/FileReader.zig index 95a5cdfcef60..b3dbbd036ee6 100644 --- a/src/bun.js/webcore/FileReader.zig +++ b/src/bun.js/webcore/FileReader.zig @@ -320,14 +320,18 @@ pub fn onReadChunk(this: *@This(), init_buf: []const u8, state: bun.io.ReadState if (buf.len > 0) { if (this.max_size) |max_size| { - if (this.total_readed >= max_size) return false; + if (this.total_readed >= max_size) { + close = true; + hasMore = false; + return false; + } const len = @min(max_size - this.total_readed, buf.len); if (buf.len > len) { buf = buf[0..len]; } this.total_readed += len; - if (buf.len == 0) { + if (this.total_readed >= max_size) { close = true; hasMore = false; } diff --git a/test/regression/issue/18192.test.ts b/test/regression/issue/18192.test.ts new file mode 100644 index 000000000000..6c88622e262c --- /dev/null +++ b/test/regression/issue/18192.test.ts @@ -0,0 +1,41 @@ +// https://github.com/oven-sh/bun/issues/18192 +// Bun.file().slice().stream() should not hang for files larger than 640KB + +import { expect, test } from "bun:test"; +import { tempDir } from "harness"; +import { join } from "path"; + +test("Bun.file().slice().stream() should not hang for large files", async () => { + using tmpbase = tempDir("issue-18192", {}); + const path = join(tmpbase, "large-file.bin"); + + const size = 1024 * 1024; // 1mb file + await Bun.write(path, new Uint8Array(size).fill(69)); + + const file = Bun.file(path); + + // tiny slice + { + const sliced = file.slice(0, 1); + const bytes = await new Response(sliced.stream()).bytes(); + expect(bytes.length).toBe(1); + expect(bytes).toEqual(new Uint8Array(1).fill(69)); + } + + // zero length slice + { + const sliced = file.slice(0, 0); + const bytes = await new Response(sliced.stream()).bytes(); + expect(bytes.length).toBe(0); + } + + // somewhere in the middle slice + { + const midStart = 500 * 1024; + const midEnd = midStart + 10; + const sliced = file.slice(midStart, midEnd); + const bytes = await new Response(sliced.stream()).bytes(); + expect(bytes.length).toBe(10); + expect(bytes).toEqual(new Uint8Array(10).fill(69)); + } +}); diff --git a/test/regression/issue/21175.test.ts b/test/regression/issue/21175.test.ts new file mode 100644 index 000000000000..14567f63b7a7 --- /dev/null +++ b/test/regression/issue/21175.test.ts @@ -0,0 +1,24 @@ +// https://github.com/oven-sh/bun/issues/21175 +// Bun.file().slice().stream() should not hang when consumed via iterator +import { expect, test } from "bun:test"; +import { tempDir } from "harness"; +import { join } from "path"; + +test("Bun.file().slice().stream() iterator consumption", async () => { + using tmpbase = tempDir("issue-21175", {}); + const path = join(tmpbase, "large-file.bin"); + + const size = 1024 * 1024; // 1mb file + await Bun.write(path, new Uint8Array(size).fill(69)); + const file = Bun.file(path); + + const sliced = file.slice(0, 16384); + const stream = sliced.stream(); + + let totalLen = 0; + // @ts-expect-error: ReadableStream is async iterable + for await (const chunk of stream) { + totalLen += chunk.length; + } + expect(totalLen).toBe(16384); +});