From 1c30d93e60ef058579ca7fa9e2d689a080ea96fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Fontcuberta?= Date: Fri, 30 Nov 2018 00:14:28 +0100 Subject: [PATCH] fix(error handling): handle errors on immediate watcher execution (#8581) The handle callback call should be wrapped in a try/catch that explicitly calls handleError fix #8567 --- src/core/instance/state.js | 6 +++++- test/unit/features/error-handling.spec.js | 25 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/core/instance/state.js b/src/core/instance/state.js index f70f7d1366..50311b2f61 100644 --- a/src/core/instance/state.js +++ b/src/core/instance/state.js @@ -351,7 +351,11 @@ export function stateMixin (Vue: Class) { options.user = true const watcher = new Watcher(vm, expOrFn, cb, options) if (options.immediate) { - cb.call(vm, watcher.value) + try { + cb.call(vm, watcher.value) + } catch (error) { + handleError(error, vm, `callback for immediate watcher "${watcher.expression}"`) + } } return function unwatchFn () { watcher.teardown() diff --git a/test/unit/features/error-handling.spec.js b/test/unit/features/error-handling.spec.js index 77ac0b928b..713c91a766 100644 --- a/test/unit/features/error-handling.spec.js +++ b/test/unit/features/error-handling.spec.js @@ -92,6 +92,16 @@ describe('Error handling', () => { }).then(done) }) + it('should recover from errors in user immediate watcher callback', done => { + const vm = createTestInstance(components.userImmediateWatcherCallback) + waitForUpdate(() => { + expect(`Error in callback for immediate watcher "n"`).toHaveBeenWarned() + expect(`Error: userImmediateWatcherCallback error`).toHaveBeenWarned() + }).thenWaitFor(next => { + assertBothInstancesActive(vm).end(next) + }).then(done) + }) + it('config.errorHandler should capture render errors', done => { const spy = Vue.config.errorHandler = jasmine.createSpy('errorHandler') const vm = createTestInstance(components.render) @@ -234,6 +244,21 @@ function createErrorTestComponents () { } } + components.userImmediateWatcherCallback = { + props: ['n'], + watch: { + n: { + immediate: true, + handler () { + throw new Error('userImmediateWatcherCallback error') + } + } + }, + render (h) { + return h('div', this.n) + } + } + // event errors components.event = { beforeCreate () {