fix(reactivity): dereference nested effect scopes on manual stop

This commit is contained in:
Evan You 2021-07-28 12:08:01 -04:00
parent da6c055b19
commit 1867591e7c
2 changed files with 16 additions and 2 deletions

View File

@ -191,6 +191,14 @@ describe('reactivity/effect/scope', () => {
expect(dummy).toBe(7) 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 () => { it('test with higher level APIs', async () => {
const r = ref(1) const r = ref(1)

View File

@ -1,3 +1,4 @@
import { remove } from '@vue/shared'
import { ReactiveEffect } from './effect' import { ReactiveEffect } from './effect'
import { warn } from './warning' import { warn } from './warning'
@ -8,10 +9,12 @@ export class EffectScope {
active = true active = true
effects: (ReactiveEffect | EffectScope)[] = [] effects: (ReactiveEffect | EffectScope)[] = []
cleanups: (() => void)[] = [] cleanups: (() => void)[] = []
parent: EffectScope | undefined
constructor(detached = false) { constructor(detached = false) {
if (!detached) { if (!detached) {
recordEffectScope(this) recordEffectScope(this)
this.parent = activeEffectScope
} }
} }
@ -42,11 +45,14 @@ export class EffectScope {
} }
} }
stop() { stop(fromParent = false) {
if (this.active) { if (this.active) {
this.effects.forEach(e => e.stop()) this.effects.forEach(e => e.stop(true))
this.cleanups.forEach(cleanup => cleanup()) this.cleanups.forEach(cleanup => cleanup())
this.active = false this.active = false
if (!fromParent && this.parent) {
remove(this.parent.effects, this)
}
} }
} }
} }