From 7c4dd7d660f3ea3872c7a9fea873ecb388738e5e Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Thu, 23 Apr 2026 12:49:49 -0500 Subject: [PATCH] refactor(ui-tui): collapse xterm.js resize settle dance Replace 28-line guard + nested queueMicrotask + pendingResizeRender flag-reuse with a named canAltScreenRepaint predicate and a single flat paint. setTimeout already drained the burst coalescer; the nested defer and flag dance were paranoia. --- ui-tui/packages/hermes-ink/src/ink/ink.tsx | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ui-tui/packages/hermes-ink/src/ink/ink.tsx b/ui-tui/packages/hermes-ink/src/ink/ink.tsx index 036954a770..5a32ceeffd 100644 --- a/ui-tui/packages/hermes-ink/src/ink/ink.tsx +++ b/ui-tui/packages/hermes-ink/src/ink/ink.tsx @@ -463,33 +463,21 @@ export default class Ink { this.resetFramesForAltScreen() this.needsEraseBeforePaint = true + // xterm.js burst-drift healer: 160ms after the last resize, force one + // full reconcile so Yoga/React catch up to the final viewport. No flag + // dance — setTimeout already drained the burst coalescer; a concurrent + // render would be idempotent. if (isXtermJs()) { this.resizeSettleTimer = setTimeout(() => { this.resizeSettleTimer = null - if ( - this.isUnmounted || - this.isPaused || - !this.altScreenActive || - !this.options.stdout.isTTY || - this.currentNode === null || - this.pendingResizeRender - ) { + if (!this.canAltScreenRepaint()) { return } - this.pendingResizeRender = true - queueMicrotask(() => { - this.pendingResizeRender = false - - if (this.isUnmounted || this.isPaused || !this.altScreenActive || !this.options.stdout.isTTY || this.currentNode === null) { - return - } - - this.resetFramesForAltScreen() - this.needsEraseBeforePaint = true - this.render(this.currentNode) - }) + this.resetFramesForAltScreen() + this.needsEraseBeforePaint = true + this.render(this.currentNode!) }, 160) } } @@ -513,6 +501,17 @@ export default class Ink { this.render(this.currentNode) }) } + + private canAltScreenRepaint(): boolean { + return ( + !this.isUnmounted && + !this.isPaused && + this.altScreenActive && + !!this.options.stdout.isTTY && + this.currentNode !== null + ) + } + resolveExitPromise: () => void = () => {} rejectExitPromise: (reason?: Error) => void = () => {} unsubscribeExit: () => void = () => {} @@ -1970,6 +1969,7 @@ export default class Ink { clearTimeout(this.drainTimer) this.drainTimer = null } + if (this.resizeSettleTimer !== null) { clearTimeout(this.resizeSettleTimer) this.resizeSettleTimer = null