Fix error when recursively traverse an object (#2686)

* fix 'Maximum call stack size exceeded' when recursively traverse an object

* remove semicolon

* simplify  assignment expression

* add unit test for circular references detected in Watcher#traverse
This commit is contained in:
flytreeleft 2016-04-17 12:18:17 +08:00 committed by Evan You
parent cfad4234dd
commit e314db1af1
2 changed files with 31 additions and 3 deletions

View File

@ -334,14 +334,25 @@ Watcher.prototype.teardown = function () {
* @param {*} val
*/
function traverse (val) {
function traverse (val, walkedObjs) {
var i, keys
walkedObjs = walkedObjs || {}
if (isArray(val)) {
i = val.length
while (i--) traverse(val[i])
while (i--) traverse(val[i], walkedObjs)
} else if (isObject(val)) {
if (val.__ob__) {
var depId = val.__ob__.dep.id
if (walkedObjs[depId]) {
return
} else {
walkedObjs[depId] = true
}
}
keys = Object.keys(val)
i = keys.length
while (i--) traverse(val[keys[i]])
while (i--) traverse(val[keys[i]], walkedObjs)
}
}

View File

@ -286,6 +286,23 @@ describe('Watcher', function () {
})
})
it('deep watch with circular references', function (done) {
new Watcher(vm, 'b', spy, {
deep: true
})
Vue.set(vm.b, '_', vm.b)
nextTick(function () {
expect(spy).toHaveBeenCalledWith(vm.b, vm.b)
expect(spy.calls.count()).toBe(1)
vm.b._.c = 1
nextTick(function () {
expect(spy).toHaveBeenCalledWith(vm.b, vm.b)
expect(spy.calls.count()).toBe(2)
done()
})
})
})
it('fire change for prop addition/deletion in non-deep mode', function (done) {
new Watcher(vm, 'b', spy)
Vue.set(vm.b, 'e', 123)