fix: drop late remote terminal subscription handles (#4254)

This commit is contained in:
Neil
2026-05-31 09:46:55 -07:00
committed by GitHub
parent 12d75587a5
commit a263ed36fd
2 changed files with 46 additions and 4 deletions
@@ -174,7 +174,7 @@ class RemoteRuntimeTerminalMultiplexer {
if (this.connectPromise) {
return this.connectPromise
}
this.connectPromise = new Promise<void>((resolve, reject) => {
const connectPromise = new Promise<void>((resolve, reject) => {
this.readyResolver = resolve
this.readyRejecter = reject
void window.api.runtimeEnvironments
@@ -193,16 +193,26 @@ class RemoteRuntimeTerminalMultiplexer {
}
)
.then((subscription) => {
if (this.connectPromise !== connectPromise || (!this.ready && !this.readyRejecter)) {
// Why: close/error can arrive before subscribe() resolves because
// preload listens before ipcMain.handle() returns. The multiplexer
// may already be released; do not retain the late handle.
subscription.unsubscribe()
return
}
this.subscription = subscription
this.resolveReadyIfConnected()
})
.catch((error) => {
this.connectPromise = null
this.readyResolver = null
this.readyRejecter = null
if (this.connectPromise === connectPromise) {
this.connectPromise = null
this.readyResolver = null
this.readyRejecter = null
}
reject(error instanceof Error ? error : new Error(String(error)))
})
})
this.connectPromise = connectPromise
return this.connectPromise
}
@@ -46,6 +46,8 @@ describe('remote runtime terminal data subscriptions', () => {
let callbacks: {
onResponse: (response: unknown) => void
onBinary?: (bytes: Uint8Array<ArrayBufferLike>) => void
onError?: (error: { message: string }) => void
onClose?: () => void
} | null = null
beforeEach(() => {
@@ -156,4 +158,34 @@ describe('remote runtime terminal data subscriptions', () => {
expect(sendBinary).not.toHaveBeenCalled()
expect(_getRemoteRuntimeTerminalMultiplexerCountForTest()).toBe(0)
})
it('unsubscribes a late subscription handle after pre-resolution transport close', async () => {
let resolveSubscribe!: (handle: {
unsubscribe: () => void
sendBinary: typeof sendBinary
}) => void
runtimeSubscribe.mockImplementationOnce((_args: unknown, nextCallbacks: typeof callbacks) => {
callbacks = nextCallbacks
callbacks?.onClose?.()
return new Promise((resolve) => {
resolveSubscribe = resolve
})
})
const subscriptionPromise = subscribeToRuntimeTerminalData(
{ activeRuntimeEnvironmentId: 'env-fallback' },
'remote:env-1@@terminal-1',
'watcher-1',
vi.fn()
)
await expect(subscriptionPromise).rejects.toThrow('Remote Orca runtime closed the connection.')
expect(_getRemoteRuntimeTerminalMultiplexerCountForTest()).toBe(0)
expect(unsubscribe).not.toHaveBeenCalled()
resolveSubscribe({ unsubscribe, sendBinary })
await Promise.resolve()
expect(unsubscribe).toHaveBeenCalledOnce()
})
})