fix(head/tail): read file arguments byte-clean, not UTF-8 (#264)
* fix(head/tail): read file arguments byte-clean, not UTF-8 head/tail read file arguments via `ctx.fs.readFile`, which UTF-8-decodes the content. For binary (or any non-ASCII) files this corrupts the data: `-c` slices by codepoint instead of byte, and high/invalid bytes are re-encoded (e.g. 0xFF -> U+FFFD, 3 bytes), so `head -c 50000` on binary could emit 150000 bytes. The stdin path was already byte-clean (latin1FromBytes(ctx.stdin)); the file-argument path was missed in the 3.0.0 stdin byte/utf8 overhaul. Read files via byte-preserving `readBytesFrom` and mark stdout `binary` (like `cat`) so redirects/pipes don't double-encode. `-c` byte counts and `-n` line splits (on 0x0A, UTF-8-transparent) are byte-safe over the latin1 view. Adds regression tests for UTF-8 byte counting and raw high-byte round-trip through a redirect for both head and tail. * fix(head/tail): UTF-8 encode filename headers in binary output The byte-clean fix marks head/tail stdout as binary so raw file bytes round-trip through redirects/pipes. But headers (-v or multiple files) carry the filename as a JS Unicode string, and the binary glue writes each char as one latin1 byte. A non-ASCII filename like café.txt was written as caf\xe9.txt (latin1) instead of caf\xc3\xa9.txt (UTF-8), corrupting the header on redirect. Encode the header text to its byte-shaped (UTF-8) form before mixing it with the raw file bytes. One spot in the shared helper covers both head and tail. Adds regression tests asserting the redirected header bytes are UTF-8.
H
Harry Nguyen committed
9481331f54fdcbfa1b81b313d756cd7f541d7018
Parent: 75d8dfd
Committed by GitHub <noreply@github.com>
on 6/4/2026, 5:30:57 PM