Files
vue-tui/packages/runtime-tests
Yunfei He 0ba8a5ff0e fix(runtime): sync log-update with the bytes actually written on the clear path (#199)
The clear-terminal branch of renderInteractiveFrame writes raw `output` (no
trailing newline) via a direct stdout.write, but then called
`writer.sync(outputToRender)`. `outputToRender` appends "\n" for non-fullscreen
frames, so on a fullscreen→non-fullscreen transition (a fullscreen frame
shrinking below the viewport) sync recorded a state that didn't match the screen:
with a declared cursor (useCursor) it placed the persistent caret one row too
high (buildCursorSuffix with hasTrailingNewline=true, basing the caret on row
`visibleLineCount` instead of the real `visibleLineCount - 1`), and it recorded
previousLineCount off by one so the next frame's erase was eraseLines(N+1) (G46
residue). This is the fullscreen→non-fullscreen sibling of #198.

Fix: sync the SAME string just written (`output`). `outputToRender === output`
whenever the frame is fullscreen or screen-reader, so steady-state fullscreen and
SR are byte-for-byte unchanged (G17: an empty SR frame still syncs "" → zero
lines). Leaving-fullscreen, overflowing, and unmount-clear all write raw `output`,
so syncing `output` is consistent for every clear sub-case.

TDD: a new integration test mounts a fullscreen TTY frame with a declared cursor,
shrinks it below the viewport, and asserts the emitted caret row and the
following frame's erase count. Red before the fix (cursorUp(3)/eraseLines(4)),
green after (cursorUp(2)/eraseLines(3)).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 04:45:07 +08:00
..