fix(js-exec): honor encoding arg in Buffer.from / toString / write / byteLength (#256)
* fix(js-exec): honor encoding arg in Buffer.from / toString / write / byteLength
Add pure-JS encoders/decoders for base64, base64url, hex, latin1/binary,
ascii, and utf16le inside BUFFER_MODULE_SOURCE. Dispatch on a normalized
encoding string in Buffer.from, Buffer.prototype.toString,
Buffer.prototype.write, and Buffer.byteLength so the QuickJS shim matches
real Node.js Buffer semantics for every encoding Node supports.
- _normEnc: normalizes encoding aliases (binary→latin1, ucs2→utf16le, etc.)
- _hexEncode/_hexDecode: lenient hex (stops at first invalid char)
- _latin1Encode/_latin1Decode, _asciiEncode/_asciiDecode
- _utf16leEncode/_utf16leDecode
- _b64Encode/_b64UrlEncode/_b64Decode: forgiving base64 (ignores whitespace,
tolerates missing padding, supports base64url alphabet)
Adds js-exec.buffer-encoding.test.ts with 29 cases covering encode-only,
decode-only, round-trips, binary bytes (0xff/0xfe/0x00), alias names, and
forgiving inputs. Adds a guardrail comment above _normEnc explaining why
round-trip tests alone would mask a broken encoding implementation.
* perf(js-exec): compute base64 byteLength in O(1) without decoding
Replace _b64Decode(value).length with a length-based formula
(strip non-alphabet + padding, then floor(len * 3 / 4)). Matches
Node's Buffer.byteLength semantics and avoids allocating an array
just to count bytes.
* refactor(js-exec): consolidate ascii/latin1 encode and fix Buffer shim correctness
- Replace _latin1Encode/_asciiEncode with shared _rawEncode (both truncate to low byte; encode semantics are identical)
- Fix Buffer.from(ArrayBuffer, byteOffset, length) to respect offset and length args
- Fix Buffer.byteLength to throw TypeError for non-string/non-Buffer input instead of returning 0
- Fix Buffer.byteLength base64 regex to correctly handle mid-string '=' as terminator
- Fix Buffer.prototype.toString to clamp negative start to 0, matching Node behavior
- Fix Buffer.prototype.write to throw RangeError for negative/out-of-range offset
* chore: bump patch version for changeset
* fix(js-exec): Buffer shim ArrayBuffer sharing, write length validation, toString negative end
- Buffer.from(ArrayBuffer, offset, length) now shares the backing store as Node does
(previously the inner Uint8Array was copied through the Buffer constructor).
- Buffer.prototype.write throws RangeError for negative length or length > remaining,
matching Node's ERR_OUT_OF_RANGE rather than silently clamping.
- Buffer.prototype.toString clamps negative end to 0 (Node behavior), so
Buffer.from("abc").toString("utf8", 0, -1) returns "" instead of "ab".
Adds edge-case tests covering all three behaviors.
* fix(js-exec): validate Buffer.write length against total size, clamp writes to remaining
Per vercel bot review: Node validates the `length` arg against the buffer's
total size, not the remaining space after `offset`, and clamps actual writes
to the remaining space. The previous fix validated against remaining, which
incorrectly threw for cases like `Buffer.alloc(5).write('abcde', 3, 5)` that
Node accepts (writing 2 bytes).
Adds a regression test for the offset+length clamping case. H
Harry Nguyen committed
75d8dfd3a322786250e3b0f81b1500c87610acb7
Parent: 4ece258
Committed by GitHub <noreply@github.com>
on 6/4/2026, 5:30:16 PM