fix(reactivity): fix nested batch edge case

This commit is contained in:
Evan You 2024-09-27 23:10:11 +08:00
parent aa9ef2386a
commit 93c95dd4cd
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
2 changed files with 33 additions and 2 deletions

View File

@ -229,4 +229,35 @@ describe('watch', () => {
expect(r.value).toBe(1)
expect(c.value).toBe(1)
})
// edge case where a nested endBatch() causes an effect to be batched in a
// nested batch loop with its .next mutated, causing the outer loop to end
// early
test('nested batch edge case', () => {
// useClamp from VueUse
const clamp = (n: number, min: number, max: number) =>
Math.min(max, Math.max(min, n))
function useClamp(src: Ref<number>, min: number, max: number) {
return computed({
get() {
return (src.value = clamp(src.value, min, max))
},
set(val) {
src.value = clamp(val, min, max)
},
})
}
const src = ref(1)
const clamped = useClamp(src, 1, 5)
watch(src, val => (clamped.value = val))
const spy = vi.fn()
watch(clamped, spy)
src.value = 2
expect(spy).toHaveBeenCalledTimes(1)
src.value = 10
expect(spy).toHaveBeenCalledTimes(2)
})
})

View File

@ -274,6 +274,8 @@ export function endBatch(): void {
batchedSub = undefined
// 2nd pass: run effects
while (e) {
next = e.next
e.next = undefined
e.flags &= ~EffectFlags.NOTIFIED
if (e.flags & EffectFlags.ACTIVE) {
try {
@ -283,8 +285,6 @@ export function endBatch(): void {
if (!error) error = err
}
}
next = e.next
e.next = undefined
e = next
}
}