From 987f322b8f419cc307f4294173f8792a706ed73f Mon Sep 17 00:00:00 2001 From: Ben Delaney Date: Tue, 30 Mar 2021 20:46:12 +1100 Subject: [PATCH] fix: pause dep collection during immediate watcher invocation (#11943) Co-authored-by: Eduardo San Martin Morote --- src/core/instance/state.js | 2 ++ .../instance/methods-lifecycle.spec.js | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/core/instance/state.js b/src/core/instance/state.js index cc1401a3353..67f9dae381d 100644 --- a/src/core/instance/state.js +++ b/src/core/instance/state.js @@ -355,11 +355,13 @@ export function stateMixin (Vue: Class) { options.user = true const watcher = new Watcher(vm, expOrFn, cb, options) if (options.immediate) { + pushTarget() try { cb.call(vm, watcher.value) } catch (error) { handleError(error, vm, `callback for immediate watcher "${watcher.expression}"`) } + popTarget() } return function unwatchFn () { watcher.teardown() diff --git a/test/unit/features/instance/methods-lifecycle.spec.js b/test/unit/features/instance/methods-lifecycle.spec.js index 1e424a5c9be..a2c5b86e920 100644 --- a/test/unit/features/instance/methods-lifecycle.spec.js +++ b/test/unit/features/instance/methods-lifecycle.spec.js @@ -53,6 +53,38 @@ describe('Instance methods lifecycle', () => { } }).$mount() }) + + it('Dep.target should be undefined during invocation of child immediate watcher', done => { + let calls = 0 + const childData = { a: 1 } + const parentUpdate = jasmine.createSpy() + new Vue({ + template: '
', + updated: parentUpdate, + components: { + myComponent: { + template: '
{{ a }}
', + data() { + return childData + }, + watch: { + anything: { + handler() { + ++calls + this.a + }, + immediate: true + } + } + } + } + }).$mount() + expect(calls).toBe(1) + childData.a++ + waitForUpdate(() => { + expect(parentUpdate).not.toHaveBeenCalled() + }).then(done) + }) }) describe('$destroy', () => {