Fix useAutomationChat missing onUnmounted cleanup (#1192)#1199
Fix useAutomationChat missing onUnmounted cleanup (#1192)#1199Chris0Jeky wants to merge 1 commit into
Conversation
Add scope disposal guards to prevent watcher and async write leaks after component teardown. Follows the existing isDisposed + onScopeDispose pattern from useGlobalSearch. - Store watch stop handle and call it in onScopeDispose - Add isDisposed flag to guard all async continuations after await - Add tests verifying reactive state is not written after disposal
There was a problem hiding this comment.
Code Review
This pull request introduces scope disposal handling in the useAutomationChat composable by utilizing onScopeDispose and an isDisposed flag to guard asynchronous operations from writing to reactive state after the scope is destroyed. It also adds corresponding unit tests to verify this behavior. The review feedback correctly identifies an unguarded async continuation in onMounted that calls applyRouteBoardContext(), which could still write to reactive state after disposal and should be guarded.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| onScopeDispose(() => { | ||
| isDisposed = true | ||
| stopWatch() | ||
| }) |
There was a problem hiding this comment.
While isDisposed is set to true here, there is still an unguarded async continuation in onMounted (line 357):
void loadBoardOptions().then(() => {
applyRouteBoardContext()
})If loadBoardOptions() resolves after the scope is disposed, the .then() callback will still execute and call applyRouteBoardContext(). This function writes to the reactive refs newSessionBoardId and selectedNewSessionBoardId without checking isDisposed.
To fix this, you can add an isDisposed check at the beginning of applyRouteBoardContext() or guard the .then() callback in onMounted.
Summary
const stopWatch = watch(...)) and call it during disposalisDisposedflag (plainlet, matchinguseGlobalSearchpattern) to guard all async continuations after everyawaitinloadSessions,loadSession,loadProviderHealth,handleCreateSession,sendMessageToSession, andloadBoardOptionsonScopeDisposecallback that setsisDisposed = trueand callsstopWatch()Closes #1192
Test plan
npm run typecheckpassesuseAutomationChat.spec.tstests pass (17 existing + 3 new disposal tests)