Skip to content

Commit a62da80

Browse files
committed
chore: rebase
1 parent a0e7dc3 commit a62da80

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

packages/reactivity/src/effectScope.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,12 @@ export class EffectScope {
8181
stop(fromParent?: boolean) {
8282
if (this._active) {
8383
let i, l
84-
for (i = 0, l = this.effects.length; i < l; i++) {
85-
this.effects[i].stop()
84+
// #5783
85+
// effects will be changed when a watcher stoped.
86+
// so we need to copy it for iteration.
87+
const effectsToStop = this.effects.slice()
88+
for (i = 0, l = effectsToStop.length; i < l; i++) {
89+
effectsToStop[i].stop()
8690
}
8791
for (i = 0, l = this.cleanups.length; i < l; i++) {
8892
this.cleanups[i]()

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,33 @@ describe('api: watch', () => {
11261126
expect(spy).toHaveBeenCalledTimes(2)
11271127
})
11281128

1129+
test('handle nested watcher stop properly', () => {
1130+
let instance: ComponentInternalInstance
1131+
const Comp = {
1132+
setup() {
1133+
instance = getCurrentInstance()!
1134+
watch(
1135+
() => 1,
1136+
(val, oldVal, onCleanup) => {
1137+
const stop = watch(
1138+
() => 2,
1139+
() => {}
1140+
)
1141+
onCleanup(stop)
1142+
},
1143+
{ immediate: true }
1144+
)
1145+
return () => ''
1146+
}
1147+
}
1148+
const root = nodeOps.createElement('div')
1149+
createApp(Comp).mount(root)
1150+
expect(instance!.scope.effects.length).toBe(3)
1151+
1152+
instance!.scope.stop()
1153+
expect(instance!.scope.effects[0].active).toBe(false)
1154+
})
1155+
11291156
it('watching sources: ref<any[]>', async () => {
11301157
const foo = ref([1])
11311158
const spy = vi.fn()

0 commit comments

Comments
 (0)