fix: cap unlimited terminal scrollback
Some checks failed
build-packages / dedupe push run (push) Has been cancelled
build-packages / dedupe result (push) Has been cancelled
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-x64' || 'build-linux-x64' }} (push) Has been cancelled
build-packages / ${{ needs.dedupe.outputs.skip_heavy_ci == 'true' && 'deduped build-linux-arm64' || 'build-linux-arm64' }} (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled

This commit is contained in:
sakuradairong
2026-06-19 11:05:06 +08:00
parent 52bc48f73a
commit 850d038c5a
4 changed files with 29 additions and 5 deletions

View File

@@ -15,6 +15,7 @@ import { fontStore } from "../../../application/state/fontStore";
import { KeywordHighlighter } from "../keywordHighlight";
import {
XTERM_PERFORMANCE_CONFIG,
resolveXTermScrollback,
type XTermPlatform,
resolveXTermPerformanceConfig,
} from "../../../infrastructure/config/xtermPerformance";
@@ -270,11 +271,8 @@ export const createXTermRuntime = (ctx: CreateXTermRuntimeContext): XTermRuntime
const cursorStyle = settings?.cursorShape ?? "block";
const cursorBlink = settings?.cursorBlink ?? true;
// xterm.js treats scrollback=0 as "no scrollback buffer", which breaks mouse
// wheel scrolling (events become arrow-key sequences). The UI uses 0 to mean
// "no limit", so map it to a large value instead.
const rawScrollback = settings?.scrollback ?? 10000;
const scrollback = rawScrollback === 0 ? 999999 : rawScrollback;
const scrollback = resolveXTermScrollback(rawScrollback);
const drawBoldTextInBrightColors = settings?.drawBoldInBrightColors ?? true;
const fontWeight = resolveHostTerminalFontWeight(ctx.host, settings?.fontWeight ?? 400);
const fontWeightBold = settings?.fontWeightBold ?? 700;

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any, react-hooks/exhaustive-deps */
import { useRef } from 'react';
import { resolveFontWeightBold } from '../../lib/fontWeightAvailability';
import { resolveXTermScrollback } from '../../infrastructure/config/xtermPerformance';
import { shouldInterceptMouseTrackingContextMenu } from './runtime/middleClickBehavior';
type TerminalEffectsContext = Record<string, any>;
@@ -465,7 +466,7 @@ export function useTerminalEffects(ctx: TerminalEffectsContext) {
if (terminalSettings) {
applyUserCursorPreference(termRef.current, terminalSettings);
termRef.current.options.scrollback = terminalSettings.scrollback === 0 ? 999999 : terminalSettings.scrollback;
termRef.current.options.scrollback = resolveXTermScrollback(terminalSettings.scrollback);
termRef.current.options.fontWeight = effectiveFontWeight as
| 100
| 200

View File

@@ -0,0 +1,17 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import {
XTERM_UNLIMITED_SCROLLBACK_CAP,
resolveXTermScrollback,
} from './xtermPerformance';
test('resolveXTermScrollback maps the unlimited sentinel to a 50000 row cap', () => {
assert.equal(XTERM_UNLIMITED_SCROLLBACK_CAP, 50000);
assert.equal(resolveXTermScrollback(0), 50000);
});
test('resolveXTermScrollback preserves explicit positive scrollback values', () => {
assert.equal(resolveXTermScrollback(10000), 10000);
assert.equal(resolveXTermScrollback(50000), 50000);
});

View File

@@ -8,6 +8,14 @@
* - Memory pressure handling
*/
export const XTERM_UNLIMITED_SCROLLBACK_CAP = 50000;
export function resolveXTermScrollback(scrollback: number): number {
// xterm.js treats 0 as "no scrollback". Keep the app's 0 sentinel useful
// without asking xterm to resize/reflow nearly one million buffer rows.
return scrollback === 0 ? XTERM_UNLIMITED_SCROLLBACK_CAP : scrollback;
}
export const XTERM_PERFORMANCE_CONFIG = {
// Memory and Scrollback Settings
scrollback: {