Skip to content

Commit bee2f5e

Browse files
authoredNov 14, 2024··
fix(reactivity): release nested effects/scopes on effect scope stop (#12373)
close #12370
1 parent 2193284 commit bee2f5e

File tree

3 files changed

+14
-5
lines changed

3 files changed

+14
-5
lines changed
 

‎packages/reactivity/__tests__/effectScope.spec.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ describe('reactivity/effect/scope', () => {
176176

177177
expect('[Vue warn] cannot run an inactive effect scope.').toHaveBeenWarned()
178178

179-
expect(scope.effects.length).toBe(1)
179+
expect(scope.effects.length).toBe(0)
180180

181181
counter.num = 7
182182
expect(dummy).toBe(0)
@@ -358,5 +358,8 @@ describe('reactivity/effect/scope', () => {
358358
await nextTick()
359359
expect(watcherCalls).toBe(3)
360360
expect(cleanupCalls).toBe(1)
361+
362+
expect(scope.effects.length).toBe(0)
363+
expect(scope.cleanups.length).toBe(0)
361364
})
362365
})

‎packages/reactivity/src/effectScope.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,24 @@ export class EffectScope {
119119
if (this._active) {
120120
this._active = false
121121
let i, l
122-
for (i = 0, l = this.effects.length; i < l; i++) {
123-
this.effects[i].stop()
122+
const effects = this.effects.slice()
123+
for (i = 0, l = effects.length; i < l; i++) {
124+
effects[i].stop()
124125
}
126+
this.effects.length = 0
127+
125128
for (i = 0, l = this.cleanups.length; i < l; i++) {
126129
this.cleanups[i]()
127130
}
131+
this.cleanups.length = 0
132+
128133
if (this.scopes) {
129134
for (i = 0, l = this.scopes.length; i < l; i++) {
130135
this.scopes[i].stop(true)
131136
}
137+
this.scopes.length = 0
132138
}
139+
133140
// nested scope, dereference from parent to avoid memory leaks
134141
if (!this.detached && this.parent && !fromParent) {
135142
// optimized O(1) removal

‎packages/runtime-core/__tests__/apiWatch.spec.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import {
2525
} from '@vue/runtime-test'
2626
import {
2727
type DebuggerEvent,
28-
EffectFlags,
2928
ITERATE_KEY,
3029
type Ref,
3130
type ShallowRef,
@@ -1341,7 +1340,7 @@ describe('api: watch', () => {
13411340
await nextTick()
13421341
await nextTick()
13431342

1344-
expect(instance!.scope.effects[0].flags & EffectFlags.ACTIVE).toBeFalsy()
1343+
expect(instance!.scope.effects.length).toBe(0)
13451344
})
13461345

13471346
test('this.$watch should pass `this.proxy` to watch source as the first argument ', () => {

0 commit comments

Comments
 (0)
Please sign in to comment.