From 582efeaa929a580749db3a0a06b6249f94534c3f Mon Sep 17 00:00:00 2001 From: AchillesJ Date: Mon, 3 Apr 2017 11:37:54 +0800 Subject: [PATCH] handle errors thrown by directive hooks (#5314) (#5324) * handle errors thrown by directive hooks * fix import --- src/core/vdom/modules/directives.js | 8 ++++++-- test/unit/features/error-handling.spec.js | 25 ++++++++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/core/vdom/modules/directives.js b/src/core/vdom/modules/directives.js index f08ab359128..db35c3543f0 100644 --- a/src/core/vdom/modules/directives.js +++ b/src/core/vdom/modules/directives.js @@ -1,7 +1,7 @@ /* @flow */ import { emptyNode } from 'core/vdom/patch' -import { resolveAsset } from 'core/util/options' +import { resolveAsset, handleError } from 'core/util/index' import { mergeVNodeHook } from 'core/vdom/helpers/index' export default { @@ -107,6 +107,10 @@ function getRawDirName (dir: VNodeDirective): string { function callHook (dir, hook, vnode, oldVnode, isDestroy) { const fn = dir.def && dir.def[hook] if (fn) { - fn(vnode.elm, dir, vnode, oldVnode, isDestroy) + try { + fn(vnode.elm, dir, vnode, oldVnode, isDestroy) + } catch (e) { + handleError(e, vnode.context, `directive ${dir.name} ${hook} hook`) + } } } diff --git a/test/unit/features/error-handling.spec.js b/test/unit/features/error-handling.spec.js index f2e5c076961..4dc6080f982 100644 --- a/test/unit/features/error-handling.spec.js +++ b/test/unit/features/error-handling.spec.js @@ -11,7 +11,8 @@ describe('Error handling', () => { ['render', 'render function'], ['beforeCreate', 'beforeCreate hook'], ['created', 'created hook'], - ['beforeMount', 'beforeMount hook'] + ['beforeMount', 'beforeMount hook'], + ['directive bind', 'directive foo bind hook'] ].forEach(([type, description]) => { it(`should recover from errors in ${type}`, done => { const vm = createTestInstance(components[type]) @@ -32,7 +33,8 @@ describe('Error handling', () => { // error in beforeUpdate/updated should affect neither child nor parent ;[ ['beforeUpdate', 'beforeUpdate hook'], - ['updated', 'updated hook'] + ['updated', 'updated hook'], + ['directive update', 'directive foo update hook'] ].forEach(([type, description]) => { it(`should recover from errors in ${type} hook`, done => { const vm = createTestInstance(components[type]) @@ -45,7 +47,8 @@ describe('Error handling', () => { ;[ ['beforeDestroy', 'beforeDestroy hook'], - ['destroyed', 'destroyed hook'] + ['destroyed', 'destroyed hook'], + ['directive unbind', 'directive foo unbind hook'] ].forEach(([type, description]) => { it(`should recover from errors in ${type} hook`, done => { const vm = createTestInstance(components[type]) @@ -173,6 +176,22 @@ function createErrorTestComponents () { } }) + // directive hooks errors + ;['bind', 'update', 'unbind'].forEach(hook => { + const key = 'directive ' + hook + const dirComp = components[key] = { + props: ['n'], + template: `
{{ n }}
` + } + const dirFoo = {} + dirFoo[hook] = function () { + throw new Error(key) + } + dirComp.directives = { + foo: dirFoo + } + }) + // user watcher components.userWatcherGetter = { props: ['n'],