From 63d37bb2737ceb57a6bd77cd16fdf20f51a63e6e Mon Sep 17 00:00:00 2001 From: Merge Sim Date: Thu, 3 Sep 2026 13:09:08 -0700 Subject: [PATCH] fix(window-close): preserve request correlation for clean closes --- ...erminal-window-lifecycle.lazy-ref.test.tsx | 20 +++++++++++++++++-- .../use-terminal-window-lifecycle.ts | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/renderer/src/components/use-terminal-window-lifecycle.lazy-ref.test.tsx b/src/renderer/src/components/use-terminal-window-lifecycle.lazy-ref.test.tsx index ce99e46db27..c0960483609 100644 --- a/src/renderer/src/components/use-terminal-window-lifecycle.lazy-ref.test.tsx +++ b/src/renderer/src/components/use-terminal-window-lifecycle.lazy-ref.test.tsx @@ -10,6 +10,10 @@ import { act, cleanup, render } from '@testing-library/react' import { afterEach, describe, expect, it, vi } from 'vitest' const collectBrowserWebviewIdsCalls = vi.hoisted(() => ({ count: 0 })) +const closeRequestHandlerRef = vi.hoisted(() => ({ + current: null as ((data: { isQuitting: boolean; requestId?: number }) => void) | null +})) +const proceedToNativeWindowCloseMock = vi.hoisted(() => vi.fn()) vi.mock('../store', () => { const state = { @@ -40,7 +44,9 @@ vi.mock('@/lib/shutdown-checkpoint-guard', () => ({ preventUnloadAndScheduleShutdownCheckpointReset: vi.fn() })) vi.mock('./window-close-request-coordinator', () => ({ - setWindowCloseRequestHandler: vi.fn() + setWindowCloseRequestHandler: (handler: typeof closeRequestHandlerRef.current) => { + closeRequestHandlerRef.current = handler + } })) const { useTerminalWindowLifecycle } = await import('./use-terminal-window-lifecycle') @@ -49,7 +55,7 @@ const controller = { activeBrowserTabId: null, activeTabType: 'terminal', activeWorktreeBrowserTabIdsKey: '', - proceedToNativeWindowClose: () => {}, + proceedToNativeWindowClose: proceedToNativeWindowCloseMock, queueEditorCloseRequests: () => {}, renderedActiveWorktreeId: null, setActiveBrowserTab: () => {}, @@ -69,6 +75,8 @@ function Host(): null { afterEach(() => { cleanup() collectBrowserWebviewIdsCalls.count = 0 + closeRequestHandlerRef.current = null + proceedToNativeWindowCloseMock.mockReset() bumpRender = null }) @@ -83,4 +91,12 @@ describe('useTerminalWindowLifecycle browser-webview id seed', () => { expect(collectBrowserWebviewIdsCalls.count).toBe(1) }) + + it('forwards requestId when a clean close proceeds natively', () => { + render() + + closeRequestHandlerRef.current?.({ isQuitting: true, requestId: 42 }) + + expect(proceedToNativeWindowCloseMock).toHaveBeenCalledWith(true, 42) + }) }) diff --git a/src/renderer/src/components/use-terminal-window-lifecycle.ts b/src/renderer/src/components/use-terminal-window-lifecycle.ts index 13faf85d8d7..3ec2c8e2de8 100644 --- a/src/renderer/src/components/use-terminal-window-lifecycle.ts +++ b/src/renderer/src/components/use-terminal-window-lifecycle.ts @@ -54,7 +54,7 @@ export function useTerminalWindowLifecycle(controller: TerminalActivationControl ) return } - proceedToNativeWindowClose(isQuitting) + proceedToNativeWindowClose(isQuitting, requestId) }) return () => setWindowCloseRequestHandler(null) // oxlint-disable-next-line react-hooks/exhaustive-deps -- controller refs preserve their original stable identities.