From e43f121dfbf049ed2f5ba51c9843c8af4c287c85 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sat, 30 May 2026 21:44:54 -0400 Subject: [PATCH] refactor(ext/popup): extract teardownSettingsCommon (Plan C Phase 5) DEV-C P2: settings.ts:56-65 and settings-vault.ts:15-22 had near- identical cleanup paths. Single source for closeGeneratorPanel + activeKeyHandler removal. Helper takes the handler as a parameter and returns null so each caller still owns its own module-scoped handler state. Co-Authored-By: Claude Opus 4.7 --- .../src/popup/components/settings-vault.ts | 7 ++--- extension/src/popup/components/settings.ts | 26 +++++++++++++++---- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/extension/src/popup/components/settings-vault.ts b/extension/src/popup/components/settings-vault.ts index cc5038e..36add5b 100644 --- a/extension/src/popup/components/settings-vault.ts +++ b/extension/src/popup/components/settings-vault.ts @@ -9,6 +9,7 @@ import type { import type { SessionTimeoutConfig } from '../../shared/messages'; import { relativeTime } from '../../shared/relative-time'; import { openGeneratorPanel, closeGeneratorPanel, isGeneratorPanelOpen } from './generator-panel'; +import { teardownSettingsCommon } from './settings'; import { GLYPH_NEXT } from '../../shared/glyphs'; let pendingSettings: VaultSettings | null = null; @@ -17,11 +18,7 @@ let pendingSession: SessionTimeoutConfig | null = null; let baseSession: SessionTimeoutConfig | null = null; export function teardown(): void { - closeGeneratorPanel(); - if (activeKeyHandler) { - document.removeEventListener('keydown', activeKeyHandler); - activeKeyHandler = null; - } + activeKeyHandler = teardownSettingsCommon(activeKeyHandler); pendingSettings = null; pendingSession = null; baseSession = null; diff --git a/extension/src/popup/components/settings.ts b/extension/src/popup/components/settings.ts index a4021ba..cacd7e6 100644 --- a/extension/src/popup/components/settings.ts +++ b/extension/src/popup/components/settings.ts @@ -53,13 +53,29 @@ export async function renderSettings(container: HTMLElement): Promise { await renderSection(activeSection); } -export function teardownSettings(): void { +/** + * Common cleanup invoked by both the device-settings teardown + * (settings.ts) and the vault-settings teardown (settings-vault.ts). + * Centralized to avoid the "regression class with known prior leaks" + * DEV-C P2 flagged. + * + * Closes the generator popover and detaches the supplied keydown + * handler from the document if present. Returns the new handler value + * (always null), so the caller can do `handler = teardownSettingsCommon(handler)`. + */ +export function teardownSettingsCommon( + keyHandler: ((e: KeyboardEvent) => void) | null, +): null { closeGeneratorPanel(); - teardownSecuritySection(); - if (activeKeyHandler) { - document.removeEventListener('keydown', activeKeyHandler); - activeKeyHandler = null; + if (keyHandler) { + document.removeEventListener('keydown', keyHandler); } + return null; +} + +export function teardownSettings(): void { + activeKeyHandler = teardownSettingsCommon(activeKeyHandler); + teardownSecuritySection(); pendingVaultSettings = null; sessionHandle = null; }