blob: copy the source slice window in Bun.write(file, file.slice()), not the whole file
Bun.write(dst, Bun.file(src).slice(a, b)) wrote the entire source file instead of the slice. The file-to-file copy passed the destination blob's offset/size as the copy window, but the copier applies that window to the source read, and a plain-path destination has offset 0 and size MAX_SIZE, so the whole source was copied. The data itself was fine (slice(a, b).bytes() already worked); only the file-to-file copy dropped the window. Present in Bun 1.3.14 too, so this is not a port regression.
await Bun.write(dst, Bun.file(src).slice(100, 164));
// returned 4096 (the whole source size) and dst held the whole file
Fix
Pass the source blob's window to the copier and make every platform honor it.
- POSIX: seek the source fd to the slice start before the per-OS copy.
copy_file_range,sendfile,fcopyfile, and the read/write loop all read from the fd's current position. Only regular files are seeked; pipes, FIFOs, sockets, and character devices are copied from their current position (per review). - macOS:
clonefilestays gated onoffset == 0and truncates to the slice length for head slices. The byte countBun.writeresolves with on thefcopyfilepath is now the copied length (read_lenwas never set on that path, so it resolved with 0). - Windows:
CopyFileWindowslearns the source offset. A sliced source goes through a positioned, window-clampeduv_fs_readloop;uv_fs_copyfileis only used when there is no offset. A slice past EOF is clamped from the opened fd so the destination is never zero-padded. copy_file_using_read_write_loop: a non-zerostat_sizeis now the exact number of bytes to copy rather than a lower bound, so the fallback stops at the slice end instead of reading the backing file to EOF.0still means unknown (read to EOF).fs.copyFileandcppass the full file size, for which both behaviors are identical.- The destination blob's size is no longer consulted. It never carried user intent: reading
.sizeon aBunFilecaches the stat into the blob, soconst f = Bun.file(dst); f.size; await Bun.write(f, biggerFile)silently truncated the copy to the destination's old length.
Tests
All in test/js/bun/io/bun-write.test.js and running on every platform: mid, head, and tail slices, a slice past EOF, an empty slice, an fd-backed source, a larger-than-1MB middle slice through both the fast path and the forced read/write loop, a pre-existing larger destination, a non-seekable FIFO source, a destination with a resolved .size, and whole-file regression guards.