Browse Source

handle errors in nextTick (close #5277)

Evan You 9 years ago
parent
commit
4b6913cb46
2 changed files with 30 additions and 3 deletions
  1. 11 3
      src/core/util/env.js
  2. 19 0
      test/unit/features/error-handling.spec.js

+ 11 - 3
src/core/util/env.js

@@ -2,6 +2,7 @@
 /* globals MutationObserver */
 
 import { noop } from 'shared/util'
+import { handleError } from './error'
 
 // can we use __proto__?
 export const hasProto = '__proto__' in {}
@@ -123,15 +124,22 @@ export const nextTick = (function () {
   return function queueNextTick (cb?: Function, ctx?: Object) {
     let _resolve
     callbacks.push(() => {
-      if (cb) cb.call(ctx)
-      if (_resolve) _resolve(ctx)
+      if (cb) {
+        try {
+          cb.call(ctx)
+        } catch (e) {
+          handleError(e, ctx, 'nextTick')
+        }
+      } else if (_resolve) {
+        _resolve(ctx)
+      }
     })
     if (!pending) {
       pending = true
       timerFunc()
     }
     if (!cb && typeof Promise !== 'undefined') {
-      return new Promise(resolve => {
+      return new Promise((resolve, reject) => {
         _resolve = resolve
       })
     }

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

@@ -106,6 +106,25 @@ describe('Error handling', () => {
     }).then(done)
   })
 
+  it('should capture and recover from nextTick errors', done => {
+    const err1 = new Error('nextTick')
+    const err2 = new Error('nextTick2')
+    const spy = Vue.config.errorHandler = jasmine.createSpy('errorHandler')
+    Vue.nextTick(() => { throw err1 })
+    Vue.nextTick(() => {
+      expect(spy).toHaveBeenCalledWith(err1, undefined, 'nextTick')
+
+      const vm = new Vue()
+      vm.$nextTick(() => { throw err2 })
+      Vue.nextTick(() => {
+        // should be called with correct instance info
+        expect(spy).toHaveBeenCalledWith(err2, vm, 'nextTick')
+        Vue.config.errorHandler = null
+        done()
+      })
+    })
+  })
+
   it('properly format component names', () => {
     const vm = new Vue()
     expect(formatComponentName(vm)).toBe('<Root>')