withLoopAlive<T>(work: () => Promise<T>): Promise<T>
Runs work with the event loop held open, so it cannot end by everything going quiet.
A run's handles are deliberately not enough to keep Node alive: the pre-launched Chrome and its
stderr pipe are unref'd (see chrome/spawn.ts), page and server closes are bounded by unref'd
timers, and Playwright drops its transport the moment a browser dies. So a browser that dies at
the wrong moment leaves a process with nothing left to do, and a process with nothing left to do
exits — reporting code 0, having printed nothing but its header. That is not a theory: Windows CI
run 35946105100 announced # Running 1 test file across 1 group, went silent for 21s, and exited
0, with an assertion in line-target-test.ts as the only sign that a run had been lost.
Held open, the same failure has to end as a failure — a timeout, a rejection, something said out
loud — because nothing else can end the process while this is armed. The finally is what makes
that safe to wrap around anything: an interval nobody clears is the opposite bug.
import { withLoopAlive } from './with-loop-alive.ts'; await withLoopAlive(() => Promise.resolve('finished')); // 'finished'
work: () => Promise<T>
Promise<T>