]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(scheduler): warn recursive updates in postFlushCbs as well (#456)
authorJiZhi <471695625@qq.com>
Thu, 14 Nov 2019 17:06:23 +0000 (01:06 +0800)
committerEvan You <yyx990803@gmail.com>
Thu, 14 Nov 2019 17:06:23 +0000 (12:06 -0500)
packages/runtime-core/src/scheduler.ts

index e291d412a6d56ff51362a2ff65047a6a34f0f73b..78d3d59cd1dcb2e2aca3d87a91e4ad6985f02c24 100644 (file)
@@ -8,6 +8,9 @@ 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
 }
@@ -37,51 +40,57 @@ function queueFlush() {
 
 const dedupe = (cbs: Function[]): Function[] => [...new Set(cbs)]
 
-export function flushPostFlushCbs() {
+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]()
     }
   }
 }
 
-const RECURSION_LIMIT = 100
-type JobCountMap = Map<Function, number>
-
-function flushJobs(seenJobs?: JobCountMap) {
+function flushJobs(seen?: CountMap) {
   isFlushPending = false
   isFlushing = true
   let job
   if (__DEV__) {
-    seenJobs = seenJobs || new Map()
+    seen = seen || new Map()
   }
   while ((job = queue.shift())) {
     if (__DEV__) {
-      const seen = seenJobs!
-      if (!seen.has(job)) {
-        seen.set(job, 1)
-      } else {
-        const count = seen.get(job)!
-        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.'
-          )
-        } else {
-          seen.set(job, count + 1)
-        }
-      }
+      checkRecursiveUpdates(seen!, job)
     }
     callWithErrorHandling(job, null, ErrorCodes.SCHEDULER)
   }
-  flushPostFlushCbs()
+  flushPostFlushCbs(seen)
   isFlushing = false
   // some postFlushCb queued jobs!
   // keep flushing until it drains.
   if (queue.length || postFlushCbs.length) {
-    flushJobs(seenJobs)
+    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)
+    }
   }
 }