Skip to content

fix(suspense): avoid DOM leak with out-in transition in v-if fragment#14762

Merged
edison1105 merged 1 commit into
mainfrom
edison/fix/14761
May 6, 2026
Merged

fix(suspense): avoid DOM leak with out-in transition in v-if fragment#14762
edison1105 merged 1 commit into
mainfrom
edison/fix/14761

Conversation

@edison1105

@edison1105 edison1105 commented Apr 27, 2026

Copy link
Copy Markdown
Member

close #14761

Summary by CodeRabbit

  • Bug Fixes

    • Fixed Suspense transitions in out-in mode to properly manage DOM anchor positioning when switching between component branches, ensuring correct element placement and preventing unnecessary recalculations.
  • Tests

    • Added regression test validating that Transition with nested Suspense components correctly handles memory cleanup and DOM updates during branch switching.

@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aa58a3f6-b71d-4c88-af19-86082aa96261

📥 Commits

Reviewing files that changed from the base of the PR and between 3310eea and eb6489a.

📒 Files selected for processing (2)
  • packages/runtime-core/src/components/Suspense.ts
  • packages/vue/__tests__/e2e/memory-leak.spec.ts

📝 Walkthrough

Walkthrough

This PR fixes a DOM leak occurring when toggling between <template v-if> branches containing nested <Transition mode="out-in"> and <Suspense> components. The fix prevents unnecessary anchor recalculation during out-in transitions by tracking whether the anchor was already updated during unmount, and includes a regression test.

Changes

Cohort / File(s) Summary
Suspense anchor timing fix
packages/runtime-core/src/components/Suspense.ts
Adds hasUpdatedAnchor flag to prevent recalculating the DOM anchor in afterLeave callbacks during out-in transitions if the anchor was already updated during unmount.
Memory leak regression test
packages/vue/__tests__/e2e/memory-leak.spec.ts
New e2e test covering Transition (out-in) + Suspense + async setup inside <template v-if> branches; verifies DOM is properly removed on branch toggles and no stale elements leak.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

ready to merge, scope: suspense, scope: transition, :hammer: p3-minor-bug

Poem

🐰 A leak through the branches, we spotted it clear,
When Suspense met Transition, the DOM stayed right here!
An anchor, a flag, a timely update,
Now toggles work flawlessly—no longer so late! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 fix: preventing DOM leaks with out-in transitions in v-if fragments, directly addressing the linked issue #14761.
Linked Issues check ✅ Passed The PR fixes the core issue by gating anchor updates during Suspense unmount to prevent premature afterLeave callback execution, and validates the fix with a regression test covering the exact scenario: Transition (out-in) with nested Suspense in v-if.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the DOM leak issue: core Suspense logic handles anchor refresh tracking, and the regression test covers the exact problematic pattern with no extraneous modifications.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch edison/fix/14761

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

@github-actions

Copy link
Copy Markdown

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 106 kB (+26 B) 40 kB (+10 B) 36 kB (+36 B)
vue.global.prod.js 164 kB (+26 B) 60 kB (+10 B) 53.4 kB (+46 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.6 kB 18.9 kB 17.3 kB
createApp 56.7 kB 21.9 kB 20.1 kB
createSSRApp 61 kB 23.7 kB 21.6 kB
defineCustomElement 62.9 kB 23.9 kB 21.8 kB
overall 71.5 kB (+26 B) 27.3 kB (+11 B) 24.9 kB (+8 B)

@pkg-pr-new

pkg-pr-new Bot commented Apr 27, 2026

Copy link
Copy Markdown

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@14762
npm i https://pkg.pr.new/@vue/compiler-core@14762
yarn add https://pkg.pr.new/@vue/compiler-core@14762.tgz

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@14762
npm i https://pkg.pr.new/@vue/compiler-dom@14762
yarn add https://pkg.pr.new/@vue/compiler-dom@14762.tgz

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@14762
npm i https://pkg.pr.new/@vue/compiler-sfc@14762
yarn add https://pkg.pr.new/@vue/compiler-sfc@14762.tgz

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@14762
npm i https://pkg.pr.new/@vue/compiler-ssr@14762
yarn add https://pkg.pr.new/@vue/compiler-ssr@14762.tgz

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@14762
npm i https://pkg.pr.new/@vue/reactivity@14762
yarn add https://pkg.pr.new/@vue/reactivity@14762.tgz

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@14762
npm i https://pkg.pr.new/@vue/runtime-core@14762
yarn add https://pkg.pr.new/@vue/runtime-core@14762.tgz

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@14762
npm i https://pkg.pr.new/@vue/runtime-dom@14762
yarn add https://pkg.pr.new/@vue/runtime-dom@14762.tgz

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@14762
npm i https://pkg.pr.new/@vue/server-renderer@14762
yarn add https://pkg.pr.new/@vue/server-renderer@14762.tgz

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@14762
npm i https://pkg.pr.new/@vue/shared@14762
yarn add https://pkg.pr.new/@vue/shared@14762.tgz

vue

pnpm add https://pkg.pr.new/vue@14762
npm i https://pkg.pr.new/vue@14762
yarn add https://pkg.pr.new/vue@14762.tgz

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@14762
npm i https://pkg.pr.new/@vue/compat@14762
yarn add https://pkg.pr.new/@vue/compat@14762.tgz

commit: eb6489a

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

Copy link
Copy Markdown
Member Author

/ecosystem-ci run

@vue-bot

vue-bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

📝 Ran ecosystem CI: Open

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

@edison1105 edison1105 merged commit 9667e0d into main May 6, 2026
20 of 21 checks passed
@edison1105 edison1105 deleted the edison/fix/14761 branch May 6, 2026 06:42
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. scope: suspense

Projects

None yet

Development

Successfully merging this pull request may close these issues.

<Transition mode="out-in"> + <Suspense> inside a <template v-if> fragment leaks DOM on toggle

2 participants