From 71019ed772aab81baed6684ffc60c7b7d8ab442a Mon Sep 17 00:00:00 2001 From: raoht Date: Fri, 9 Dec 2022 14:27:30 +0800 Subject: [PATCH] fix #12897:call newly pushed watcher orderly --- src/core/observer/scheduler.ts | 8 +++++- test/unit/modules/observer/scheduler.spec.ts | 30 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/core/observer/scheduler.ts b/src/core/observer/scheduler.ts index 8fc82b48cf4..b403af80f90 100644 --- a/src/core/observer/scheduler.ts +++ b/src/core/observer/scheduler.ts @@ -8,7 +8,7 @@ import type { Component } from 'types/component' export const MAX_UPDATE_COUNT = 100 -const queue: Array = [] +let queue: Array = [] const activatedChildren: Array = [] let has: { [key: number]: true | undefined | null } = {} let circular: { [key: number]: number } = {} @@ -96,6 +96,12 @@ function flushSchedulerQueue() { id = watcher.id has[id] = null watcher.run() + //when flushing,new watchers will be added to the queue and they should be resort + queue = [ + ...queue.slice(0, index + 1), + ...queue.slice(index + 1).sort(sortCompareFn) + ] + // in dev build, check and stop circular updates. if (__DEV__ && has[id] != null) { circular[id] = (circular[id] || 0) + 1 diff --git a/test/unit/modules/observer/scheduler.spec.ts b/test/unit/modules/observer/scheduler.spec.ts index 001ee5a429a..4953b5b2f3d 100644 --- a/test/unit/modules/observer/scheduler.spec.ts +++ b/test/unit/modules/observer/scheduler.spec.ts @@ -151,6 +151,36 @@ describe('Scheduler', () => { }).then(done) }) + // Github issue #12897 + it('should call newly pushed watcher orderly via the flush attribute after current watcher is done', done => { + const callOrder: any[] = [] + queueWatcher({ + id: 1, + user: true, + run() { + callOrder.push(1) + + queueWatcher({ + id: 3, + run() { + callOrder.push(4) + }, + post: true + }) + queueWatcher({ + id: 4, + run() { + callOrder.push(3) + } + }), + callOrder.push(2) + } + }) + waitForUpdate(() => { + expect(callOrder).toEqual([1, 2, 3, 4]) + }).then(done) + }) + // GitHub issue #5191 it('emit should work when updated hook called', done => { const el = document.createElement('div')