From 03a530f0d62a68ac5aa62f2bf76b7a3b3e104748 Mon Sep 17 00:00:00 2001 From: linzhe141 <1572213544@qq.com> Date: Mon, 12 Aug 2024 11:16:30 +0800 Subject: [PATCH 1/7] fix(reactivety): sync watch should be executed correctly --- packages/reactivity/src/dep.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/reactivity/src/dep.ts b/packages/reactivity/src/dep.ts index 4ce73ac9954..bb2362e428b 100644 --- a/packages/reactivity/src/dep.ts +++ b/packages/reactivity/src/dep.ts @@ -145,7 +145,7 @@ export class Dep { } } } - for (let link = this.subs; link; link = link.prevSub) { + for (let link = this.subsHead; link; link = link.nextSub) { link.sub.notify() } } finally { From 563132bbf921cc6fc8b1d66d661b1b889280706f Mon Sep 17 00:00:00 2001 From: linzhe141 <1572213544@qq.com> Date: Mon, 12 Aug 2024 13:55:13 +0800 Subject: [PATCH 2/7] chore: update --- packages/reactivity/src/dep.ts | 2 +- packages/runtime-core/src/apiWatch.ts | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/reactivity/src/dep.ts b/packages/reactivity/src/dep.ts index bb2362e428b..4ce73ac9954 100644 --- a/packages/reactivity/src/dep.ts +++ b/packages/reactivity/src/dep.ts @@ -145,7 +145,7 @@ export class Dep { } } } - for (let link = this.subsHead; link; link = link.nextSub) { + for (let link = this.subs; link; link = link.prevSub) { link.sub.notify() } } finally { diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 2ad887a349d..badc277a5ba 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -175,6 +175,8 @@ export function watch = false>( return doWatch(source as any, cb, options) } +const syncJobs: SchedulerJob[] = [] + function doWatch( source: WatchSource | WatchSource[] | WatchEffect | object, cb: WatchCallback | null, @@ -395,7 +397,14 @@ function doWatch( let scheduler: EffectScheduler if (flush === 'sync') { effect.flags |= EffectFlags.NO_BATCH - scheduler = job as any // the scheduler function gets called directly + syncJobs.push(job) + scheduler = () => { + const job = syncJobs.shift() + if (job) { + syncJobs.push(job) + job() + } + } // the scheduler function gets called directly in reverse-order } else if (flush === 'post') { scheduler = () => queuePostRenderEffect(job, instance && instance.suspense) } else { From a650c5f799b227ad24195ff19abe682028dd7d04 Mon Sep 17 00:00:00 2001 From: linzhe141 <1572213544@qq.com> Date: Mon, 12 Aug 2024 14:21:26 +0800 Subject: [PATCH 3/7] chore: update test --- .../runtime-core/__tests__/apiWatch.spec.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 85afec24ceb..67f0bc160e3 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -1856,4 +1856,32 @@ describe('api: watch', () => { warn.mockRestore() }) + + it('should be executed correctly', () => { + const v = ref(1) + let foo = '' + + watch( + v, + () => { + foo += '1' + }, + { + flush: 'sync', + }, + ) + watch( + v, + () => { + foo += '2' + }, + { + flush: 'sync', + }, + ) + + expect(foo).toBe('') + v.value++ + expect(foo).toBe('12') + }) }) From 5c2bc2376564c40a03d9e7b79f87e71a0244d3b1 Mon Sep 17 00:00:00 2001 From: linzhe Date: Mon, 12 Aug 2024 21:58:33 +0800 Subject: [PATCH 4/7] chore: update --- packages/reactivity/src/effect.ts | 4 ++-- packages/runtime-core/src/apiWatch.ts | 12 ++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 6b18318dd1d..2e7a2fb7e98 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -169,7 +169,7 @@ export class ReactiveEffect ) { return } - if (this.flags & EffectFlags.NO_BATCH) { + if (this.flags & EffectFlags.NO_BATCH && !batchDepth) { return this.trigger() } if (!(this.flags & EffectFlags.NOTIFIED)) { @@ -267,6 +267,7 @@ export function endBatch(): void { return } + batchDepth-- let error: unknown while (batchedEffect) { let e: ReactiveEffect | undefined = batchedEffect @@ -286,7 +287,6 @@ export function endBatch(): void { } } - batchDepth-- if (error) throw error } diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index badc277a5ba..95ad76cb16d 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -175,8 +175,6 @@ export function watch = false>( return doWatch(source as any, cb, options) } -const syncJobs: SchedulerJob[] = [] - function doWatch( source: WatchSource | WatchSource[] | WatchEffect | object, cb: WatchCallback | null, @@ -397,14 +395,8 @@ function doWatch( let scheduler: EffectScheduler if (flush === 'sync') { effect.flags |= EffectFlags.NO_BATCH - syncJobs.push(job) - scheduler = () => { - const job = syncJobs.shift() - if (job) { - syncJobs.push(job) - job() - } - } // the scheduler function gets called directly in reverse-order + + scheduler = job as any } else if (flush === 'post') { scheduler = () => queuePostRenderEffect(job, instance && instance.suspense) } else { From e8075fd582a4e9a7d6238e7850c1649486727e3c Mon Sep 17 00:00:00 2001 From: linzhe Date: Mon, 12 Aug 2024 22:03:12 +0800 Subject: [PATCH 5/7] chore: update --- packages/runtime-core/src/apiWatch.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 95ad76cb16d..7675dd6c6b8 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -395,7 +395,6 @@ function doWatch( let scheduler: EffectScheduler if (flush === 'sync') { effect.flags |= EffectFlags.NO_BATCH - scheduler = job as any } else if (flush === 'post') { scheduler = () => queuePostRenderEffect(job, instance && instance.suspense) From f96fa26ddfb5415d521840c2e7e58b130d12dff6 Mon Sep 17 00:00:00 2001 From: linzhe Date: Mon, 12 Aug 2024 22:04:19 +0800 Subject: [PATCH 6/7] chore: update --- packages/runtime-core/src/apiWatch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 7675dd6c6b8..2ad887a349d 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -395,7 +395,7 @@ function doWatch( let scheduler: EffectScheduler if (flush === 'sync') { effect.flags |= EffectFlags.NO_BATCH - scheduler = job as any + scheduler = job as any // the scheduler function gets called directly } else if (flush === 'post') { scheduler = () => queuePostRenderEffect(job, instance && instance.suspense) } else { From 606d86eace2a4e32ff758d655733974fa09ecf13 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 13 Aug 2024 22:51:03 +0800 Subject: [PATCH 7/7] chore: remove no_batch --- packages/reactivity/src/effect.ts | 6 +----- packages/runtime-core/src/apiWatch.ts | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 2e7a2fb7e98..c769ba57d8c 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -45,8 +45,7 @@ export enum EffectFlags { NOTIFIED = 1 << 3, DIRTY = 1 << 4, ALLOW_RECURSE = 1 << 5, - NO_BATCH = 1 << 6, - PAUSED = 1 << 7, + PAUSED = 1 << 6, } /** @@ -169,9 +168,6 @@ export class ReactiveEffect ) { return } - if (this.flags & EffectFlags.NO_BATCH && !batchDepth) { - return this.trigger() - } if (!(this.flags & EffectFlags.NOTIFIED)) { this.flags |= EffectFlags.NOTIFIED this.nextEffect = batchedEffect diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 2ad887a349d..479a263b39b 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -394,7 +394,6 @@ function doWatch( let scheduler: EffectScheduler if (flush === 'sync') { - effect.flags |= EffectFlags.NO_BATCH scheduler = job as any // the scheduler function gets called directly } else if (flush === 'post') { scheduler = () => queuePostRenderEffect(job, instance && instance.suspense)