fix(reactivity): release nested effects/scopes on effect scope stop (#12373)

close #12370
This commit is contained in:
edison 2024-11-14 14:24:22 +08:00 committed by GitHub
parent 21932840ea
commit bee2f5ee62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 14 additions and 5 deletions

View 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)
})
})

View 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

View 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 ', () => {