From 75bfa809972a50cbe64beea70c5ba045874bd2c1 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 24 Sep 2018 13:38:54 -0400 Subject: [PATCH] fix: fix scheduler dupe invokes --- packages/core/src/createRenderer.ts | 20 ++++++++++--------- .../scheduler/__tests__/scheduler.spec.ts | 4 ---- packages/scheduler/src/index.ts | 18 +++++++---------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/packages/core/src/createRenderer.ts b/packages/core/src/createRenderer.ts index 1deb16305b..3d9af82139 100644 --- a/packages/core/src/createRenderer.ts +++ b/packages/core/src/createRenderer.ts @@ -160,10 +160,6 @@ export function createRenderer(options: RendererOptions) { const hooks: Function[] = [] - function queueHook(fn: Function) { - hooks.push(fn) - } - function flushHooks() { let fn while ((fn = hooks.shift())) { @@ -251,7 +247,7 @@ export function createRenderer(options: RendererOptions) { } function mountRef(ref: Ref, el: RenderNode | MountedComponent) { - queueHook(() => { + hooks.push(() => { ref(el) }) } @@ -1166,8 +1162,9 @@ export function createRenderer(options: RendererOptions) { } }, { - scheduler: queueUpdate - // TODO add API for using onTrigger for component re-render debugging + scheduler: queueUpdate, + onTrack: instance.renderTracked, + onTrigger: instance.renderTriggered } ) @@ -1185,7 +1182,7 @@ export function createRenderer(options: RendererOptions) { mountRef(ref, instance) } if (instance.mounted) { - queueHook(() => { + hooks.push(() => { ;(instance as any).mounted.call(instance.$proxy) }) } @@ -1220,7 +1217,12 @@ export function createRenderer(options: RendererOptions) { } if (instance.updated) { - queueHook(() => { + // Because the child's update is executed by the scheduler and not + // synchronously within the parent's update call, the child's updated hook + // will be added to the queue AFTER the parent's, but they should be + // invoked BEFORE the parent's. Therefore we add them to the head of the + // queue instead. + hooks.unshift(() => { ;(instance as any).updated.call(instance.$proxy, nextVNode) }) } diff --git a/packages/scheduler/__tests__/scheduler.spec.ts b/packages/scheduler/__tests__/scheduler.spec.ts index fccd4ffd21..a0aa89fd52 100644 --- a/packages/scheduler/__tests__/scheduler.spec.ts +++ b/packages/scheduler/__tests__/scheduler.spec.ts @@ -22,8 +22,6 @@ describe('scheduler', () => { calls.push('job1') // job1 queues job2 queueJob(job2) - // should be called sync - expect(calls).toEqual(['job1', 'job2']) } const job2 = () => { calls.push('job2') @@ -60,8 +58,6 @@ describe('scheduler', () => { calls.push('job1') // job1 queues job2 queueJob(job2, cb2) - // should be called sync - expect(calls).toEqual(['job1', 'job2']) } const job2 = () => { calls.push('job2') diff --git a/packages/scheduler/src/index.ts b/packages/scheduler/src/index.ts index e99840be78..93172ffdd5 100644 --- a/packages/scheduler/src/index.ts +++ b/packages/scheduler/src/index.ts @@ -2,7 +2,7 @@ const queue: Array<() => void> = [] const postFlushCbs: Array<() => void> = [] const p = Promise.resolve() -let flushing = false +let hasPendingFlush = false export function nextTick(fn?: () => void): Promise { return p.then(fn) @@ -10,22 +10,18 @@ export function nextTick(fn?: () => void): Promise { export function queueJob(job: () => void, postFlushCb?: () => void) { if (queue.indexOf(job) === -1) { - if (flushing) { - job() - } else { - queue.push(job) + queue.push(job) + if (!hasPendingFlush) { + hasPendingFlush = true + nextTick(flushJobs) } } - if (postFlushCb) { + if (postFlushCb && postFlushCbs.indexOf(postFlushCb) === -1) { postFlushCbs.push(postFlushCb) } - if (!flushing) { - nextTick(flushJobs) - } } function flushJobs() { - flushing = true let job while ((job = queue.shift())) { job() @@ -33,5 +29,5 @@ function flushJobs() { while ((job = postFlushCbs.shift())) { job() } - flushing = false + hasPendingFlush = false } -- 2.47.3