From a62da807c300a1e09443689ead7f8c01386bef30 Mon Sep 17 00:00:00 2001 From: daiwei Date: Mon, 13 Feb 2023 17:45:37 +0800 Subject: [PATCH] chore: rebase --- packages/reactivity/src/effectScope.ts | 8 ++++-- .../runtime-core/__tests__/apiWatch.spec.ts | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/reactivity/src/effectScope.ts b/packages/reactivity/src/effectScope.ts index c644d03fae6..3ded91da878 100644 --- a/packages/reactivity/src/effectScope.ts +++ b/packages/reactivity/src/effectScope.ts @@ -81,8 +81,12 @@ export class EffectScope { stop(fromParent?: boolean) { if (this._active) { let i, l - for (i = 0, l = this.effects.length; i < l; i++) { - this.effects[i].stop() + // #5783 + // effects will be changed when a watcher stoped. + // so we need to copy it for iteration. + const effectsToStop = this.effects.slice() + for (i = 0, l = effectsToStop.length; i < l; i++) { + effectsToStop[i].stop() } for (i = 0, l = this.cleanups.length; i < l; i++) { this.cleanups[i]() diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 1b9f500da3c..c0dc1f4d300 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -1126,6 +1126,33 @@ describe('api: watch', () => { expect(spy).toHaveBeenCalledTimes(2) }) + test('handle nested watcher stop properly', () => { + let instance: ComponentInternalInstance + const Comp = { + setup() { + instance = getCurrentInstance()! + watch( + () => 1, + (val, oldVal, onCleanup) => { + const stop = watch( + () => 2, + () => {} + ) + onCleanup(stop) + }, + { immediate: true } + ) + return () => '' + } + } + const root = nodeOps.createElement('div') + createApp(Comp).mount(root) + expect(instance!.scope.effects.length).toBe(3) + + instance!.scope.stop() + expect(instance!.scope.effects[0].active).toBe(false) + }) + it('watching sources: ref', async () => { const foo = ref([1]) const spy = vi.fn()