From b15a874e72978fa19ad1a1b45c0bbc9543a47969 Mon Sep 17 00:00:00 2001 From: Ben Delaney Date: Mon, 8 Mar 2021 03:43:29 +1100 Subject: [PATCH 1/6] fix: pause dep collection during immediate watcher invocation (#11942) --- src/core/instance/state.js | 2 ++ 1 file changed, 2 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() From 6434e7c07aef4ad05c950a94c97cadbc281c0c1e Mon Sep 17 00:00:00 2001 From: Ben Delaney Date: Mon, 8 Mar 2021 22:41:52 +1100 Subject: [PATCH 2/6] test: child immediate watcher Dep.target (#11943) --- .../instance/methods-lifecycle.spec.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/unit/features/instance/methods-lifecycle.spec.js b/test/unit/features/instance/methods-lifecycle.spec.js index 1e424a5c9be..5a43e9e31a0 100644 --- a/test/unit/features/instance/methods-lifecycle.spec.js +++ b/test/unit/features/instance/methods-lifecycle.spec.js @@ -53,6 +53,31 @@ describe('Instance methods lifecycle', () => { } }).$mount() }) + + it('Dep.target should be undefined during invocation of child immediate watcher', () => { + let calls = 0; + new Vue({ + template: '
', + components: { + myComponent: { + template: '
hi
', + data() { + return { a: 123 } + }, + watch: { + a: { + handler() { + ++calls + expect(Dep.target).toBe(undefined) + }, + immediate: true + } + } + } + } + }).$mount() + expect(calls).toBe(1) + }) }) describe('$destroy', () => { From f434182464caefc342d547742972e6975eead00a Mon Sep 17 00:00:00 2001 From: Ben Delaney Date: Wed, 10 Mar 2021 04:03:26 +1100 Subject: [PATCH 3/6] chore: update child immediate watcher test case (#11943) --- .../features/instance/methods-lifecycle.spec.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/unit/features/instance/methods-lifecycle.spec.js b/test/unit/features/instance/methods-lifecycle.spec.js index 5a43e9e31a0..d465b962063 100644 --- a/test/unit/features/instance/methods-lifecycle.spec.js +++ b/test/unit/features/instance/methods-lifecycle.spec.js @@ -54,15 +54,17 @@ describe('Instance methods lifecycle', () => { }).$mount() }) - it('Dep.target should be undefined during invocation of child immediate watcher', () => { - let calls = 0; + it('Dep.target should be undefined during invocation of child immediate watcher', done => { + let calls = 0, childData + const parentUpdate = jasmine.createSpy() new Vue({ template: '
', + updated: parentUpdate, components: { myComponent: { - template: '
hi
', + template: '
{{ a }}
', data() { - return { a: 123 } + return childData = { a: 123 } }, watch: { a: { @@ -77,6 +79,10 @@ describe('Instance methods lifecycle', () => { } }).$mount() expect(calls).toBe(1) + childData.a++ + waitForUpdate(() => { + expect(parentUpdate.calls.count()).toBe(0) + }).then(done) }) }) From 52522baf1a34994b1a4d3fb270fdc3c55e5209f5 Mon Sep 17 00:00:00 2001 From: Ben Delaney Date: Wed, 10 Mar 2021 23:45:58 +1100 Subject: [PATCH 4/6] Update test/unit/features/instance/methods-lifecycle.spec.js Co-authored-by: Eduardo San Martin Morote --- test/unit/features/instance/methods-lifecycle.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/features/instance/methods-lifecycle.spec.js b/test/unit/features/instance/methods-lifecycle.spec.js index d465b962063..3708e65fb1a 100644 --- a/test/unit/features/instance/methods-lifecycle.spec.js +++ b/test/unit/features/instance/methods-lifecycle.spec.js @@ -81,7 +81,7 @@ describe('Instance methods lifecycle', () => { expect(calls).toBe(1) childData.a++ waitForUpdate(() => { - expect(parentUpdate.calls.count()).toBe(0) + expect(parentUpdate).not.toHaveBeenCalled() }).then(done) }) }) From 18d3f63063ed872049de5c749006c285b9fd2309 Mon Sep 17 00:00:00 2001 From: Ben Delaney Date: Thu, 11 Mar 2021 03:40:36 +1100 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: Eduardo San Martin Morote --- test/unit/features/instance/methods-lifecycle.spec.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/unit/features/instance/methods-lifecycle.spec.js b/test/unit/features/instance/methods-lifecycle.spec.js index 3708e65fb1a..077d7f41a31 100644 --- a/test/unit/features/instance/methods-lifecycle.spec.js +++ b/test/unit/features/instance/methods-lifecycle.spec.js @@ -55,7 +55,8 @@ describe('Instance methods lifecycle', () => { }) it('Dep.target should be undefined during invocation of child immediate watcher', done => { - let calls = 0, childData + let calls = 0 + const childData = { a: 1 } const parentUpdate = jasmine.createSpy() new Vue({ template: '
', @@ -64,10 +65,10 @@ describe('Instance methods lifecycle', () => { myComponent: { template: '
{{ a }}
', data() { - return childData = { a: 123 } + return childData }, watch: { - a: { + anything: { handler() { ++calls expect(Dep.target).toBe(undefined) From ca5eb901cd1a7b094cec18c50c7e686e4fbe7849 Mon Sep 17 00:00:00 2001 From: Ben Delaney Date: Thu, 11 Mar 2021 03:50:04 +1100 Subject: [PATCH 6/6] chore: apply suggestions from code review --- test/unit/features/instance/methods-lifecycle.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/features/instance/methods-lifecycle.spec.js b/test/unit/features/instance/methods-lifecycle.spec.js index 077d7f41a31..a2c5b86e920 100644 --- a/test/unit/features/instance/methods-lifecycle.spec.js +++ b/test/unit/features/instance/methods-lifecycle.spec.js @@ -71,7 +71,7 @@ describe('Instance methods lifecycle', () => { anything: { handler() { ++calls - expect(Dep.target).toBe(undefined) + this.a }, immediate: true }