| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- var _ = require('./util')
- var config = require('./config')
- // we have two separate queues: one for directive updates
- // and one for user watcher registered via $watch().
- // we want to guarantee directive updates to be called
- // before user watchers so that when user watchers are
- // triggered, the DOM would have already been in updated
- // state.
- var queue = []
- var userQueue = []
- var has = {}
- var circular = {}
- var waiting = false
- var internalQueueDepleted = false
- /**
- * Reset the batcher's state.
- */
- function resetBatcherState () {
- queue = []
- userQueue = []
- has = {}
- circular = {}
- waiting = internalQueueDepleted = false
- }
- /**
- * Flush both queues and run the watchers.
- */
- function flushBatcherQueue () {
- runBatcherQueue(queue)
- internalQueueDepleted = true
- runBatcherQueue(userQueue)
- // dev tool hook
- /* istanbul ignore if */
- if (process.env.NODE_ENV !== 'production') {
- if (_.inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__) {
- window.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit('flush')
- }
- }
- resetBatcherState()
- }
- /**
- * Run the watchers in a single queue.
- *
- * @param {Array} queue
- */
- function runBatcherQueue (queue) {
- // do not cache length because more watchers might be pushed
- // as we run existing watchers
- for (var i = 0; i < queue.length; i++) {
- var watcher = queue[i]
- var id = watcher.id
- has[id] = null
- watcher.run()
- // in dev build, check and stop circular updates.
- if (process.env.NODE_ENV !== 'production' && has[id] != null) {
- circular[id] = (circular[id] || 0) + 1
- if (circular[id] > config._maxUpdateCount) {
- queue.splice(has[id], 1)
- _.warn(
- 'You may have an infinite update loop for watcher ' +
- 'with expression: ' + watcher.expression
- )
- }
- }
- }
- }
- /**
- * Push a watcher into the watcher queue.
- * Jobs with duplicate IDs will be skipped unless it's
- * pushed when the queue is being flushed.
- *
- * @param {Watcher} watcher
- * properties:
- * - {Number} id
- * - {Function} run
- */
- exports.push = function (watcher) {
- var id = watcher.id
- if (has[id] == null) {
- // if an internal watcher is pushed, but the internal
- // queue is already depleted, we run it immediately.
- if (internalQueueDepleted && !watcher.user) {
- watcher.run()
- return
- }
- // push watcher into appropriate queue
- var q = watcher.user ? userQueue : queue
- has[id] = q.length
- q.push(watcher)
- // queue the flush
- if (!waiting) {
- waiting = true
- _.nextTick(flushBatcherQueue)
- }
- }
- }
|