From 74c632fab3359e2338f783665a32b064ae7d5101 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 14 Mar 2019 15:25:01 +0800 Subject: [PATCH] fix: should not swallow user catch on rejected promise in methods fix #9694 --- src/core/util/error.js | 7 ++++--- .../{invoke-with-error-handling.spec.js => error.spec.js} | 7 +++++-- 2 files changed, 9 insertions(+), 5 deletions(-) rename test/unit/modules/util/{invoke-with-error-handling.spec.js => error.spec.js} (74%) diff --git a/src/core/util/error.js b/src/core/util/error.js index 8b8b9014ddb..4dbdbc7443d 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 c958203ccec..c9152bbb7bc 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() }) })