From 72de2f6765bcf6a63e0ea31f452b70ce24b911d5 Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Wed, 5 Aug 2026 14:23:59 -0700 Subject: [PATCH] fix(terminal): clear stale parked frame on empty snapshot --- .../remote-runtime-pty-transport.test.ts | 19 +++++++++++++++++++ .../remote-runtime-pty-transport.ts | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.test.ts b/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.test.ts index d0b63186d48..328a2d15386 100644 --- a/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.test.ts +++ b/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.test.ts @@ -889,6 +889,25 @@ describe('createRemoteRuntimePtyTransport', () => { transport.destroy?.() }) + it('forwards an empty authoritative snapshot so a cached parked viewport clears', async () => { + const { createRemoteRuntimePtyTransport } = await import('./remote-runtime-pty-transport') + const onReplayData = vi.fn() + const transport = createRemoteRuntimePtyTransport('env-1', { + worktreeId: 'wt-1', + tabId: 'web-terminal-host-tab-1', + leafId: 'pane:1' + }) + + const connect = transport.connect({ url: '', callbacks: { onReplayData } }) + await vi.waitFor(() => expect(subscriptionSendBinary).toHaveBeenCalled()) + emitSnapshot(latestSubscribePayload().streamId, '') + await connect + + expect(onReplayData).toHaveBeenCalledOnce() + expect(onReplayData).toHaveBeenCalledWith('') + transport.destroy?.() + }) + it('keeps the current mirror input queue when an older connect settles', async () => { const healthyRuntimeCall = runtimeCall.getMockImplementation() let releaseFirstActivation = (): void => {} diff --git a/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts b/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts index b0a3ed893ac..a50fbb1a200 100644 --- a/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts +++ b/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts @@ -1858,8 +1858,8 @@ export function createRemoteRuntimePtyTransport( } }, onSnapshot: (data, meta) => { - // Why: an empty snapshot can still carry a pending mid-escape tail that must replay so the next live chunk completes it. - if ((data || meta?.pendingEscapeTailAnsi) && isCurrentSubscription()) { + // Why: an empty snapshot is still authoritative and must clear a cached parked viewport. + if (isCurrentSubscription()) { if (subscribedPtyId && bufferPtyShutdownReplayData(subscribedPtyId, data)) { return }