diff --git a/src/core/util/error.js b/src/core/util/error.js index 8b8b9014..4dbdbc74 100644 --- a/src/core/util/error.js +++ b/src/core/util/error.js @@ -43,10 +43,11 @@ export function invokeWithErrorHandling ( let res try { res = args ? handler.apply(context, args) : handler.call(context) - if (res && !res._isVue && isPromise(res)) { + if (res && !res._isVue && isPromise(res) && !res._handled) { + res.catch(e => handleError(e, vm, info + ` (Promise/async)`)) // issue #9511 - // reassign to res to avoid catch triggering multiple times when nested calls - res = res.catch(e => handleError(e, vm, info + ` (Promise/async)`)) + // avoid catch triggering multiple times when nested calls + res._handled = true } } catch (e) { handleError(e, vm, info) diff --git a/test/unit/modules/util/invoke-with-error-handling.spec.js b/test/unit/modules/util/error.spec.js similarity index 74% rename from test/unit/modules/util/invoke-with-error-handling.spec.js rename to test/unit/modules/util/error.spec.js index c958203c..c9152bbb 100644 --- a/test/unit/modules/util/invoke-with-error-handling.spec.js +++ b/test/unit/modules/util/error.spec.js @@ -6,14 +6,17 @@ describe('invokeWithErrorHandling', () => { it('should errorHandler call once when nested calls return rejected promise', done => { const originalHandler = Vue.config.errorHandler const handler = Vue.config.errorHandler = jasmine.createSpy() + const userCatch = jasmine.createSpy() + const err = new Error('fake error') invokeWithErrorHandling(() => { return invokeWithErrorHandling(() => { - return Promise.reject(new Error('fake error')) + return Promise.reject(err) }) - }).then(() => { + }).catch(userCatch).then(() => { Vue.config.errorHandler = originalHandler expect(handler.calls.count()).toBe(1) + expect(userCatch).toHaveBeenCalledWith(err) done() }) })