diff --git a/flow/global-api.js b/flow/global-api.js index 0b2efb23ac3..cbd9d8c2e2f 100644 --- a/flow/global-api.js +++ b/flow/global-api.js @@ -8,6 +8,7 @@ declare interface GlobalAPI { set: (target: Object | Array, key: string | number, value: T) => T; delete: (target: Object| Array, key: string | number) => void; nextTick: (fn: Function, context?: Object) => void | Promise<*>; + depTarget: (target: {storage: ?Watcher}) => {storage: ?Watcher} | void; use: (plugin: Function | Object) => void; mixin: (mixin: Object) => void; compile: (template: string) => { render: Function, staticRenderFns: Array }; diff --git a/src/core/global-api/index.js b/src/core/global-api/index.js index 03ffa0fbf31..2b3d962e5d1 100644 --- a/src/core/global-api/index.js +++ b/src/core/global-api/index.js @@ -6,6 +6,7 @@ import { initMixin } from './mixin' import { initExtend } from './extend' import { initAssetRegisters } from './assets' import { set, del } from '../observer/index' +import { depTarget } from '../observer/dep' import { ASSET_TYPES } from 'shared/constants' import builtInComponents from '../components/index' @@ -43,6 +44,7 @@ export function initGlobalAPI (Vue: GlobalAPI) { Vue.set = set Vue.delete = del Vue.nextTick = nextTick + Vue.depTarget = depTarget Vue.options = Object.create(null) ASSET_TYPES.forEach(type => { diff --git a/src/core/observer/dep.js b/src/core/observer/dep.js index abf3b275ce4..eb79ac9e9c6 100644 --- a/src/core/observer/dep.js +++ b/src/core/observer/dep.js @@ -10,7 +10,7 @@ let uid = 0 * directives subscribing to it. */ export default class Dep { - static target: ?Watcher; + static target: {storage: ?Watcher}; id: number; subs: Array; @@ -28,8 +28,8 @@ export default class Dep { } depend () { - if (Dep.target) { - Dep.target.addDep(this) + if (Dep.target.storage) { + Dep.target.storage.addDep(this) } } @@ -45,14 +45,24 @@ export default class Dep { // the current target watcher being evaluated. // this is globally unique because there could be only one // watcher being evaluated at any time. -Dep.target = null +Dep.target = { + storage: null +} const targetStack = [] export function pushTarget (_target: ?Watcher) { - if (Dep.target) targetStack.push(Dep.target) - Dep.target = _target + if (Dep.target.storage) targetStack.push(Dep.target.storage) + Dep.target.storage = _target } export function popTarget () { - Dep.target = targetStack.pop() + Dep.target.storage = targetStack.pop() +} + +export function depTarget (target: {storage: ?Watcher}): {storage: ?Watcher} | void { + if (target) { + Dep.target = target + } else { + return Dep.target + } } diff --git a/src/core/observer/index.js b/src/core/observer/index.js index 35469aaf16a..409cda83ba3 100644 --- a/src/core/observer/index.js +++ b/src/core/observer/index.js @@ -158,7 +158,7 @@ export function defineReactive ( configurable: true, get: function reactiveGetter () { const value = getter ? getter.call(obj) : val - if (Dep.target) { + if (Dep.target.storage) { dep.depend() if (childOb) { childOb.dep.depend() diff --git a/src/core/observer/watcher.js b/src/core/observer/watcher.js index 725480d9215..bfe10ca2375 100644 --- a/src/core/observer/watcher.js +++ b/src/core/observer/watcher.js @@ -243,7 +243,7 @@ export default class Watcher { * Depend on this watcher. Only for computed property watchers. */ depend () { - if (this.dep && Dep.target) { + if (this.dep && Dep.target.storage) { this.dep.depend() } } diff --git a/test/unit/modules/observer/dep.spec.js b/test/unit/modules/observer/dep.spec.js index 02809f8a4d9..3514d531d6f 100644 --- a/test/unit/modules/observer/dep.spec.js +++ b/test/unit/modules/observer/dep.spec.js @@ -34,22 +34,22 @@ describe('Dep', () => { let _target beforeAll(() => { - _target = Dep.target + _target = Dep.target.storage }) afterAll(() => { - Dep.target = _target + Dep.target.storage = _target }) it('should do nothing if no target', () => { - Dep.target = null + Dep.target.storage = null dep.depend() }) it('should add itself to target', () => { - Dep.target = jasmine.createSpyObj('TARGET', ['addDep']) + Dep.target.storage = jasmine.createSpyObj('TARGET', ['addDep']) dep.depend() - expect(Dep.target.addDep).toHaveBeenCalledWith(dep) + expect(Dep.target.storage.addDep).toHaveBeenCalledWith(dep) }) }) diff --git a/test/unit/modules/observer/observer.spec.js b/test/unit/modules/observer/observer.spec.js index 5f075bccc95..1b367c73ce3 100644 --- a/test/unit/modules/observer/observer.spec.js +++ b/test/unit/modules/observer/observer.spec.js @@ -189,9 +189,9 @@ describe('Observer', () => { update: jasmine.createSpy() } // collect dep - Dep.target = watcher + Dep.target.storage = watcher obj.a.b - Dep.target = null + Dep.target.storage = null expect(watcher.deps.length).toBe(3) // obj.a + a + a.b obj.a.b = 3 expect(watcher.update.calls.count()).toBe(1) @@ -200,10 +200,10 @@ describe('Observer', () => { expect(watcher.update.calls.count()).toBe(2) watcher.deps = [] - Dep.target = watcher + Dep.target.storage = watcher obj.a.b obj.c - Dep.target = null + Dep.target.storage = null expect(watcher.deps.length).toBe(4) // set on the swapped object obj.a.b = 5 @@ -236,9 +236,9 @@ describe('Observer', () => { update: jasmine.createSpy() } // collect dep - Dep.target = watcher + Dep.target.storage = watcher expect(obj.a).toBe(2) // Make sure 'this' is preserved - Dep.target = null + Dep.target.storage = null obj.a = 3 expect(obj.val).toBe(3) // make sure 'setter' was called obj.val = 5