-
-
Notifications
You must be signed in to change notification settings - Fork 842
fix: make unmount flush pending renders and await stdout drain #863
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: make unmount flush pending renders and await stdout drain #863
Conversation
|
I do not think we need a public flush API. The real fix can live inside existing behavior: make unmount force the final render without throttling, and have |
Instead of adding a public flush() API, this modifies the existing unmount() to flush throttled renders/log writes before the final render, and waitUntilExit() to await stdout drain before resolving. Users can use `process.exitCode` + `await waitUntilExit()` for guaranteed output. Closes vadimdemedes#796
26eb6c2 to
edab70d
Compare
|
Great feedback, agreed! I've revised this PR to avoid adding a public
Users can use |
|
Replace the writableNeedDrain check with a stdout.write('', callback)
barrier so waitUntilExit() only resolves after all queued write
callbacks have completed, regardless of stream backpressure state.
Add regression test with a delayed custom Writable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Thanks @sindresorhus, great catch on both points. P1 – write callback barrier: You're right, gating on P2 – regression test: Added a test using a custom |
The empty write barrier (stdout.write('', callback)) records an
observable call on sinon spy-based test stdouts, breaking tests that
check lastCall. Detect real writable streams via _writableState or
writableLength and only use the write barrier for those. For non-stream
objects (test spies), resolve via setImmediate instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Follow-up fix: the empty write barrier ( |
When signal-exit calls unmount() during process shutdown, the event loop is draining and async callbacks (stdout.write barrier, setImmediate) may never fire. Detect this case by checking if the error parameter is a number or null (signal-exit signature) rather than undefined/Error (manual unmount), and resolve the exit promise synchronously. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Pushed an additional fix (6d537d2): when The detection works by checking the Regarding the 2 remaining CI failures ( |
Summary
unmount()flush pending throttled renders and log writes before the final render, so the last frame is always displayedwaitUntilExit()await the stdout drain callback, so the promise only resolves once buffered writes are actually flushed to the terminalprocess.exitCode+await waitUntilExit()instead ofprocess.exit()for guaranteed final outputChanges
unmount()now callsthis.throttledOnRender.flush()andthis.throttledLog.flush()before the final renderstdout.writableNeedDrainis false (or thedrainevent fires)flush()public method,src/flush.ts, andflushexportTest plan
Closes #796