From: Eduardo San Martin Morote Date: Thu, 6 Aug 2020 14:10:10 +0000 (+0200) Subject: feat(warn): warn against infinite redirections X-Git-Tag: v4.0.0-beta.7~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e3dcc8d9477e17f9b92e22787b750edc4658b77a;p=thirdparty%2Fvuejs%2Frouter.git feat(warn): warn against infinite redirections --- diff --git a/__tests__/warnings.spec.ts b/__tests__/warnings.spec.ts index 61b4026d..5cba0f90 100644 --- a/__tests__/warnings.spec.ts +++ b/__tests__/warnings.spec.ts @@ -187,4 +187,24 @@ describe('warnings', () => { await expect(router.push({ path: '/foo2' })).resolves.toBe(undefined) expect(`No match found for location with path "/foo2"`).toHaveBeenWarned() }) + + it('warns if next is called with the same location too many times', async () => { + let router = createRouter({ + history: createMemoryHistory(), + routes: [ + { path: '/', name: 'a', component }, + { path: '/b', component }, + ], + }) + + router.beforeEach(to => { + if (to.path === '/b') return '/b' + return + }) + + await router.push('/b').catch(() => {}) + expect( + 'Detected an infinite redirection in a navigation guard when going from "/" to "/b"' + ).toHaveBeenWarned() + }) }) diff --git a/src/navigationGuards.ts b/src/navigationGuards.ts index 1eebe39c..4093e189 100644 --- a/src/navigationGuards.ts +++ b/src/navigationGuards.ts @@ -157,9 +157,6 @@ export function guardToPromiseFn( record && record.instances[name!], to, from, - // TODO: could wrap in dev to check if the guard returns before - // calling next with 3 or more arguments. This would help people - // forgetting to remove the `next` argument __DEV__ ? canOnlyBeCalledOnce(next, to, from) : next ) ) diff --git a/src/router.ts b/src/router.ts index f10f04a6..9850dd8e 100644 --- a/src/router.ts +++ b/src/router.ts @@ -490,8 +490,31 @@ export function createRouter(options: RouterOptions): Router { if (failure) { if ( isNavigationFailure(failure, ErrorTypes.NAVIGATION_GUARD_REDIRECT) - ) - // preserve the original redirectedFrom if any + ) { + if ( + __DEV__ && + // we are redirecting to the same location we were already at + isSameRouteLocation( + stringifyQuery, + resolve(failure.to), + toLocation + ) && + // and we have done it a couple of times + redirectedFrom && + // @ts-ignore + (redirectedFrom._count = redirectedFrom._count + ? // @ts-ignore + redirectedFrom._count + 1 + : 1) > 10 + ) { + warn( + `Detected an infinite redirection in a navigation guard when going from "${from.fullPath}" to "${toLocation.fullPath}". Aborting to avoid a Stack Overflow. This will break in production if not fixed.` + ) + return Promise.reject( + new Error('Infinite redirect in navigation guard') + ) + } + return pushWithRedirect( // keep options assign(locationAsObject(failure.to), { @@ -499,8 +522,10 @@ export function createRouter(options: RouterOptions): Router { force, replace, }), + // preserve the original redirectedFrom if any redirectedFrom || toLocation ) + } } else { // if we fail we don't finalize the navigation failure = finalizeNavigation(