Преглед изворни кода

handle errors thrown by directive hooks (#5314) (#5324)

* handle errors thrown by directive hooks

* fix import
AchillesJ пре 9 година
родитељ
комит
3c0265517b
2 измењених фајлова са 28 додато и 5 уклоњено
  1. 6 2
      src/core/vdom/modules/directives.js
  2. 22 3
      test/unit/features/error-handling.spec.js

+ 6 - 2
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`)
+    }
   }
 }

+ 22 - 3
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: `<div v-foo="n">{{ n }}</div>`
+    }
+    const dirFoo = {}
+    dirFoo[hook] = function () {
+      throw new Error(key)
+    }
+    dirComp.directives = {
+      foo: dirFoo
+    }
+  })
+
   // user watcher
   components.userWatcherGetter = {
     props: ['n'],