]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(guards): preserve navigation options when redirecting
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 20 Apr 2020 21:28:00 +0000 (23:28 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 20 Apr 2020 21:28:00 +0000 (23:28 +0200)
__tests__/router.spec.ts
src/components/View.ts
src/index.ts
src/router.ts
src/types/index.ts

index c3c41b78cef3dd9b8e9152c852df3ce4fd558f29..67375a35c0146dc9a58f063e39cf9121c05c1af7 100644 (file)
@@ -119,6 +119,25 @@ describe('Router', () => {
     )
   })
 
+  it('replaces if a guard redirects', async () => {
+    const history = createMemoryHistory()
+    const { router } = await newRouter({ history })
+    // move somewhere else
+    await router.push('/search')
+    jest.spyOn(history, 'replace')
+    await router.replace('/home-before')
+    expect(history.replace).toHaveBeenCalledTimes(1)
+    expect(history.replace).toHaveBeenCalledWith(
+      expect.objectContaining({
+        fullPath: '/',
+        path: '/',
+        query: {},
+        hash: '',
+      }),
+      undefined
+    )
+  })
+
   it('allows to customize parseQuery', async () => {
     const parseQuery = jest.fn()
     const { router } = await newRouter({ parseQuery })
index 9c2134e4f0a4628d87825b6539e74ef49ab10f3a..addf04ea8b43a9f16299de020856f1378e93afba 100644 (file)
@@ -67,10 +67,11 @@ export const View = (defineComponent({
       // we nee the value at the time we render because when we unmount, we
       // navigated to a different location so the value is different
       const currentMatched = matchedRoute.value
+      const currentName = props.name
       function onVnodeUnmounted() {
         if (currentMatched) {
           // remove the instance reference to prevent leak
-          currentMatched.instances[props.name] = null
+          currentMatched.instances[currentName] = null
         }
       }
 
index 8098ba7ad3c7be6ab53c63ecb74a30a1c1275b2e..38b92cc3f477d2c580e878c1ee7b5178cc6f1fa8 100644 (file)
@@ -16,6 +16,7 @@ export { RouteRecord, RouteRecordNormalized } from './matcher/types'
 
 export {
   RouteLocationRaw,
+  RouteLocation,
   RouteLocationNormalized,
   RouteLocationNormalizedLoaded,
   START_LOCATION_NORMALIZED as START_LOCATION,
index a4c6092594f7ee5f8b7432291be24dac23f6a2fe..269a4c62435cc0954e174d2c4e89553ccdfd6a4a 100644 (file)
@@ -13,6 +13,7 @@ import {
   RouteRecordName,
   isRouteName,
   NavigationGuardWithThis,
+  RouteLocationOptions,
 } from './types'
 import { RouterHistory, HistoryState } from './history/common'
 import {
@@ -249,9 +250,10 @@ export function createRouter({
   ): Promise<NavigationFailure | void> {
     const targetLocation: RouteLocation = (pendingLocation = resolve(to))
     const from = currentRoute.value
-    const data: HistoryState | undefined = (to as any).state
-    const force: boolean | undefined = (to as any).force
-    const replace: boolean | undefined = (to as any).replace === true
+    const data: HistoryState | undefined = (to as RouteLocationOptions).state
+    const force: boolean | undefined = (to as RouteLocationOptions).force
+    // to could be a string where `replace` is a function
+    const replace = (to as RouteLocationOptions).replace === true
 
     if (!force && isSameRouteLocation(from, targetLocation)) return
 
@@ -294,7 +296,13 @@ export function createRouter({
       } else if (error.type === ErrorTypes.NAVIGATION_GUARD_REDIRECT) {
         // preserve the original redirectedFrom if any
         return pushWithRedirect(
-          (error as NavigationRedirectError).to,
+          // keep options
+          {
+            ...locationAsObject((error as NavigationRedirectError).to),
+            state: data,
+            force,
+            replace,
+          },
           redirectedFrom || toLocation
         )
       } else {
@@ -503,6 +511,7 @@ export function createRouter({
         return pushWithRedirect(
           (error as NavigationRedirectError).to,
           toLocation
+          // TODO: in dev show warning, in prod noop, same as initial navigation
         ).catch(() => {})
       } else {
         // TODO: test on different browsers ensure consistent behavior
index 0b1a6d2b4ff46680194747e74ee7ad7687d8082f..f2b7631cb56ade8a4fa147f708c1a5410d2efa28 100644 (file)
@@ -1,6 +1,6 @@
 import { LocationQuery, LocationQueryRaw } from '../utils/query'
 import { PathParserOptions } from '../matcher/path-parser-ranker'
-import { markRaw, Ref, ComputedRef, Component } from 'vue'
+import { markRaw, Ref, ComputedRef, ComponentOptions } from 'vue'
 import { RouteRecord, RouteRecordNormalized } from '../matcher/types'
 import { HistoryState } from '../history/common'
 
@@ -128,7 +128,7 @@ export interface RouteLocationNormalized extends _RouteLocationBase {
   matched: RouteRecordNormalized[] // non-enumerable
 }
 
-export type RouteComponent = Component
+export type RouteComponent = ComponentOptions
 export type RawRouteComponent = RouteComponent | Lazy<RouteComponent>
 
 export type RouteRecordName = string | symbol