Skip to content

fix(runtime-core): prevent currentInstance leak into sibling render during async setup re-entry#14668

Merged
edison1105 merged 2 commits intovuejs:mainfrom
cernymatej:fix/concurrent-suspense-instance-leak
Apr 3, 2026
Merged

fix(runtime-core): prevent currentInstance leak into sibling render during async setup re-entry#14668
edison1105 merged 2 commits intovuejs:mainfrom
cernymatej:fix/concurrent-suspense-instance-leak

Conversation

@cernymatej
Copy link
Copy Markdown
Contributor

@cernymatej cernymatej commented Apr 1, 2026

fix #14667

Summary by CodeRabbit

  • Bug Fixes
    • Fixed instance context leakage in Suspense boundaries when rendering async sibling components, ensuring correct component identity during async setup and rendering.
  • Tests
    • Added tests to verify async setup/render context preservation and correct DOM ordering under Suspense.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 960c095b-b4ec-4f7e-b87e-14055ec06c41

📥 Commits

Reviewing files that changed from the base of the PR and between bd4bb93 and 2f33bdd.

📒 Files selected for processing (2)
  • packages/runtime-core/__tests__/apiSetupHelpers.spec.ts
  • packages/runtime-core/src/components/Suspense.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/runtime-core/src/components/Suspense.ts

📝 Walkthrough

Walkthrough

Clears a leaked component instance during Suspense async resolution by calling unsetCurrentInstance() before retrying a component render, and adds a test verifying no instance/context leakage across sibling async components in a Suspense boundary.

Changes

Cohort / File(s) Summary
Suspense async resolution cleanup
packages/runtime-core/src/components/Suspense.ts
Imported unsetCurrentInstance() and added a call in the async continuation path of registerDep before retrying the component render to avoid leaking the previous current instance.
Instance leakage regression test
packages/runtime-core/__tests__/apiSetupHelpers.spec.ts
Added withAsyncContext test that mounts two async components under a Suspense boundary and asserts getCurrentInstance() does not leak between setup and slot render, and no false slot-warning occurs.

Sequence Diagram(s)

sequenceDiagram
  participant AsyncA as AsyncA (slow)
  participant Suspense as SuspenseBoundary
  participant Runtime as Runtime (currentInstance)
  participant AsyncB as AsyncB (fast)

  AsyncA->>Suspense: registerDep (starts async setup)
  AsyncB->>Suspense: registerDep (starts async setup)
  AsyncB->>Runtime: setCurrentInstance(AsyncB) / withAsyncContext
  AsyncB-->>Suspense: resolves quickly
  Suspense->>Runtime: retry render for AsyncB
  Runtime-->>AsyncB: render (slots invoked) 

  AsyncA-->>Runtime: setCurrentInstance(AsyncA) / withAsyncContext (still resolving)
  AsyncA-->>Suspense: resolves later
  Suspense->>Runtime: before retry for AsyncA calls unsetCurrentInstance() rgba(255,0,0,0.5)
  Runtime->>AsyncA: retry render for AsyncA (no lingering instance)
  Suspense->>AsyncB: ensures no leaked instance into AsyncB slot render
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested labels

scope: suspense, :hammer: p3-minor-bug

Poem

🐰 I hopped between async blooms so bright,
Unsetting stray shadows in the night,
No more mixed-up instance song,
Each render hops where it belongs,
Hooray—order restored, what a delight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: preventing currentInstance leak during async setup re-entry in a Suspense boundary context.
Linked Issues check ✅ Passed The code changes directly address the reported issue by inserting unsetCurrentInstance() to prevent instance leakage when retrying async component setup after resolution, matching the root cause hypothesis.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the instance leak in Suspense.registerDep and include a focused test case; no unrelated modifications present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@edison1105 edison1105 force-pushed the fix/concurrent-suspense-instance-leak branch from bd4bb93 to 2f33bdd Compare April 3, 2026 01:05
@edison1105 edison1105 changed the title fix(runtime-core): prevent instance leak in registerDep fix(runtime-core): prevent currentInstance leak into sibling render during async setup re-entry Apr 3, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 105 kB (+5 B) 39.8 kB (+4 B) 35.8 kB (+10 B)
vue.global.prod.js 164 kB (+5 B) 59.8 kB (+4 B) 53.2 kB (-46 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.3 kB 18.8 kB 17.2 kB
createApp 56.5 kB 21.8 kB 19.9 kB
createSSRApp 60.7 kB 23.6 kB 21.5 kB
defineCustomElement 62.6 kB 23.8 kB 21.7 kB
overall 71 kB (+5 B) 27.2 kB (+3 B) 24.7 kB (+4 B)

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 3, 2026

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@14668
npm i https://pkg.pr.new/@vue/compiler-core@14668
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@14668
npm i https://pkg.pr.new/@vue/compiler-dom@14668
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@14668
npm i https://pkg.pr.new/@vue/compiler-sfc@14668
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@14668
npm i https://pkg.pr.new/@vue/compiler-ssr@14668
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@14668
npm i https://pkg.pr.new/@vue/reactivity@14668
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@14668
npm i https://pkg.pr.new/@vue/runtime-core@14668
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@14668
npm i https://pkg.pr.new/@vue/runtime-dom@14668
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@14668
npm i https://pkg.pr.new/@vue/server-renderer@14668
yarn add https://pkg.pr.new/@vue/[email protected]

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@14668
npm i https://pkg.pr.new/@vue/shared@14668
yarn add https://pkg.pr.new/@vue/[email protected]

vue

pnpm add https://pkg.pr.new/vue@14668
npm i https://pkg.pr.new/vue@14668
yarn add https://pkg.pr.new/[email protected]

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@14668
npm i https://pkg.pr.new/@vue/compat@14668
yarn add https://pkg.pr.new/@vue/[email protected]

commit: 2f33bdd

@edison1105 edison1105 added ready to merge The PR is ready to be merged. 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Apr 3, 2026
@edison1105
Copy link
Copy Markdown
Member

/ecosystem-ci run

@vue-bot
Copy link
Copy Markdown
Contributor

vue-bot commented Apr 3, 2026

📝 Ran ecosystem CI: Open

suite result latest scheduled
nuxt success success
radix-vue success success
primevue success success
pinia success success
quasar success success
vue-simple-compiler success success
vue-macros success success
vue-i18n success success
vitepress success success
vant success success
language-tools failure failure
test-utils success success
vuetify success success
vite-plugin-vue success success
vueuse success success
router success success

@edison1105 edison1105 merged commit f166353 into vuejs:main Apr 3, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. ready to merge The PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

False "Slot invoked outside of the render function" warning with multiple async components in Suspense

3 participants