From 93498ab3d01fceb616fd3311d5129a6a9702ddb3 Mon Sep 17 00:00:00 2001 From: Evan You Date: Sun, 17 Apr 2016 22:37:10 -0400 Subject: [PATCH] handle circular refs in deep watch --- src/runtime/observer/watcher.js | 36 ++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/runtime/observer/watcher.js b/src/runtime/observer/watcher.js index d2722cb4..458b2af2 100644 --- a/src/runtime/observer/watcher.js +++ b/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) + } } }