fix(reactivity): fix recursive sync watcher on computed edge case

close #12033
close #12037
This commit is contained in:
Evan You 2024-09-26 18:38:02 +08:00
parent cb34b28a4a
commit 10ff159240
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
2 changed files with 28 additions and 3 deletions

View File

@ -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)
})
})

View File

@ -260,11 +260,14 @@ export function endBatch(): void {
let error: unknown
while (batchedSub) {
let e: Subscriber | undefined = batchedSub
let next: Subscriber | undefined
while (e) {
e.flags &= ~EffectFlags.NOTIFIED
e = e.next
}
e = batchedSub
batchedSub = undefined
while (e) {
const next: Subscriber | undefined = e.next
e.next = undefined
e.flags &= ~EffectFlags.NOTIFIED
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
}
}