Files
scriptc/tests/corpus/stdout-write-patch.ts
T
Malte UblandClaude Opus 5.5 2b03f66ff3 Host patching H1: typed process output write slot
Reading `process.stdout.write` as a value, `write.bind(stream)`, and
`process.stdout.write = fn` now reach the runtime stream object's write
slot in TypeScript, and a program that replaces an output write method
calls its typed writes through that slot (SC8020 refuses the combination
with Node islands until H2 shares the stream object with them).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:37:56 -07:00

43 lines
2.0 KiB
TypeScript

// Replacing process.stdout.write from TypeScript: the output-guard idiom.
// The real write methods are taken first with bind (they write straight
// to the descriptor, past any later patch). The replacement then sees
// every stdout write: console.log's lines, direct string and byte writes
// with their encoding and callback arguments as passed. Assigning the
// saved method back restores the stream.
type RawWrite = (chunk: string, callback?: (error?: Error | null) => void) => boolean;
const rawStdout = process.stdout.write.bind(process.stdout) as RawWrite;
const rawStderr = process.stderr.write.bind(process.stderr) as RawWrite;
const original = process.stdout.write;
const captured: string[] = [];
function text(chunk: string | Uint8Array): string {
return typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
}
process.stdout.write = ((
chunk: string | Uint8Array,
encodingOrCallback?: BufferEncoding | ((error?: Error | null) => void),
callback?: (error?: Error | null) => void,
): boolean => {
const done = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
const encoding = typeof encodingOrCallback === "string" ? encodingOrCallback : "-";
captured.push(`${typeof chunk === "string" ? "string" : "bytes"}/${encoding}:${text(chunk).trimEnd()}`);
return rawStderr(`[redirected] ${text(chunk)}`, done);
}) as typeof process.stdout.write;
console.log("from console.log", 42);
process.stdout.write("direct string\n");
process.stdout.write(new Uint8Array([104, 105, 10]));
process.stdout.write("6869210a", "hex");
process.stdout.write("with callback\n", (error) => {
rawStderr(`callback error is null: ${error === null}\n`);
});
const accepted = process.stdout.write("result\n");
rawStdout("raw stdout bypasses the patch\n");
console.log("same method", process.stdout.write === original, accepted);
process.stdout.write = original;
console.log("restored", process.stdout.write === original);
console.log(captured.join(" | "));