From ff35f0b98c3ecc3e37e1680b1d231cfad80ca419 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Fri, 31 Aug 2018 14:42:49 +0800 Subject: [PATCH 1/4] fix(#8728): only execute the dependArray function once --- src/core/observer/index.js | 3 ++- src/core/observer/watcher.js | 7 ++++++ test/unit/modules/observer/observer.spec.js | 27 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/core/observer/index.js b/src/core/observer/index.js index 35469aaf16a..4770e88a8df 100644 --- a/src/core/observer/index.js +++ b/src/core/observer/index.js @@ -161,8 +161,9 @@ export function defineReactive ( if (Dep.target) { dep.depend() if (childOb) { + const needDepend = Array.isArray(value) && !Dep.target.checkRelated(childOb.dep) childOb.dep.depend() - if (Array.isArray(value)) { + if (needDepend) { dependArray(value) } } diff --git a/src/core/observer/watcher.js b/src/core/observer/watcher.js index 725480d9215..a0715f99405 100644 --- a/src/core/observer/watcher.js +++ b/src/core/observer/watcher.js @@ -139,6 +139,13 @@ export default class Watcher { } } + /** + * Check if a dependency has been associated with the current watcher. + */ + checkRelated (dep: Dep) { + return this.newDepIds.has(dep.id) + } + /** * Clean up for dependency collection. */ diff --git a/test/unit/modules/observer/observer.spec.js b/test/unit/modules/observer/observer.spec.js index 5f075bccc95..db1c6e48cc6 100644 --- a/test/unit/modules/observer/observer.spec.js +++ b/test/unit/modules/observer/observer.spec.js @@ -356,6 +356,33 @@ describe('Observer', () => { }) }) + it('Array\'s getter is triggered multiple times, the Watcher should only associate with Dep once.', () => { + const data = { + arr: [{}] + } + observe(data) + // mock a watcher! + const watcher = { + newDepIds: new Set(), + addDep (dep) { + this.newDepIds.add(dep.id) + dep.addSub(this) + }, + checkRelated: function (dep) { + return this.newDepIds.has(dep.id) + } + } + spyOn(watcher, 'checkRelated').and.callThrough() + Dep.target = watcher + data.arr + data.arr + Dep.target = null + expect(watcher.checkRelated.calls.count()).toBe(2) + const allCalls = watcher.checkRelated.calls.all() + expect(allCalls[0].returnValue).toBe(false) + expect(allCalls[1].returnValue).toBe(true) + }) + it('warn set/delete on non valid values', () => { try { setProp(null, 'foo', 1) From 956e535fe57ec5a788d0005b5ea9074cf9e4cc88 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Fri, 31 Aug 2018 15:22:31 +0800 Subject: [PATCH 2/4] fix(flow): method call error --- src/core/observer/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/observer/index.js b/src/core/observer/index.js index 4770e88a8df..44b686e6aea 100644 --- a/src/core/observer/index.js +++ b/src/core/observer/index.js @@ -158,10 +158,11 @@ export function defineReactive ( configurable: true, get: function reactiveGetter () { const value = getter ? getter.call(obj) : val - if (Dep.target) { + const targetWatcher = Dep.target + if (targetWatcher) { dep.depend() if (childOb) { - const needDepend = Array.isArray(value) && !Dep.target.checkRelated(childOb.dep) + const needDepend = Array.isArray(value) && !targetWatcher.checkRelated(childOb.dep) childOb.dep.depend() if (needDepend) { dependArray(value) From bfe76e0ee3ead720c161ab9bb2df9616670a9eeb Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Fri, 31 Aug 2018 15:51:37 +0800 Subject: [PATCH 3/4] fix(test): use polyfill Set --- test/unit/modules/observer/observer.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/modules/observer/observer.spec.js b/test/unit/modules/observer/observer.spec.js index db1c6e48cc6..79cc5097c30 100644 --- a/test/unit/modules/observer/observer.spec.js +++ b/test/unit/modules/observer/observer.spec.js @@ -6,7 +6,7 @@ import { del as delProp } from 'core/observer/index' import Dep from 'core/observer/dep' -import { hasOwn } from 'core/util/index' +import { hasOwn, Set } from 'core/util/index' describe('Observer', () => { it('create on non-observables', () => { From 62c232cdbac6d7d25f6fd5d1672eb33064eed18c Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Fri, 31 Aug 2018 15:57:36 +0800 Subject: [PATCH 4/4] fix(test): alias --- test/unit/modules/observer/observer.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/modules/observer/observer.spec.js b/test/unit/modules/observer/observer.spec.js index 79cc5097c30..81d2008df33 100644 --- a/test/unit/modules/observer/observer.spec.js +++ b/test/unit/modules/observer/observer.spec.js @@ -6,7 +6,7 @@ import { del as delProp } from 'core/observer/index' import Dep from 'core/observer/dep' -import { hasOwn, Set } from 'core/util/index' +import { hasOwn, _Set as Set } from 'core/util/index' describe('Observer', () => { it('create on non-observables', () => {