| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import { ErrorCodes, callWithErrorHandling } from './errorHandling'
- import { isArray } from '@vue/shared'
- const queue: Function[] = []
- const postFlushCbs: Function[] = []
- const p = Promise.resolve()
- let isFlushing = false
- let isFlushPending = false
- const RECURSION_LIMIT = 100
- type CountMap = Map<Function, number>
- export function nextTick(fn?: () => void): Promise<void> {
- return fn ? p.then(fn) : p
- }
- export function queueJob(job: () => void) {
- if (!queue.includes(job)) {
- queue.push(job)
- queueFlush()
- }
- }
- export function queuePostFlushCb(cb: Function | Function[]) {
- if (!isArray(cb)) {
- postFlushCbs.push(cb)
- } else {
- postFlushCbs.push(...cb)
- }
- queueFlush()
- }
- function queueFlush() {
- if (!isFlushing && !isFlushPending) {
- isFlushPending = true
- nextTick(flushJobs)
- }
- }
- const dedupe = (cbs: Function[]): Function[] => [...new Set(cbs)]
- export function flushPostFlushCbs(seen?: CountMap) {
- if (postFlushCbs.length) {
- const cbs = dedupe(postFlushCbs)
- postFlushCbs.length = 0
- if (__DEV__) {
- seen = seen || new Map()
- }
- for (let i = 0; i < cbs.length; i++) {
- if (__DEV__) {
- checkRecursiveUpdates(seen!, cbs[i])
- }
- cbs[i]()
- }
- }
- }
- function flushJobs(seen?: CountMap) {
- isFlushPending = false
- isFlushing = true
- let job
- if (__DEV__) {
- seen = seen || new Map()
- }
- while ((job = queue.shift())) {
- if (__DEV__) {
- checkRecursiveUpdates(seen!, job)
- }
- callWithErrorHandling(job, null, ErrorCodes.SCHEDULER)
- }
- flushPostFlushCbs(seen)
- isFlushing = false
- // some postFlushCb queued jobs!
- // keep flushing until it drains.
- if (queue.length || postFlushCbs.length) {
- flushJobs(seen)
- }
- }
- function checkRecursiveUpdates(seen: CountMap, fn: Function) {
- if (!seen.has(fn)) {
- seen.set(fn, 1)
- } else {
- const count = seen.get(fn)!
- if (count > RECURSION_LIMIT) {
- throw new Error(
- 'Maximum recursive updates exceeded. ' +
- "You may have code that is mutating state in your component's " +
- 'render function or updated hook or watcher source function.'
- )
- } else {
- seen.set(fn, count + 1)
- }
- }
- }
|