Skip to content

Commit

Permalink
feat(warn): warn against infinite redirections
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Aug 6, 2020
1 parent 3896f15 commit e3dcc8d
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
20 changes: 20 additions & 0 deletions __tests__/warnings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
})
3 changes: 0 additions & 3 deletions src/navigationGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
)
Expand Down
29 changes: 27 additions & 2 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,17 +490,42 @@ 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), {
state: data,
force,
replace,
}),
// preserve the original redirectedFrom if any
redirectedFrom || toLocation
)
}
} else {
// if we fail we don't finalize the navigation
failure = finalizeNavigation(
Expand Down

0 comments on commit e3dcc8d

Please sign in to comment.