perf(dashboard-popout): bound terminal preview resize work

This commit is contained in:
Brennan Benson
2026-07-22 16:29:29 -07:00
parent 7f5c41b625
commit bc8fa4fa81
4 changed files with 64 additions and 1 deletions
@@ -81,6 +81,9 @@ export class TerminalPreviewOutputStream {
}
append(data: string, meta?: TerminalPreviewOutputMeta): void {
if (this.isDisposed || this.awaitingReconnect || this.resyncPending) {
return
}
if (this.bufferingSnapshot) {
this.appendInitial(data, meta)
} else {
+23
View File
@@ -301,6 +301,29 @@ describe('registerTerminalPreviewHandlers', () => {
expect(runtime.unsubscribeResize).toHaveBeenCalledTimes(1)
})
it('stops batching changed-grid output while an earlier frame drains before resync', async () => {
vi.useFakeTimers()
const runtime = makeRuntime()
registerTerminalPreviewHandlers(runtime as never)
const sender = makeSender()
await handlers.get('terminalPreview:connect')!(eventFor(sender), { ptyId: 'p1' })
runtime.listeners[0]!('old')
await vi.advanceTimersByTimeAsync(5)
runtime.resizeListeners[0]!({ cols: 100, rows: 30 })
expect(sender.send).toHaveBeenCalledTimes(1)
runtime.listeners[0]!('captured by the replacement snapshot')
expect(vi.getTimerCount()).toBe(0)
handlers.get('terminalPreview:ack')!(eventFor(sender), { ptyId: 'p1', bytes: 3 })
expect(sender.send).toHaveBeenLastCalledWith('terminalPreview:data', {
type: 'resync',
ptyId: 'p1'
})
expect(sender.send).toHaveBeenCalledTimes(2)
})
it('claims the PTY grid on fit and reports the size actually in effect', async () => {
const runtime = makeRuntime()
runtime.getTerminalSize.mockReturnValue({ cols: 132, rows: 40 })
@@ -45,4 +45,38 @@ describe('createPreviewGridClaim', () => {
expect(fit).toHaveBeenCalledWith('pty-1', 90, 30)
claim.dispose()
})
it('coalesces a continuous resize burst into one settled fit request', async () => {
vi.useFakeTimers()
const fit = vi.fn(async (_ptyId: string, cols: number, rows: number) => ({ cols, rows }))
Object.assign(window, { api: { terminalPreview: { fit } } })
const box = document.createElement('div')
const container = document.createElement('div')
const screen = document.createElement('div')
screen.className = 'xterm-screen'
box.appendChild(container)
container.appendChild(screen)
dimension(box, 'clientWidth', 800)
dimension(box, 'clientHeight', 480)
dimension(screen, 'offsetWidth', 800)
dimension(screen, 'offsetHeight', 384)
const claim = createPreviewGridClaim({
ptyId: 'pty-1',
container,
getTerminal: () => ({ cols: 80, rows: 24 }) as never
})
claim.schedule()
for (let step = 1; step <= 10; step += 1) {
await vi.advanceTimersByTimeAsync(100)
dimension(box, 'clientWidth', 800 + step * 20)
claim.schedule()
}
expect(fit).not.toHaveBeenCalled()
await vi.advanceTimersByTimeAsync(200)
expect(fit).toHaveBeenCalledTimes(1)
expect(fit).toHaveBeenCalledWith('pty-1', 100, 30)
claim.dispose()
})
})
@@ -70,9 +70,12 @@ export function createPreviewGridClaim(args: {
}
const schedule = (): void => {
if (timer || disposed) {
if (disposed) {
return
}
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
timer = null
request()