]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): release nested effects/scopes on effect scope stop (#12373)
authoredison <daiwei521@126.com>
Thu, 14 Nov 2024 06:24:22 +0000 (14:24 +0800)
committerGitHub <noreply@github.com>
Thu, 14 Nov 2024 06:24:22 +0000 (14:24 +0800)
close #12370

packages/reactivity/__tests__/effectScope.spec.ts
packages/reactivity/src/effectScope.ts
packages/runtime-core/__tests__/apiWatch.spec.ts

index 537cac64c6b94b070b4c3aa805ee5d7e0fb8d10f..debbdafb1e70bbef3529729f5061fb211490ccf0 100644 (file)
@@ -176,7 +176,7 @@ describe('reactivity/effect/scope', () => {
 
     expect('[Vue warn] cannot run an inactive effect scope.').toHaveBeenWarned()
 
-    expect(scope.effects.length).toBe(1)
+    expect(scope.effects.length).toBe(0)
 
     counter.num = 7
     expect(dummy).toBe(0)
@@ -358,5 +358,8 @@ describe('reactivity/effect/scope', () => {
     await nextTick()
     expect(watcherCalls).toBe(3)
     expect(cleanupCalls).toBe(1)
+
+    expect(scope.effects.length).toBe(0)
+    expect(scope.cleanups.length).toBe(0)
   })
 })
index 98e45fb5707e4a733049c6f2f59487903abb950d..e045d30e89b08cccdaae7b0bcaa3c6318389689e 100644 (file)
@@ -119,17 +119,24 @@ export class EffectScope {
     if (this._active) {
       this._active = false
       let i, l
-      for (i = 0, l = this.effects.length; i < l; i++) {
-        this.effects[i].stop()
+      const effects = this.effects.slice()
+      for (i = 0, l = effects.length; i < l; i++) {
+        effects[i].stop()
       }
+      this.effects.length = 0
+
       for (i = 0, l = this.cleanups.length; i < l; i++) {
         this.cleanups[i]()
       }
+      this.cleanups.length = 0
+
       if (this.scopes) {
         for (i = 0, l = this.scopes.length; i < l; i++) {
           this.scopes[i].stop(true)
         }
+        this.scopes.length = 0
       }
+
       // nested scope, dereference from parent to avoid memory leaks
       if (!this.detached && this.parent && !fromParent) {
         // optimized O(1) removal
index 10a4fe659e09e39f84b2c73ec582eb0ef92840bf..7d2a1e73c0830e3c3bc63aedc0bc44654d92b081 100644 (file)
@@ -25,7 +25,6 @@ import {
 } from '@vue/runtime-test'
 import {
   type DebuggerEvent,
-  EffectFlags,
   ITERATE_KEY,
   type Ref,
   type ShallowRef,
@@ -1341,7 +1340,7 @@ describe('api: watch', () => {
     await nextTick()
     await nextTick()
 
-    expect(instance!.scope.effects[0].flags & EffectFlags.ACTIVE).toBeFalsy()
+    expect(instance!.scope.effects.length).toBe(0)
   })
 
   test('this.$watch should pass `this.proxy` to watch source as the first argument ', () => {