@@ -12,6 +12,9 @@ const p = Promise.resolve()
12
12
13
13
let isFlushing = false
14
14
let isFlushPending = false
15
+ let flushIndex = 0
16
+ let pendingPostFlushCbs : Function [ ] | null = null
17
+ let pendingPostFlushIndex = 0
15
18
16
19
const RECURSION_LIMIT = 100
17
20
type CountMap = Map < Job | Function , number >
@@ -21,7 +24,7 @@ export function nextTick(fn?: () => void): Promise<void> {
21
24
}
22
25
23
26
export function queueJob ( job : Job ) {
24
- if ( ! queue . includes ( job ) ) {
27
+ if ( ! queue . includes ( job , flushIndex ) ) {
25
28
queue . push ( job )
26
29
queueFlush ( )
27
30
}
@@ -36,8 +39,16 @@ export function invalidateJob(job: Job) {
36
39
37
40
export function queuePostFlushCb ( cb : Function | Function [ ] ) {
38
41
if ( ! isArray ( cb ) ) {
39
- postFlushCbs . push ( cb )
42
+ if (
43
+ ! pendingPostFlushCbs ||
44
+ ! pendingPostFlushCbs . includes ( cb , pendingPostFlushIndex )
45
+ ) {
46
+ postFlushCbs . push ( cb )
47
+ }
40
48
} else {
49
+ // if cb is an array, it is a component lifecycle hook which can only be
50
+ // triggered by a job, which is already deduped in the main queue, so
51
+ // we can skip dupicate check here to improve perf
41
52
postFlushCbs . push ( ...cb )
42
53
}
43
54
queueFlush ( )
@@ -52,17 +63,23 @@ function queueFlush() {
52
63
53
64
export function flushPostFlushCbs ( seen ?: CountMap ) {
54
65
if ( postFlushCbs . length ) {
55
- const cbs = [ ...new Set ( postFlushCbs ) ]
66
+ pendingPostFlushCbs = [ ...new Set ( postFlushCbs ) ]
56
67
postFlushCbs . length = 0
57
68
if ( __DEV__ ) {
58
69
seen = seen || new Map ( )
59
70
}
60
- for ( let i = 0 ; i < cbs . length ; i ++ ) {
71
+ for (
72
+ pendingPostFlushIndex = 0 ;
73
+ pendingPostFlushIndex < pendingPostFlushCbs . length ;
74
+ pendingPostFlushIndex ++
75
+ ) {
61
76
if ( __DEV__ ) {
62
- checkRecursiveUpdates ( seen ! , cbs [ i ] )
77
+ checkRecursiveUpdates ( seen ! , pendingPostFlushCbs [ pendingPostFlushIndex ] )
63
78
}
64
- cbs [ i ] ( )
79
+ pendingPostFlushCbs [ pendingPostFlushIndex ] ( )
65
80
}
81
+ pendingPostFlushCbs = null
82
+ pendingPostFlushIndex = 0
66
83
}
67
84
}
68
85
@@ -71,7 +88,6 @@ const getId = (job: Job) => (job.id == null ? Infinity : job.id)
71
88
function flushJobs ( seen ?: CountMap ) {
72
89
isFlushPending = false
73
90
isFlushing = true
74
- let job
75
91
if ( __DEV__ ) {
76
92
seen = seen || new Map ( )
77
93
}
@@ -87,15 +103,18 @@ function flushJobs(seen?: CountMap) {
87
103
// during execution of another flushed job.
88
104
queue . sort ( ( a , b ) => getId ( a ! ) - getId ( b ! ) )
89
105
90
- while ( ( job = queue . shift ( ) ) !== undefined ) {
91
- if ( job === null ) {
92
- continue
93
- }
94
- if ( __DEV__ ) {
95
- checkRecursiveUpdates ( seen ! , job )
106
+ for ( flushIndex = 0 ; flushIndex < queue . length ; flushIndex ++ ) {
107
+ const job = queue [ flushIndex ]
108
+ if ( job ) {
109
+ if ( __DEV__ ) {
110
+ checkRecursiveUpdates ( seen ! , job )
111
+ }
112
+ callWithErrorHandling ( job , null , ErrorCodes . SCHEDULER )
96
113
}
97
- callWithErrorHandling ( job , null , ErrorCodes . SCHEDULER )
98
114
}
115
+ flushIndex = 0
116
+ queue . length = 0
117
+
99
118
flushPostFlushCbs ( seen )
100
119
isFlushing = false
101
120
// some postFlushCb queued jobs!
0 commit comments