console Chrome never outlives its run: exit kills it, SIGINT / SIGTERM / SIGHUP close it gracefully, a detached watchdog ends it when the parent dies (SIGKILL included; a reused pid is never killed); every start ends headless orphans on storebound profiles and names orphaned windows; headless runs on macOS prefer Chromium / Chrome for Testing over Google Chrome.app (an orphan kept the owner's Chrome from opening from the Dock); console fill closes the window on errors; pitfall 68; tests

This commit is contained in:
CRTkafa 2026-10-15 00:28:32 +08:00
parent b350781ab5
commit 89d94d6993
10 changed files with 372 additions and 17 deletions

View file

@ -203,6 +203,8 @@ export interface SpawnOptions {
stderr?: Io | null;
/** [stdin, stdout, stderr]; wins over the single options. */
stdio?: [Io | null, Io | null, Io | null];
/** Its own process group (session): a Ctrl+C sent to the terminal's group does not reach it. */
detached?: boolean;
}
/** A running child, shaped like Bun's Subprocess (the parts storebound uses). */
@ -258,7 +260,7 @@ export function spawn(argv: string[], o: SpawnOptions = {}): Subprocess {
const cmd = checkExecutable(argv[0], o);
const [i0, o0, e0] = o.stdio ?? [o.stdin, o.stdout, o.stderr];
const stdio: StdioOptions = [io(i0, 'ignore'), io(o0, 'pipe'), io(e0, 'inherit')];
const child = nodeSpawn(cmd, argv.slice(1), { cwd: o.cwd, env: envOf(o.env) ?? process.env, stdio, windowsHide: true });
const child = nodeSpawn(cmd, argv.slice(1), { cwd: o.cwd, env: envOf(o.env) ?? process.env, stdio, windowsHide: true, ...(o.detached ? { detached: true } : {}) });
let exitCode: number | null = null, signalCode: string | null = null;
const exited = new Promise<number>(res => {
let done = false;