1 |
|
2 |
|
3 | import type Watcher from './watcher'
|
4 | import config from '../config'
|
5 | import { callHook, activateChildComponent } from '../instance/lifecycle'
|
6 |
|
7 | import {
|
8 | warn,
|
9 | nextTick,
|
10 | devtools,
|
11 | inBrowser,
|
12 | isIE
|
13 | } from '../util/index'
|
14 |
|
15 | export const MAX_UPDATE_COUNT = 100
|
16 |
|
17 | const queue: Array<Watcher> = []
|
18 | const activatedChildren: Array<Component> = []
|
19 | let has: { [key: number]: ?true } = {}
|
20 | let circular: { [key: number]: number } = {}
|
21 | let waiting = false
|
22 | let flushing = false
|
23 | let index = 0
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | function resetSchedulerState () {
|
29 | index = queue.length = activatedChildren.length = 0
|
30 | has = {}
|
31 | if (process.env.NODE_ENV !== 'production') {
|
32 | circular = {}
|
33 | }
|
34 | waiting = flushing = false
|
35 | }
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 | export let currentFlushTimestamp = 0
|
43 |
|
44 |
|
45 | let getNow: () => number = Date.now
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | if (inBrowser && !isIE) {
|
54 | const performance = window.performance
|
55 | if (
|
56 | performance &&
|
57 | typeof performance.now === 'function' &&
|
58 | getNow() > document.createEvent('Event').timeStamp
|
59 | ) {
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | getNow = () => performance.now()
|
65 | }
|
66 | }
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | function flushSchedulerQueue () {
|
72 | currentFlushTimestamp = getNow()
|
73 | flushing = true
|
74 | let watcher, id
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 | queue.sort((a, b) => a.id - b.id)
|
85 |
|
86 |
|
87 |
|
88 | for (index = 0; index < queue.length; index++) {
|
89 | watcher = queue[index]
|
90 | if (watcher.before) {
|
91 | watcher.before()
|
92 | }
|
93 | id = watcher.id
|
94 | has[id] = null
|
95 | watcher.run()
|
96 |
|
97 | if (process.env.NODE_ENV !== 'production' && has[id] != null) {
|
98 | circular[id] = (circular[id] || 0) + 1
|
99 | if (circular[id] > MAX_UPDATE_COUNT) {
|
100 | warn(
|
101 | 'You may have an infinite update loop ' + (
|
102 | watcher.user
|
103 | ? `in watcher with expression "${watcher.expression}"`
|
104 | : `in a component render function.`
|
105 | ),
|
106 | watcher.vm
|
107 | )
|
108 | break
|
109 | }
|
110 | }
|
111 | }
|
112 |
|
113 |
|
114 | const activatedQueue = activatedChildren.slice()
|
115 | const updatedQueue = queue.slice()
|
116 |
|
117 | resetSchedulerState()
|
118 |
|
119 |
|
120 | callActivatedHooks(activatedQueue)
|
121 | callUpdatedHooks(updatedQueue)
|
122 |
|
123 |
|
124 |
|
125 | if (devtools && config.devtools) {
|
126 | devtools.emit('flush')
|
127 | }
|
128 | }
|
129 |
|
130 | function callUpdatedHooks (queue) {
|
131 | let i = queue.length
|
132 | while (i--) {
|
133 | const watcher = queue[i]
|
134 | const vm = watcher.vm
|
135 | if (vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) {
|
136 | callHook(vm, 'updated')
|
137 | }
|
138 | }
|
139 | }
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 | export function queueActivatedComponent (vm: Component) {
|
146 |
|
147 |
|
148 | vm._inactive = false
|
149 | activatedChildren.push(vm)
|
150 | }
|
151 |
|
152 | function callActivatedHooks (queue) {
|
153 | for (let i = 0; i < queue.length; i++) {
|
154 | queue[i]._inactive = true
|
155 | activateChildComponent(queue[i], true )
|
156 | }
|
157 | }
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 | export function queueWatcher (watcher: Watcher) {
|
165 | const id = watcher.id
|
166 | if (has[id] == null) {
|
167 | has[id] = true
|
168 | if (!flushing) {
|
169 | queue.push(watcher)
|
170 | } else {
|
171 |
|
172 |
|
173 | let i = queue.length - 1
|
174 | while (i > index && queue[i].id > watcher.id) {
|
175 | i--
|
176 | }
|
177 | queue.splice(i + 1, 0, watcher)
|
178 | }
|
179 |
|
180 | if (!waiting) {
|
181 | waiting = true
|
182 |
|
183 | if (process.env.NODE_ENV !== 'production' && !config.async) {
|
184 | flushSchedulerQueue()
|
185 | return
|
186 | }
|
187 | nextTick(flushSchedulerQueue)
|
188 | }
|
189 | }
|
190 | }
|