]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat(warn): warn against infinite redirections
authorEduardo San Martin Morote <posva13@gmail.com>
Thu, 6 Aug 2020 14:10:10 +0000 (16:10 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Thu, 6 Aug 2020 14:10:10 +0000 (16:10 +0200)
__tests__/warnings.spec.ts
src/navigationGuards.ts
src/router.ts

index 61b4026d6135dadc2f35f7b68288b610b66e5bc1..5cba0f90fd05f1aeebc26de642effe285e3e7618 100644 (file)
@@ -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()
+  })
 })
index 1eebe39c117277e95f5501491af72e59b55f0839..4093e189cc76bea2eeebb2c5db046da94c06da4e 100644 (file)
@@ -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
         )
       )
index f10f04a6fe8bc5d42aea918ec676c6dfdc1b8d1a..9850dd8eaced217b0fdd4a5695ae38306f93cdb2 100644 (file)
@@ -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(