fix: fix scheduler dupe invokes

This commit is contained in:
Evan You 2018-09-24 13:38:54 -04:00
parent f398c129e6
commit 75bfa80997
3 changed files with 18 additions and 24 deletions

View File

@ -160,10 +160,6 @@ export function createRenderer(options: RendererOptions) {
const hooks: Function[] = [] const hooks: Function[] = []
function queueHook(fn: Function) {
hooks.push(fn)
}
function flushHooks() { function flushHooks() {
let fn let fn
while ((fn = hooks.shift())) { while ((fn = hooks.shift())) {
@ -251,7 +247,7 @@ export function createRenderer(options: RendererOptions) {
} }
function mountRef(ref: Ref, el: RenderNode | MountedComponent) { function mountRef(ref: Ref, el: RenderNode | MountedComponent) {
queueHook(() => { hooks.push(() => {
ref(el) ref(el)
}) })
} }
@ -1166,8 +1162,9 @@ export function createRenderer(options: RendererOptions) {
} }
}, },
{ {
scheduler: queueUpdate scheduler: queueUpdate,
// TODO add API for using onTrigger for component re-render debugging onTrack: instance.renderTracked,
onTrigger: instance.renderTriggered
} }
) )
@ -1185,7 +1182,7 @@ export function createRenderer(options: RendererOptions) {
mountRef(ref, instance) mountRef(ref, instance)
} }
if (instance.mounted) { if (instance.mounted) {
queueHook(() => { hooks.push(() => {
;(instance as any).mounted.call(instance.$proxy) ;(instance as any).mounted.call(instance.$proxy)
}) })
} }
@ -1220,7 +1217,12 @@ export function createRenderer(options: RendererOptions) {
} }
if (instance.updated) { 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) ;(instance as any).updated.call(instance.$proxy, nextVNode)
}) })
} }

View File

@ -22,8 +22,6 @@ describe('scheduler', () => {
calls.push('job1') calls.push('job1')
// job1 queues job2 // job1 queues job2
queueJob(job2) queueJob(job2)
// should be called sync
expect(calls).toEqual(['job1', 'job2'])
} }
const job2 = () => { const job2 = () => {
calls.push('job2') calls.push('job2')
@ -60,8 +58,6 @@ describe('scheduler', () => {
calls.push('job1') calls.push('job1')
// job1 queues job2 // job1 queues job2
queueJob(job2, cb2) queueJob(job2, cb2)
// should be called sync
expect(calls).toEqual(['job1', 'job2'])
} }
const job2 = () => { const job2 = () => {
calls.push('job2') calls.push('job2')

View File

@ -2,7 +2,7 @@ const queue: Array<() => void> = []
const postFlushCbs: Array<() => void> = [] const postFlushCbs: Array<() => void> = []
const p = Promise.resolve() const p = Promise.resolve()
let flushing = false let hasPendingFlush = false
export function nextTick(fn?: () => void): Promise<void> { export function nextTick(fn?: () => void): Promise<void> {
return p.then(fn) return p.then(fn)
@ -10,22 +10,18 @@ export function nextTick(fn?: () => void): Promise<void> {
export function queueJob(job: () => void, postFlushCb?: () => void) { export function queueJob(job: () => void, postFlushCb?: () => void) {
if (queue.indexOf(job) === -1) { if (queue.indexOf(job) === -1) {
if (flushing) { queue.push(job)
job() if (!hasPendingFlush) {
} else { hasPendingFlush = true
queue.push(job) nextTick(flushJobs)
} }
} }
if (postFlushCb) { if (postFlushCb && postFlushCbs.indexOf(postFlushCb) === -1) {
postFlushCbs.push(postFlushCb) postFlushCbs.push(postFlushCb)
} }
if (!flushing) {
nextTick(flushJobs)
}
} }
function flushJobs() { function flushJobs() {
flushing = true
let job let job
while ((job = queue.shift())) { while ((job = queue.shift())) {
job() job()
@ -33,5 +29,5 @@ function flushJobs() {
while ((job = postFlushCbs.shift())) { while ((job = postFlushCbs.shift())) {
job() job()
} }
flushing = false hasPendingFlush = false
} }