Просмотр исходного кода

handle circular refs in deep watch

Evan You 10 лет назад
Родитель
Сommit
93498ab3d0
1 измененных файлов с 27 добавлено и 9 удалено
  1. 27 9
      src/runtime/observer/watcher.js

+ 27 - 9
src/runtime/observer/watcher.js

@@ -246,16 +246,34 @@ Watcher.prototype.teardown = function () {
  * is collected as a "deep" dependency.
  *
  * @param {*} val
+ * @param {Set} seen
  */
 
-function traverse (val) {
-  var i, keys
-  if (isArray(val)) {
-    i = val.length
-    while (i--) traverse(val[i])
-  } else if (isObject(val)) {
-    keys = Object.keys(val)
-    i = keys.length
-    while (i--) traverse(val[keys[i]])
+const seenObjects = new Set()
+function traverse (val, seen) {
+  let i, keys, isA, isO
+  if (!seen) {
+    seen = seenObjects
+    seen.clear()
+  }
+  isA = isArray(val)
+  isO = isObject(val)
+  if (isA || isO) {
+    if (val.__ob__) {
+      var depId = val.__ob__.dep.id
+      if (seen.has(depId)) {
+        return
+      } else {
+        seen.add(depId)
+      }
+    }
+    if (isA) {
+      i = val.length
+      while (i--) traverse(val[i], seen)
+    } else if (isO) {
+      keys = Object.keys(val)
+      i = keys.length
+      while (i--) traverse(val[keys[i]], seen)
+    }
   }
 }