From e07d4b9239ed79248c269c38d77dcb416f52e0b4 Mon Sep 17 00:00:00 2001 From: Raul Cabello Date: Wed, 1 Jul 2020 17:48:51 +0200 Subject: [PATCH 1/3] feat(errors): capture errors thrown in redirect callback in onError Resolves #3201 --- src/history/base.js | 77 ++++++++++++++------------ test/unit/specs/error-handling.spec.js | 29 ++++++++++ 2 files changed, 72 insertions(+), 34 deletions(-) diff --git a/src/history/base.js b/src/history/base.js index 4bfa0722b..5e54f739c 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -77,46 +77,55 @@ export class History { onComplete?: Function, onAbort?: Function ) { - const route = this.router.match(location, this.current) - this.confirmTransition( - route, - () => { - const prev = this.current - this.updateRoute(route) - onComplete && onComplete(route) - this.ensureURL() - this.router.afterHooks.forEach(hook => { - hook && hook(route, prev) - }) - - // fire ready cbs once - if (!this.ready) { - this.ready = true - this.readyCbs.forEach(cb => { - cb(route) + try { + const route = this.router.match(location, this.current) + this.confirmTransition( + route, + () => { + const prev = this.current + this.updateRoute(route) + onComplete && onComplete(route) + this.ensureURL() + this.router.afterHooks.forEach(hook => { + hook && hook(route, prev) }) - } - }, - err => { - if (onAbort) { - onAbort(err) - } - if (err && !this.ready) { - this.ready = true - // Initial redirection should still trigger the onReady onSuccess - // https://github.com/vuejs/vue-router/issues/3225 - if (!isRouterError(err, NavigationFailureType.redirected)) { - this.readyErrorCbs.forEach(cb => { - cb(err) - }) - } else { + + // fire ready cbs once + if (!this.ready) { + this.ready = true this.readyCbs.forEach(cb => { cb(route) }) } + }, + err => { + if (onAbort) { + onAbort(err) + } + if (err && !this.ready) { + this.ready = true + // Initial redirection should still trigger the onReady onSuccess + // https://github.com/vuejs/vue-router/issues/3225 + if (!isRouterError(err, NavigationFailureType.redirected)) { + this.readyErrorCbs.forEach(cb => { + cb(err) + }) + } else { + this.readyCbs.forEach(cb => { + cb(route) + }) + } + } } - } - ) + ) + } catch (e) { + this.errorCbs.forEach(cb => { + cb(e) + }) + // Exception should still be thrown + // https://github.com/vuejs/vue-router/issues/3201 + throw e + } } confirmTransition (route: Route, onComplete: Function, onAbort?: Function) { diff --git a/test/unit/specs/error-handling.spec.js b/test/unit/specs/error-handling.spec.js index d0d6f6e1d..d8784aa5e 100644 --- a/test/unit/specs/error-handling.spec.js +++ b/test/unit/specs/error-handling.spec.js @@ -183,4 +183,33 @@ describe('error handling', () => { done() }) }) + + it('should trigger onError when an exception is thrown', done => { + const config = [{ + path: '/oldpath/:part', + redirect: (to) => { + if (to.ooopsmistake.part) { + return `/newpath/${to.params.part}` + } + return '/newpath/' + } + }] + + const router = new VueRouter({ + routes: config + }) + + const onError = jasmine.createSpy('onError') + router.onError(onError) + const pushCatch = jasmine.createSpy('pushCatch') + + router + .push('/oldpath/test') + .catch(pushCatch) + .finally(() => { + expect(pushCatch).toHaveBeenCalled() + expect(onError).toHaveBeenCalled() + done() + }) + }) }) From b1f86fcff63b8d431fabf82edf31a41c376460d3 Mon Sep 17 00:00:00 2001 From: Raul Cabello Date: Fri, 3 Jul 2020 17:03:46 +0200 Subject: [PATCH 2/3] feat(errors): capture errors thrown in redirect callback in onError try catch just router.match Resolves #3201 --- src/history/base.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/history/base.js b/src/history/base.js index 5e54f739c..d8935a6e1 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -77,8 +77,18 @@ export class History { onComplete?: Function, onAbort?: Function ) { + let route try { - const route = this.router.match(location, this.current) + route = this.router.match(location, this.current) + } catch (e) { + this.errorCbs.forEach(cb => { + cb(e) + }) + // Exception should still be thrown + // https://github.com/vuejs/vue-router/issues/3201 + throw e + } + if (route) { this.confirmTransition( route, () => { @@ -118,13 +128,6 @@ export class History { } } ) - } catch (e) { - this.errorCbs.forEach(cb => { - cb(e) - }) - // Exception should still be thrown - // https://github.com/vuejs/vue-router/issues/3201 - throw e } } From 6ad2353402e5b8d1e93ccb113e70529a5d22ec44 Mon Sep 17 00:00:00 2001 From: Raul Cabello Date: Fri, 3 Jul 2020 20:38:46 +0200 Subject: [PATCH 3/3] feat(errors): capture errors thrown in redirect callback in onError remove unnecessary if Resolves #3201 --- src/history/base.js | 68 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/src/history/base.js b/src/history/base.js index d8935a6e1..a070f27c6 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -88,47 +88,45 @@ export class History { // https://github.com/vuejs/vue-router/issues/3201 throw e } - if (route) { - this.confirmTransition( - route, - () => { - const prev = this.current - this.updateRoute(route) - onComplete && onComplete(route) - this.ensureURL() - this.router.afterHooks.forEach(hook => { - hook && hook(route, prev) - }) + this.confirmTransition( + route, + () => { + const prev = this.current + this.updateRoute(route) + onComplete && onComplete(route) + this.ensureURL() + this.router.afterHooks.forEach(hook => { + hook && hook(route, prev) + }) - // fire ready cbs once - if (!this.ready) { - this.ready = true + // fire ready cbs once + if (!this.ready) { + this.ready = true + this.readyCbs.forEach(cb => { + cb(route) + }) + } + }, + err => { + if (onAbort) { + onAbort(err) + } + if (err && !this.ready) { + this.ready = true + // Initial redirection should still trigger the onReady onSuccess + // https://github.com/vuejs/vue-router/issues/3225 + if (!isRouterError(err, NavigationFailureType.redirected)) { + this.readyErrorCbs.forEach(cb => { + cb(err) + }) + } else { this.readyCbs.forEach(cb => { cb(route) }) } - }, - err => { - if (onAbort) { - onAbort(err) - } - if (err && !this.ready) { - this.ready = true - // Initial redirection should still trigger the onReady onSuccess - // https://github.com/vuejs/vue-router/issues/3225 - if (!isRouterError(err, NavigationFailureType.redirected)) { - this.readyErrorCbs.forEach(cb => { - cb(err) - }) - } else { - this.readyCbs.forEach(cb => { - cb(route) - }) - } - } } - ) - } + } + ) } confirmTransition (route: Route, onComplete: Function, onAbort?: Function) {