From 10ff15924053d9bd95ad706f78ce09e288213fcf Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 26 Sep 2024 18:38:02 +0800 Subject: [PATCH] fix(reactivity): fix recursive sync watcher on computed edge case close #12033 close #12037 --- packages/reactivity/__tests__/watch.spec.ts | 20 ++++++++++++++++++++ packages/reactivity/src/effect.ts | 11 ++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/reactivity/__tests__/watch.spec.ts b/packages/reactivity/__tests__/watch.spec.ts index b3d18e19f71..f333d7c06e0 100644 --- a/packages/reactivity/__tests__/watch.spec.ts +++ b/packages/reactivity/__tests__/watch.spec.ts @@ -4,6 +4,7 @@ import { WatchErrorCodes, type WatchOptions, type WatchScheduler, + computed, onWatcherCleanup, ref, watch, @@ -209,4 +210,23 @@ describe('watch', () => { source.value++ expect(dummy).toBe(1) }) + + // #12033 + test('recursive sync watcher on computed', () => { + const r = ref(0) + const c = computed(() => r.value) + + watch(c, v => { + if (v > 1) { + r.value-- + } + }) + + expect(r.value).toBe(0) + expect(c.value).toBe(0) + + r.value = 10 + expect(r.value).toBe(1) + expect(c.value).toBe(1) + }) }) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index b681df85cdb..15693ee39b4 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -260,11 +260,14 @@ export function endBatch(): void { let error: unknown while (batchedSub) { let e: Subscriber | undefined = batchedSub - batchedSub = undefined + let next: Subscriber | undefined while (e) { - const next: Subscriber | undefined = e.next - e.next = undefined e.flags &= ~EffectFlags.NOTIFIED + e = e.next + } + e = batchedSub + batchedSub = undefined + while (e) { if (e.flags & EffectFlags.ACTIVE) { try { // ACTIVE flag is effect-only @@ -273,6 +276,8 @@ export function endBatch(): void { if (!error) error = err } } + next = e.next + e.next = undefined e = next } }