src.value = 10
expect(spy).toHaveBeenCalledTimes(2)
})
+
+ test('should ensure correct execution order in batch processing', () => {
+ const dummy: number[] = []
+ const n1 = ref(0)
+ const n2 = ref(0)
+ const sum = computed(() => n1.value + n2.value)
+ watch(n1, () => {
+ dummy.push(1)
+ n2.value++
+ })
+ watch(sum, () => dummy.push(2))
+ watch(n1, () => dummy.push(3))
+
+ n1.value++
+
+ expect(dummy).toEqual([1, 2, 3])
+ })
})
let batchDepth = 0
let batchedSub: Subscriber | undefined
+let batchedComputed: Subscriber | undefined
-export function batch(sub: Subscriber): void {
+export function batch(sub: Subscriber, isComputed = false): void {
sub.flags |= EffectFlags.NOTIFIED
+ if (isComputed) {
+ sub.next = batchedComputed
+ batchedComputed = sub
+ return
+ }
sub.next = batchedSub
batchedSub = sub
}
return
}
+ if (batchedComputed) {
+ let e: Subscriber | undefined = batchedComputed
+ batchedComputed = undefined
+ while (e) {
+ const next: Subscriber | undefined = e.next
+ e.next = undefined
+ e.flags &= ~EffectFlags.NOTIFIED
+ e = next
+ }
+ }
+
let error: unknown
while (batchedSub) {
let e: Subscriber | undefined = batchedSub
- let next: Subscriber | undefined
- // 1st pass: clear notified flags for computed upfront
- // we use the ACTIVE flag as a discriminator between computed and effect,
- // since NOTIFIED is useless for an inactive effect anyway.
- while (e) {
- if (!(e.flags & EffectFlags.ACTIVE)) {
- e.flags &= ~EffectFlags.NOTIFIED
- }
- e = e.next
- }
- e = batchedSub
batchedSub = undefined
- // 2nd pass: run effects
while (e) {
- next = e.next
+ const next: Subscriber | undefined = e.next
e.next = undefined
e.flags &= ~EffectFlags.NOTIFIED
if (e.flags & EffectFlags.ACTIVE) {