Files
scriptc/tests/corpus/5405-buffer-arraybuffer-window.ts
T
Chris Tate 0d59abe143 Pool small Buffers as Node does
Buffer.from of strings, arrays and Uint8Arrays, Buffer.allocUnsafe and
Buffer.concat now return views into a per-thread pool slab of
Buffer.poolSize bytes (64 KiB by default) when the size is below
Buffer.poolSize >>> 1, following Node's allocate, fromStringFast and
fromArrayLike: 8-byte aligned offsets, a new slab when a request does not
fit, and the four-bytes-per-unit reservation for strings. Buffer.poolSize
can be read and set, and Buffer.allocUnsafeSlow returns an unpooled Buffer.
A slab lives while any of its views does. Its ArrayBuffer cannot be
transferred, and structuredClone of a typed array view copies the whole
ArrayBuffer and keeps the view's offset. Buffer.alloc, allocUnsafe and
allocUnsafeSlow validate sizes with Node's ERR_OUT_OF_RANGE error.

The first pooled allocation finds the startup slab, which has the
default 64 KiB size. A request it cannot hold gets a slab of the current
Buffer.poolSize, as in Node, and the room is checked after every new
slab, so a Buffer.poolSize raised before the first pooled allocation
cannot place a reservation past the end of a 64 KiB slab. A reservation
larger than a fresh slab traps instead of writing past it.

Corpus 5531 (typed) and 5532 (untyped) raise Buffer.poolSize before the
first pooled allocation and allocate just under the new threshold
through each pooled path, each case in a fresh child process, and also
shrink Buffer.poolSize and change it between allocations. The
node-types fenced fixture no longer lists Buffer.poolSize, which now
compiles.
2026-10-16 01:39:10 -05:00

17 lines
983 B
TypeScript

// Small Buffers from Buffer.from, Buffer.concat and Buffer.allocUnsafe are
// views into a shared pool slab. Reading a Buffer's window of its
// ArrayBuffer through byteOffset and length gives its own bytes, and
// Buffer.alloc is never pooled.
const small = Buffer.from("hello");
const copy = small.buffer.slice(small.byteOffset, small.byteOffset + small.length);
console.log(copy.byteLength, new TextDecoder().decode(new Uint8Array(copy)));
const view = new Uint8Array(small.buffer, small.byteOffset, small.length);
console.log(Array.from(view).join(","));
const joined = Buffer.concat([Buffer.from("ab"), Buffer.from("cd")]);
const data = new DataView(joined.buffer, joined.byteOffset, joined.length);
console.log(data.getUint16(0), data.byteLength);
const unsafe = Buffer.allocUnsafe(4).fill(7);
console.log(Array.from(new Uint8Array(unsafe.buffer, unsafe.byteOffset, 4)).join(","));
const zeroed = Buffer.alloc(16, 1);
console.log(zeroed.buffer.byteLength, zeroed.byteOffset);