shim js: narration goes to stderr under node, not console.debug (stdout)

c47bbff1 moved shim notes from warn_line to trace_line, whose console.debug
is stdout under node: an ejected program's compared output gained a
provider line, and tests/elf-prov/run-browser.sh lost the 'addresses bound'
lines it counts on stderr. host.mjs's [host] lines had the same problem.
In a page narration stays on the debug console.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_781bad2ec05143db9067c86b4b2678e2
This commit is contained in:
velzieandClaude Opus 5.5 committed 2026-10-10 17:36:36 -04:00
1 parent 893a2e6d1c
commit 8c14585aff
2 files changed
+23 -6

No files matched your search

+12 -3
View File
@@ -268,7 +268,16 @@ function debugLine(text) {
}
} catch {}
}
console.debug(text);
narrate(text);
}
// Narration under node goes to stderr: node's console.debug is stdout, which
// is the guest's own output there (an ejected program's, a test's compared
// output). In a page it stays on the debug console.
export function narrate(text) {
const stderr = typeof process !== 'undefined' ? process.stderr : null;
if (stderr?.write) stderr.write(`${text}\n`);
else console.debug(text);
}
// Dispatch slots one 4 KiB guest page covers (`gex_abi::SLOTS_PER_PAGE`) and
@@ -1813,7 +1822,7 @@ export class Gex {
const text = utf8(this.#bytes().slice(p, p + n));
// Only when it has stopped changing: a wedged process repeats the same
// wait forever, which is the signal; a busy one churns through them.
if (text === last) console.debug(`[gex] quiet: ${text}`);
if (text === last) narrate(`[gex] quiet: ${text}`);
last = text;
}
e.gex_free?.(p, 512);
@@ -4821,7 +4830,7 @@ export class Gex {
const fs = trace ? globalThis.process?.getBuiltinModule?.('fs') : null;
if (fs) fs.writeSync(2, `${line}\n`);
// A size report, not an error (a console error fails a page test).
else console.debug(line);
else narrate(line);
}
const [, a, b] = key.split(':');
e.gex_jit_note_external(BigInt(off), bytes.length, Number(a) | 0, Number(b) | 0);
+11 -3
View File
@@ -7,6 +7,14 @@
// than a message back through here. This file starts pid 1, makes a Worker per
// fork, relays I/O, and holds the run open until pid 1 exits.
// Narration under node goes to stderr: node's console.debug is stdout, the
// guest's own output there. In a page it stays on the debug console.
function narrate(text) {
const stderr = typeof process !== 'undefined' ? process.stderr : null;
if (stderr?.write) stderr.write(`${text}\n`);
else console.debug(text);
}
/**
* Announce a crash to an automated watcher. These failures are caught (the
* spawn promise is rejected and handled), so no `error` event fires and a test
@@ -244,7 +252,7 @@ export class ProcessHost {
// One line per process, to `debug`: a process that never starts leaves
// no other trace -- the fork is logged by the parent, the exit by the
// child. #137.
console.debug(`[host] pid ${pid}: worker taken, ${msg.kind} held for ready`);
narrate(`[host] pid ${pid}: worker taken, ${msg.kind} held for ready`);
// And now whatever it said while it was still in the pool.
const held = w[EARLY];
if (held) {
@@ -323,7 +331,7 @@ export class ProcessHost {
if (!res.ok) throw new Error(`${entry.url}: ${res.status} ${res.statusText}`);
const bytes = new Uint8Array(await res.arrayBuffer());
const mod = await WebAssembly.compile(bytes);
console.debug(
narrate(
`[gex] closure library ${i}: ${(bytes.length / 1048576).toFixed(1)} MiB `
+ `fetched and compiled in ${Math.round(performance.now() - t0)}ms`,
);
@@ -390,7 +398,7 @@ export class ProcessHost {
}
const msg = this.#pending.get(pid);
this.#pending.delete(pid);
console.debug(`[host] pid ${pid}: ready, ${msg ? `sending ${msg.kind}` : 'NOTHING HELD'}`);
narrate(`[host] pid ${pid}: ready, ${msg ? `sending ${msg.kind}` : 'NOTHING HELD'}`);
if (msg) {
// Awaited: compiling the shim cannot be synchronous in a browser.
this.#shimModule().then((shimMod) => {