From b75979f616709f74e314851a30840039fe92d521 Mon Sep 17 00:00:00 2001 From: daiwei Date: Fri, 21 Feb 2025 10:36:13 +0800 Subject: [PATCH] fix(apiWatch): don't invoke watch callback during resuming --- packages/reactivity/src/effect.ts | 2 ++ packages/reactivity/src/watch.ts | 8 ++++++++ packages/runtime-core/__tests__/apiWatch.spec.ts | 14 ++++++++------ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 886f380dd52..f2e28144f6c 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -49,6 +49,7 @@ export enum EffectFlags { DIRTY = 1 << 4, ALLOW_RECURSE = 1 << 5, PAUSED = 1 << 6, + RESUMING = 1 << 7, } /** @@ -127,6 +128,7 @@ export class ReactiveEffect this.flags &= ~EffectFlags.PAUSED if (pausedQueueEffects.has(this)) { pausedQueueEffects.delete(this) + this.flags |= EffectFlags.RESUMING this.trigger() } } diff --git a/packages/reactivity/src/watch.ts b/packages/reactivity/src/watch.ts index 659121ca34b..f682600e025 100644 --- a/packages/reactivity/src/watch.ts +++ b/packages/reactivity/src/watch.ts @@ -240,6 +240,14 @@ export function watch( if (cb) { // watch(source, cb) const newValue = effect.run() + + // don't invoke cb during effect resuming + if (effect.flags & EffectFlags.RESUMING) { + oldValue = newValue + effect.flags &= ~EffectFlags.RESUMING + return + } + if ( deep || forceTrigger || diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 39032a63699..5c2d1393b5d 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -1708,24 +1708,26 @@ describe('api: watch', () => { resume() count.value++ await nextTick() - expect(cb).toHaveBeenCalledTimes(2) - expect(cb).toHaveBeenLastCalledWith(3, 1, expect.any(Function)) + // don't invoke callback during resuming + expect(cb).toHaveBeenCalledTimes(1) + expect(cb).toHaveBeenLastCalledWith(1, 0, expect.any(Function)) count.value++ await nextTick() - expect(cb).toHaveBeenCalledTimes(3) + expect(cb).toHaveBeenCalledTimes(2) expect(cb).toHaveBeenLastCalledWith(4, 3, expect.any(Function)) pause() count.value++ await nextTick() - expect(cb).toHaveBeenCalledTimes(3) + expect(cb).toHaveBeenCalledTimes(2) expect(cb).toHaveBeenLastCalledWith(4, 3, expect.any(Function)) resume() await nextTick() - expect(cb).toHaveBeenCalledTimes(4) - expect(cb).toHaveBeenLastCalledWith(5, 4, expect.any(Function)) + // don't invoke callback during resuming + expect(cb).toHaveBeenCalledTimes(2) + expect(cb).toHaveBeenLastCalledWith(4, 3, expect.any(Function)) }) it('shallowReactive', async () => {