Przeglądaj źródła

fix: handle errors in errorHandler

close #6714
Evan You 8 lat temu
rodzic
commit
2b5c83af6d
2 zmienionych plików z 37 dodań i 11 usunięć
  1. 18 10
      src/core/util/error.js
  2. 19 1
      test/unit/features/error-handling.spec.js

+ 18 - 10
src/core/util/error.js

@@ -6,16 +6,24 @@ import { inBrowser } from './env'
 
 
 export function handleError (err: Error, vm: any, info: string) {
 export function handleError (err: Error, vm: any, info: string) {
   if (config.errorHandler) {
   if (config.errorHandler) {
-    config.errorHandler.call(null, err, vm, info)
-  } else {
-    if (process.env.NODE_ENV !== 'production') {
-      warn(`Error in ${info}: "${err.toString()}"`, vm)
-    }
-    /* istanbul ignore else */
-    if (inBrowser && typeof console !== 'undefined') {
-      console.error(err)
-    } else {
-      throw err
+    try {
+      config.errorHandler.call(null, err, vm, info)
+      return
+    } catch (e) {
+      logError(e, null, 'errorHandler')
     }
     }
   }
   }
+  logError(err, vm, info)
+}
+
+function logError (err, vm, info) {
+  if (process.env.NODE_ENV !== 'production') {
+    warn(`Error in ${info}: "${err.toString()}"`, vm)
+  }
+  /* istanbul ignore else */
+  if (inBrowser && typeof console !== 'undefined') {
+    console.error(err)
+  } else {
+    throw err
+  }
 }
 }

+ 19 - 1
test/unit/features/error-handling.spec.js

@@ -92,7 +92,7 @@ describe('Error handling', () => {
     }).then(done)
     }).then(done)
   })
   })
 
 
-  it('config.errorHandler should capture errors', done => {
+  it('config.errorHandler should capture render errors', done => {
     const spy = Vue.config.errorHandler = jasmine.createSpy('errorHandler')
     const spy = Vue.config.errorHandler = jasmine.createSpy('errorHandler')
     const vm = createTestInstance(components.render)
     const vm = createTestInstance(components.render)
 
 
@@ -124,6 +124,24 @@ describe('Error handling', () => {
       })
       })
     })
     })
   })
   })
+
+  it('should recover from errors thrown in errorHandler itself', () => {
+    Vue.config.errorHandler = () => {
+      throw new Error('error in errorHandler ¯\\_(ツ)_/¯')
+    }
+    const vm = new Vue({
+      render (h) {
+        throw new Error('error in render')
+      },
+      renderError (h, err) {
+        return h('div', err.toString())
+      }
+    }).$mount()
+    expect('error in errorHandler').toHaveBeenWarned()
+    expect('error in render').toHaveBeenWarned()
+    expect(vm.$el.textContent).toContain('error in render')
+    Vue.config.errorHandler = null
+  })
 })
 })
 
 
 function createErrorTestComponents () {
 function createErrorTestComponents () {