]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): dereference nested effect scopes on manual stop
authorEvan You <yyx990803@gmail.com>
Wed, 28 Jul 2021 16:08:01 +0000 (12:08 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 28 Jul 2021 16:08:01 +0000 (12:08 -0400)
packages/reactivity/__tests__/effectScope.spec.ts
packages/reactivity/src/effectScope.ts

index b5bc970e22447304dc129d3b4ccc516b948a0696..55073470b81f7a5ea70366e79fd8f7534cda5d63 100644 (file)
@@ -191,6 +191,14 @@ describe('reactivity/effect/scope', () => {
     expect(dummy).toBe(7)
   })
 
+  it('should derefence child scope from parent scope after stopping child scope (no memleaks)', async () => {
+    const parent = new EffectScope()
+    const child = parent.run(() => new EffectScope())!
+    expect(parent.effects.includes(child)).toBe(true)
+    child.stop()
+    expect(parent.effects.includes(child)).toBe(false)
+  })
+
   it('test with higher level APIs', async () => {
     const r = ref(1)
 
index fdacffc541dbb88c6d090e9ab95146ea51cd03c5..0526f90d9d3302effb0d58e1b84de150892151c1 100644 (file)
@@ -1,3 +1,4 @@
+import { remove } from '@vue/shared'
 import { ReactiveEffect } from './effect'
 import { warn } from './warning'
 
@@ -8,10 +9,12 @@ export class EffectScope {
   active = true
   effects: (ReactiveEffect | EffectScope)[] = []
   cleanups: (() => void)[] = []
+  parent: EffectScope | undefined
 
   constructor(detached = false) {
     if (!detached) {
       recordEffectScope(this)
+      this.parent = activeEffectScope
     }
   }
 
@@ -42,11 +45,14 @@ export class EffectScope {
     }
   }
 
-  stop() {
+  stop(fromParent = false) {
     if (this.active) {
-      this.effects.forEach(e => e.stop())
+      this.effects.forEach(e => e.stop(true))
       this.cleanups.forEach(cleanup => cleanup())
       this.active = false
+      if (!fromParent && this.parent) {
+        remove(this.parent.effects, this)
+      }
     }
   }
 }