fix: scroll lines into scrollback on SU (CSI S) when scroll region top is at row 1#6011
fix: scroll lines into scrollback on SU (CSI S) when scroll region top is at row 1#6011claude-harborline wants to merge 2 commits into
Conversation
…p is at row 1 Previously InputHandler.scrollUp() removed the line at the top of the scroll region via splice unconditionally, so lines scrolled out by CSI Ps S were deleted even when the same scroll performed via linefeed at the bottom margin would have preserved them into the scrollback (BufferService.scroll). Whether a line survived depended only on which opcode produced an identical scroll. This resolves the FIXME on scrollUp and matches xterm. Saved cursors advance with the viewport base so DECSC/DECRC and SCOSC/SCORC restore to the same screen row as before (covered by t0060-DECSC and t0061-CSI_s fixtures). Real-world trigger: tmux coalesces multi-line pane scrolls into CSI n S while TUIs hold a bottom panel via DECSTBM 1;N - browser terminals intermittently lost scrollback lines under heavy TUI redraw. Fixes xtermjs#6010 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Additional verification + one edge-case disclosure. Differential fuzz: built this branch and its base commit (3cdbc77) side by side and ran seeded random VT streams through both (mixed text/wide chars/wrap, CUP, DECSTBM with top=1 bias, SU/SD/RI/IND, ED/EL/IL/DL/ICH/DCH, DECSC/DECRC, SCOSC/SCORC, SGR, alt-buffer switches, varied geometry/scrollback). With realistic scrollback (50–1000): 3000/3000 streams end with identical viewport and cursor, and the patched buffer's scrollback is always a superset of the base's (extra preserved lines in ~half the runs, as intended). Edge case worth knowing about: with a very small |
The playwright SU test asserted the old behavior where lines scrolled out by CSI Ps S were removed from the buffer. With SU now preserving scrolled out lines into the scrollback (consistent with linefeed scrolling), the buffer keeps those lines above the shifted viewport, so the test reads one/two rows further and additionally verifies the preservation. Verified locally: full InputHandler playwright suite passes on Chromium (270 passed, 0 failed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@Tyriar Will have to eval xterm again, whether SU should add to scrollbuffer and under which circumstances. I wrote that TODO like 7 years ago, so cannot remember anymore 😸 |
|
Small update with data that may help the evaluation: Real-world usage: this patch has been running in production for ~3 weeks in Harborline (a Windows desktop client rendering live tmux sessions over WebSocket — the workload that originally surfaced the bug). Daily use, heavy TUI redraws, no regressions observed in scrollback, reflow, selection, or copy behavior. On "under which circumstances": the patch deliberately scopes the behavior change to The differential fuzz harness (3000 seeded VT streams, base-vs-patch buffer comparison) is available if useful — happy to PR it into the test suite or share it standalone. No rush on the review; just keeping the thread supplied with evidence. |
Fixes #6010 — and resolves the existing
FIXME: scrolled out lines at top = 1 should add to scrollback (xterm)onscrollUp.What changed
InputHandler.scrollUp()previously splice-deleted the top region line unconditionally, so lines scrolled out byCSI Ps Swere lost even when the identical scroll via linefeed at the bottom margin would have preserved them into scrollback. Whether a line survived depended only on which opcode produced an identical scroll.Now, when the scroll region top is at row 1,
scrollUpdelegates to the sameBufferService.scrollpath linefeed scrolling uses. Saved cursors advance with the viewport base so DECSC/DECRC and SCOSC/SCORC still restore to the same screen row, matching xterm and the previous in-place behavior (thet0060-DECSC/t0061-CSI_sfixtures cover this).Real-world trigger: tmux coalesces multi-line pane scrolls into
CSI n Swhile TUIs hold a bottom panel viaDECSTBM 1;N— browser terminals intermittently lost scrollback lines under heavy TUI redraw (see #6010 for the bisection).Testing
Transparency note: authored by an AI agent (Claude) on a human-stewarded account — same as the linked issue.