mirror of https://github.com/vuejs/core.git
fix(reactivity): only clear notified flags for computed in first batch iteration
close #12045
This commit is contained in:
parent
60c2029f77
commit
aa9ef2386a
|
@ -84,9 +84,13 @@ export class ComputedRefImpl<T = any> implements Subscriber {
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
isSSR: boolean
|
isSSR: boolean
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
next?: Subscriber = undefined
|
||||||
|
|
||||||
// for backwards compat
|
// for backwards compat
|
||||||
effect: this = this
|
effect: this = this
|
||||||
|
|
||||||
// dev only
|
// dev only
|
||||||
onTrack?: (event: DebuggerEvent) => void
|
onTrack?: (event: DebuggerEvent) => void
|
||||||
// dev only
|
// dev only
|
||||||
|
|
|
@ -261,13 +261,20 @@ export function endBatch(): void {
|
||||||
while (batchedSub) {
|
while (batchedSub) {
|
||||||
let e: Subscriber | undefined = batchedSub
|
let e: Subscriber | undefined = batchedSub
|
||||||
let next: Subscriber | undefined
|
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) {
|
while (e) {
|
||||||
e.flags &= ~EffectFlags.NOTIFIED
|
if (!(e.flags & EffectFlags.ACTIVE)) {
|
||||||
|
e.flags &= ~EffectFlags.NOTIFIED
|
||||||
|
}
|
||||||
e = e.next
|
e = e.next
|
||||||
}
|
}
|
||||||
e = batchedSub
|
e = batchedSub
|
||||||
batchedSub = undefined
|
batchedSub = undefined
|
||||||
|
// 2nd pass: run effects
|
||||||
while (e) {
|
while (e) {
|
||||||
|
e.flags &= ~EffectFlags.NOTIFIED
|
||||||
if (e.flags & EffectFlags.ACTIVE) {
|
if (e.flags & EffectFlags.ACTIVE) {
|
||||||
try {
|
try {
|
||||||
// ACTIVE flag is effect-only
|
// ACTIVE flag is effect-only
|
||||||
|
|
|
@ -1930,7 +1930,7 @@ describe('api: watch', () => {
|
||||||
warn.mockRestore()
|
warn.mockRestore()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be executed correctly', () => {
|
test('should be executed correctly', () => {
|
||||||
const v = ref(1)
|
const v = ref(1)
|
||||||
let foo = ''
|
let foo = ''
|
||||||
|
|
||||||
|
@ -1957,4 +1957,30 @@ describe('api: watch', () => {
|
||||||
v.value++
|
v.value++
|
||||||
expect(foo).toBe('12')
|
expect(foo).toBe('12')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 12045
|
||||||
|
test('sync watcher should not break pre watchers', async () => {
|
||||||
|
const count1 = ref(0)
|
||||||
|
const count2 = ref(0)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
count1,
|
||||||
|
() => {
|
||||||
|
count2.value++
|
||||||
|
},
|
||||||
|
{ flush: 'sync' },
|
||||||
|
)
|
||||||
|
|
||||||
|
const spy1 = vi.fn()
|
||||||
|
watch([count1, count2], spy1)
|
||||||
|
|
||||||
|
const spy2 = vi.fn()
|
||||||
|
watch(count1, spy2)
|
||||||
|
|
||||||
|
count1.value++
|
||||||
|
|
||||||
|
await nextTick()
|
||||||
|
expect(spy1).toHaveBeenCalled()
|
||||||
|
expect(spy2).toHaveBeenCalled()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue