Просмотр исходного кода

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
Adrià Fontcuberta 7 лет назад
Родитель
Сommit
2686818beb
2 измененных файлов с 30 добавлено и 1 удалено
  1. 5 1
      src/core/instance/state.js
  2. 25 0
      test/unit/features/error-handling.spec.js

+ 5 - 1
src/core/instance/state.js

@@ -351,7 +351,11 @@ export function stateMixin (Vue: Class<Component>) {
     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()

+ 25 - 0
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 () {