mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-01 07:33:12 +08:00
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>
43 lines
2.0 KiB
TypeScript
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(" | "));
|