Clean up runtime environment IPC registration

This commit is contained in:
Neil 2026-05-30 13:29:41 -07:00 committed by GitHub
parent 4f035f4bff
commit 8553ed9d43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 1 deletions

View File

@ -10,6 +10,8 @@ import * as environmentStore from '../../shared/runtime-environment-store'
const {
handleMock,
onMock,
removeHandlerMock,
removeAllListenersMock,
getPathMock,
sendRemoteRuntimeRequestMock,
subscribeRemoteRuntimeRequestMock,
@ -18,6 +20,8 @@ const {
} = vi.hoisted(() => ({
handleMock: vi.fn(),
onMock: vi.fn(),
removeHandlerMock: vi.fn(),
removeAllListenersMock: vi.fn(),
getPathMock: vi.fn(),
sendRemoteRuntimeRequestMock: vi.fn(),
subscribeRemoteRuntimeRequestMock: vi.fn(),
@ -27,7 +31,12 @@ const {
vi.mock('electron', () => ({
app: { getPath: getPathMock },
ipcMain: { handle: handleMock, on: onMock }
ipcMain: {
handle: handleMock,
on: onMock,
removeHandler: removeHandlerMock,
removeAllListeners: removeAllListenersMock
}
}))
vi.mock('../../shared/remote-runtime-client', () => ({
@ -68,6 +77,8 @@ describe('registerRuntimeEnvironmentHandlers', () => {
getPathMock.mockReturnValue(userDataPath)
handleMock.mockReset()
onMock.mockReset()
removeHandlerMock.mockReset()
removeAllListenersMock.mockReset()
sendRemoteRuntimeRequestMock.mockReset()
subscribeRemoteRuntimeRequestMock.mockReset()
sendRemoteRuntimeConnectionRequestMock.mockReset()
@ -96,6 +107,22 @@ describe('registerRuntimeEnvironmentHandlers', () => {
])
})
it('clears stale IPC registrations before registering runtime environment handlers', () => {
registerRuntimeEnvironmentHandlers()
expect(removeHandlerMock.mock.calls.map((call) => call[0])).toEqual([
'runtimeEnvironments:list',
'runtimeEnvironments:addFromPairingCode',
'runtimeEnvironments:resolve',
'runtimeEnvironments:remove',
'runtimeEnvironments:getStatus',
'runtimeEnvironments:call',
'runtimeEnvironments:subscribe',
'runtimeEnvironments:unsubscribe'
])
expect(removeAllListenersMock).toHaveBeenCalledWith('runtimeEnvironments:subscriptionBinary')
})
it('stores, resolves, lists, and removes environments under Electron userData', async () => {
registerRuntimeEnvironmentHandlers()

View File

@ -28,6 +28,17 @@ import {
} from './runtime-environment-request-connections'
const DEFAULT_REMOTE_RUNTIME_TIMEOUT_MS = 15_000
const RUNTIME_ENVIRONMENT_HANDLER_CHANNELS = [
'runtimeEnvironments:list',
'runtimeEnvironments:addFromPairingCode',
'runtimeEnvironments:resolve',
'runtimeEnvironments:remove',
'runtimeEnvironments:getStatus',
'runtimeEnvironments:call',
'runtimeEnvironments:subscribe',
'runtimeEnvironments:unsubscribe'
] as const
type RetainedRemoteRuntimeSubscription = RemoteRuntimeSubscription & {
ownerWebContentsId: number
removeDestroyedListener: () => void
@ -43,6 +54,13 @@ function shouldUseCachedRequestConnection(method: string): boolean {
}
export function registerRuntimeEnvironmentHandlers(): void {
// Why: keep direct re-registration safe even though register-core-handlers
// normally guards this path; otherwise the binary send listener can stack.
for (const channel of RUNTIME_ENVIRONMENT_HANDLER_CHANNELS) {
ipcMain.removeHandler(channel)
}
ipcMain.removeAllListeners('runtimeEnvironments:subscriptionBinary')
ipcMain.handle('runtimeEnvironments:list', (): PublicKnownRuntimeEnvironment[] =>
listEnvironments(getUserDataPath()).map(redactRuntimeEnvironment)
)