Files
scriptc/tests/corpus/shared-bytes-stdio-write.ts
T
Chris Tate 9021a03133 Pass a shared view whole to a replaced stdout or stderr write
A shared view written to stdout or stderr went out in 64 KiB pieces through
scr_stdio_write, so a replaced process.stdout.write received the first
piece alone, and a false return, which only reports backpressure, ended the
loop: a view larger than 64 KiB lost the rest. With a write hook, the view
is now copied whole and passed in one call, as Node passes it; the bounded
pieces go to the stream itself through scr_stdio_write_raw, which never
stops early.

tests/corpus/shared-bytes-stdio-write.ts replaces process.stdout.write with
a function that records each chunk's length and returns false, and writes a
150,000-byte shared view through it.
2026-10-29 07:50:05 -05:00

41 lines
1.6 KiB
TypeScript

// process.stdout.write and process.stderr.write of views into a SharedArrayBuffer that a worker
// filled: a view larger than one write chunk (64 KiB), at a byte offset, one shorter than a chunk,
// and an empty one.
import { Worker, isMainThread, parentPort, workerData } from "node:worker_threads";
type Fill = { buffer: SharedArrayBuffer };
if (isMainThread) {
const sab = new SharedArrayBuffer(200_000);
const worker = new Worker(new URL(import.meta.url), { workerData: { buffer: sab } });
worker.on("message", () => {
process.stdout.write(new Uint8Array(sab, 1000, 150_000));
process.stdout.write("\n");
process.stdout.write(new Uint8Array(sab, 0, 0));
process.stdout.write(new Uint8Array(sab, 160_000, 20_000));
process.stdout.write("\n");
process.stderr.write(new Uint8Array(sab, 63, 70_000));
process.stderr.write("\n");
// A replaced write receives the whole view in one call, even when it
// returns false.
const out = process.stdout as unknown as Record<string, unknown>;
const original = out["write"];
const sizes: number[] = [];
out["write"] = (chunk: unknown): boolean => {
sizes.push(typeof chunk === "string" ? chunk.length : (chunk as Uint8Array).length);
return false;
};
const accepted = process.stdout.write(new Uint8Array(sab, 1000, 150_000));
out["write"] = original;
console.log("replaced", accepted, sizes.join(","));
console.log("done");
});
} else {
const bytes = new Uint8Array((workerData as Fill).buffer);
for (let i = 0; i < bytes.length; i++) bytes[i] = i % 64 === 63 ? 10 : 65 + (i % 26);
parentPort!.postMessage("filled");
}