fix(dashboard-auth): ChatPage cleanup closes WS via wsRef.current

Phase 5.3 (1c99c2f5e) wrapped the WS construction in an IIFE so the
gated-mode ticket fetch could resolve asynchronously, but the effect's
top-level cleanup still referenced the IIFE-scoped `const ws`. TypeScript
catches it at build time:

  src/pages/ChatPage.tsx:654:7 - error TS2304: Cannot find name 'ws'.

LSP-cache-lag drowned the diagnostic under the JSX-types-missing noise
locally, so the bug shipped uncaught. Switch to `wsRef.current?.close()`
which:

  - resolves to the same WebSocket the IIFE assigned (line 562:
    `wsRef.current = ws`)
  - is null-safe when unmount races the ticket fetch (the IIFE early-
    returns on `unmounting` so wsRef.current is never set)

The ChatSidebar.tsx + gatewayClient.ts cleanup paths were already using
this pattern correctly (`ws?.close()` / `ws` was hoisted), so this fix
is ChatPage-only.
This commit is contained in:
Ben 2026-05-21 18:01:34 +10:00 committed by Teknium
parent 7c9cdbc093
commit af3d4a687f

View file

@ -651,7 +651,12 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
if (hostSyncRaf) cancelAnimationFrame(hostSyncRaf);
if (settleRaf1) cancelAnimationFrame(settleRaf1);
if (settleRaf2) cancelAnimationFrame(settleRaf2);
ws.close();
// Phase 5.3: ``ws`` is local to the IIFE that opens it (the gated-mode
// ticket fetch makes the open async). The cleanup runs at the outer
// effect's top level so it can't reach into that scope — close via
// the ref instead. ``?.`` covers the race where unmount fires before
// the ticket fetch resolves and ``wsRef.current`` was never assigned.
wsRef.current?.close();
wsRef.current = null;
term.dispose();
termRef.current = null;