fix(tui): stop perf-buffer leak and react to terminal resize#718
Merged
Conversation
Two fixes for the run dashboard: 1. perf_hooks leak (MaxPerformanceEntryBufferExceededWarning). ink pulls in react-reconciler, which loads its dev bundle when NODE_ENV != "production". The dev bundle emits an uncleared performance.measure() per render; at the TUI's 10 Hz poll it overflows Node's ~1M-entry perf buffer and writes a raw stderr warning (which also corrupts the in-place redraw). New loadTui() brackets the TUI's dynamic import with NODE_ENV=production (only when unset) then restores it so spawned phase children don't inherit it. Verified: 206 -> 0 measure entries for the same render workload. 2. Width corruption on resize. ink's resize handler re-renders the existing tree but does not re-run App, and App read stdout.columns imperatively — so after a resize it repainted boxes at the stale, too-wide width until the next poll, wrapping lines and misaligning borders. App now tracks columns from the stdout 'resize' event (plus a 1 Hz fallback) and clamps boxWidth to the live width. Tests: load.test.ts pins the NODE_ENV restore; App.resize.test.ts renders a real ink tree, shrinks 120->60, and asserts the box follows within one frame (fails on the un-fixed code). Entire-Checkpoint: 2b39247ae40a
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two fixes for the
sequant rundashboard.1. perf_hooks leak (
MaxPerformanceEntryBufferExceededWarning)ink pulls in
react-reconciler, which loads its development bundle wheneverNODE_ENV !== "production"(the normal dogfooding case). That bundle emits an unclearedperformance.measure()per component render; driven by the TUI's 10 Hz poll it overflows Node's ~1,000,000-entry global perf buffer and writes a raw warning to stderr — which also corrupts the in-place redraw (stderr scrolls the terminal between frames, so the erase undershoots and frames stack).Fix: new
src/ui/tui/load.ts—loadTui()brackets the TUI's single dynamicimport()withNODE_ENV=production(only when unset), caching the production reconciler (zeroperformance.measurecalls), then restoresNODE_ENVso spawned phase children don't inherit it (e.g.npm installskipping devDependencies). Both call sites (run.ts,ready.ts) now go through it.Verified: same render workload went from 206 → 0
measureentries;NODE_ENVconfirmed restored afterward.2. Width corruption on resize (duplicate / garbled frames)
ink's resize handler re-renders the existing React tree but does not re-run
App, andAppreadstdout.columnsimperatively — so after a resize it repainted boxes at the stale, too-wide width until the next 100 ms poll. Those over-wide lines wrapped while short lines didn't, misaligning the box borders into the garbled/duplicate frames.Fix (
App.tsx): trackcolumnsin state, updated from the stdoutresizeevent (plus a 1 Hz fallback for terminals that don't emit it), and clampboxWidthto the live width.Tests
load.test.ts— pins theNODE_ENVrestore behavior for every prior state.App.resize.test.ts— renders a real ink tree, shrinks 120 → 60, and asserts the box width follows within one frame (under the poll). Confirmed it fails on the un-fixed code and passes with the fix.typecheck clean; 224 tests pass in the touched areas.