fix(runtime-core): skip async component callbacks after unmount#14911
fix(runtime-core): skip async component callbacks after unmount#14911baozjj wants to merge 2 commits into
Conversation
Clear delay/timeout timers on unmount and guard load/timeout handlers with isUnmounted to avoid spurious errorHandler invocations. Co-authored-by: Cursor <cursoragent@cursor.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughdefineAsyncComponent now clears delay/timeout timers on unmount and returns early from loader resolution/rejection if the instance is unmounted; tests added to ensure app.config.errorHandler is not called when async components unmount before timeout or loader rejection, and to verify remount behavior. ChangesAsync component unmount lifecycle guards
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
@vue/compiler-core
@vue/compiler-dom
@vue/compiler-sfc
@vue/compiler-ssr
@vue/reactivity
@vue/runtime-core
@vue/runtime-dom
@vue/server-renderer
@vue/shared
vue
@vue/compat
commit: |
Size ReportBundles
Usages
|
What is the motivation / use case?
Example: A route lazy-loads a heavy chart with
defineAsyncComponent({ timeout: 10000 }). The user opens the page, sees the loading state, then navigates away after 2 seconds. About 8 seconds later, the app is already on another page, but the console / globalerrorHandler(e.g. Sentry) still reportsAsync component timed out after 10000ms.— even though that async component has already been unmounted.In the non-Suspense setup path,
delay/timeouttimers andload().then()/load().catch()do not checkinstance.isUnmounted, and timers are not cleared on unmount. That can triggeronError()→handleError()after teardown. The__asyncHydratepath already uses!instance.isUnmounted; this change aligns the setup path with that behavior.What is the solution?
onUnmountedtoclearTimeoutfordelayandtimeouttimersload()resolve/reject handlers, return early wheninstance.isUnmountedWhat is the scope of this change?
packages/runtime-core/src/apiAsyncComponent.tsand regression tests inapiAsyncComponent.spec.tsonly.Test plan
pnpm test packages/runtime-core/__tests__/apiAsyncComponent.spec.ts --run(24 passed)should not call errorHandler after unmount (timeout)— unmount before timeout firesshould not call errorHandler after unmount (loader error)— unmount before rejected loader is handledSummary by CodeRabbit
Bug Fixes
Tests