Skip to content

fix(reactivity): unlink effect scopes on out-of-order off#14734

Merged
edison1105 merged 1 commit into
mainfrom
edison/fix/ssrOnScopeDispose
Apr 22, 2026
Merged

fix(reactivity): unlink effect scopes on out-of-order off#14734
edison1105 merged 1 commit into
mainfrom
edison/fix/ssrOnScopeDispose

Conversation

@edison1105

@edison1105 edison1105 commented Apr 17, 2026

Copy link
Copy Markdown
Member

close #14733

Summary by CodeRabbit

  • Bug Fixes

    • More robust handling of out-of-order effect scope deactivation to prevent scope-link corruption.
  • Tests

    • Added unit tests covering effect-scope deactivation edge cases.
    • Added/expanded server-side rendering tests around watcher teardown and GC behavior.
    • Separated GC-dependent tests into a dedicated test project/configuration so they run with GC exposed.

@github-actions

Copy link
Copy Markdown

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 106 kB (+107 B) 39.9 kB (+27 B) 35.8 kB (+23 B)
vue.global.prod.js 164 kB (+107 B) 59.9 kB (+31 B) 53.3 kB (+38 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.4 kB (+107 B) 18.8 kB (+32 B) 17.3 kB (+29 B)
createApp 56.6 kB (+107 B) 21.9 kB (+29 B) 20 kB (+24 B)
createSSRApp 60.8 kB (+107 B) 23.6 kB (+28 B) 21.5 kB (+29 B)
defineCustomElement 62.8 kB (+107 B) 23.8 kB (+31 B) 21.7 kB (+35 B)
overall 71.1 kB (+107 B) 27.2 kB (+28 B) 24.8 kB (+22 B)

@pkg-pr-new

pkg-pr-new Bot commented Apr 17, 2026

Copy link
Copy Markdown

Open in StackBlitz

@vue/compiler-core

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

@vue/compiler-dom

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

@vue/compiler-sfc

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

@vue/compiler-ssr

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

@vue/reactivity

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

@vue/runtime-core

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

@vue/runtime-dom

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

@vue/server-renderer

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

@vue/shared

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

vue

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

@vue/compat

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

commit: 93c1802

@coderabbitai

coderabbitai Bot commented Apr 17, 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: 58b92169-acef-476f-ac4b-ac9191122081

📥 Commits

Reviewing files that changed from the base of the PR and between a843c23 and 93c1802.

📒 Files selected for processing (4)
  • packages/reactivity/__tests__/effectScope.spec.ts
  • packages/reactivity/src/effectScope.ts
  • packages/server-renderer/__tests__/ssrWatch.spec.ts
  • vitest.config.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/reactivity/tests/effectScope.spec.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • vitest.config.ts
  • packages/reactivity/src/effectScope.ts
  • packages/server-renderer/tests/ssrWatch.spec.ts

📝 Walkthrough

Walkthrough

Updated EffectScope.off() to safely unlink a scope when deactivated out-of-order, added tests for out-of-sequence scope disposal, and introduced a GC-only Vitest project plus SSR GC tests to validate server-side memory reclamation.

Changes

Cohort / File(s) Summary
Effect Scope Core Logic
packages/reactivity/src/effectScope.ts
Changed EffectScope.off() to check activeEffectScope and, if deactivating a non-top scope, traverse and rewire the prevScope chain to unlink the scope instead of blindly restoring the previous scope.
Effect Scope Tests
packages/reactivity/__tests__/effectScope.spec.ts
Added a test exercising .off() called out-of-order across chained EffectScope instances to verify correct active-scope restoration.
SSR GC Tests
packages/server-renderer/__tests__/ssrWatch.spec.ts
Added a skipped GC-focused test suite (uses WeakRef) that renders many SSR apps and asserts they are collectable after repeated GCs; imports onScopeDispose and introduces a gc() helper.
Vitest GC Project Config
vitest.config.ts
Added a unit-gc Vitest project that runs only the GC-focused test file with --expose-gc and isolates it from the main unit project.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

ready to merge, scope: reactivity, scope: ssr, :hammer: p3-minor-bug

Suggested reviewers

  • jh-leong

Poem

🐰 I hopped through scopes, rewired each link,
Unwound tangled chains before they could sink,
Tests tap the bell, GC breathes a sigh,
Apps drift away as the rabbits hop by,
A tidy heap—now that's quite a wink!

🚥 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 clearly summarizes the main code change: fixing an issue where effect scopes turned off out-of-order remain incorrectly linked in the active scope chain.
Linked Issues check ✅ Passed The pull request implements a fix to unlink out-of-order deactivated effect scopes from the active chain, directly addressing the core issue of preventing SSR memory leaks caused by stale scopes remaining reachable via onScopeDispose.
Out of Scope Changes check ✅ Passed All changes are directly aligned with fixing the out-of-order effect scope unlinking issue: the core fix in effectScope.ts, test coverage for the fix and GC verification, and necessary test configuration updates.

✏️ 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/ssrOnScopeDispose

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

@edison1105 edison1105 force-pushed the edison/fix/ssrOnScopeDispose branch from a843c23 to 93c1802 Compare April 17, 2026 13:00
@edison1105

Copy link
Copy Markdown
Member Author

/ecosystem-ci run

@vue-bot

vue-bot commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

📝 Ran ecosystem CI: Open

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

@edison1105 edison1105 added the ❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf. label Apr 20, 2026
@edison1105 edison1105 merged commit e7659be into main Apr 22, 2026
15 of 16 checks passed
@edison1105 edison1105 deleted the edison/fix/ssrOnScopeDispose branch April 22, 2026 06:02
peter-fusek added a commit to peter-fusek/oncoteam that referenced this pull request Apr 26, 2026
Pins @vue/* family to 3.5.33 via pnpm.overrides. Vue 3.5.33 (released
2026-04-22) lands the fix for vuejs/core#14733 (PR #14734) — onScopeDispose
SSR memory leak where effect scopes survive request teardown when scope
.off() is called out of order. Repro: 1000 fresh SSR apps shows 0 finalized
on 3.5.32, all alive forever.

Hypothesis fit (per six-agent week-of-Apr-20-26 audit):
- Symptom: clicking Google login on /demo triggers ~80 MB retain per OAuth
  flow, OOM at 8 GB heap in 10-13 min, restart, repeat
- Phase 0 confirmed (2026-04-27): idle anonymous traffic stays flat, leak is
  OAuth-trigger-specific
- All six in-app code amplifiers (#1 AbortSignal.timeout, #2 i18n.lazy:false,
  #3 undici body retain, #4 Twilio per-call client, #5 rateLimitMap, #6
  session-patch /auth/) already shipped on main HEAD — leak persisted
- Frontend audit found NO top-level await in pages/index.vue +
  layouts/default.vue (clean component code)
- Vue 3.5.32 → 3.5.33 is the only upstream version drift in the window that
  matches the symptom; pin held us back at 3.5.32

If memory chart stays flat after one OAuth round-trip + 30-min user soak,
this resolves #447. If it doesn't, fall back to Phase 2 heap snapshot diff.

Sources:
- vuejs/core#14733
- vuejs/core#14734
- nuxt/nuxt#34071
- nuxt/nuxt#33080
- nuxt/nuxt#34324

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

onScopeDispose can cause a SSR memory leak

2 participants