]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(guards): correctly reuse guards (#616)
authorEduardo San Martin Morote <posva@users.noreply.github.com>
Tue, 24 Nov 2020 22:25:27 +0000 (23:25 +0100)
committerGitHub <noreply@github.com>
Tue, 24 Nov 2020 22:25:27 +0000 (23:25 +0100)
Fix #614

__tests__/matcher/records.spec.ts
e2e/guards-instances/index.ts
e2e/specs/guards-instances.js
src/RouterView.ts
src/matcher/index.ts
src/matcher/types.ts
src/navigationGuards.ts
src/router.ts

index 3ff0aa4bd72354f296021857ff7a91359eb39390..698edcdfb9597552cfbd11e63f20aa458b4e1a97 100644 (file)
@@ -11,8 +11,8 @@ describe('normalizeRouteRecord', () => {
       children: [],
       aliasOf: undefined,
       components: { default: {} },
-      leaveGuards: [],
-      updateGuards: [],
+      leaveGuards: expect.any(Set),
+      updateGuards: expect.any(Set),
       instances: {},
       meta: {},
       name: undefined,
@@ -35,8 +35,8 @@ describe('normalizeRouteRecord', () => {
       beforeEnter,
       children: [{ path: '/child' }],
       components: { default: {} },
-      leaveGuards: [],
-      updateGuards: [],
+      leaveGuards: expect.any(Set),
+      updateGuards: expect.any(Set),
       instances: {},
       meta: { foo: true },
       name: 'name',
@@ -77,8 +77,8 @@ describe('normalizeRouteRecord', () => {
       beforeEnter,
       children: [{ path: '/child' }],
       components: { one: {} },
-      leaveGuards: [],
-      updateGuards: [],
+      leaveGuards: expect.any(Set),
+      updateGuards: expect.any(Set),
       instances: {},
       meta: { foo: true },
       name: 'name',
index 205efd8e5dc7943b231e5c6dd632a862c371fe25..b2e1f7194c5792f51ecdefbbb9af3e59cbe4afa0 100644 (file)
@@ -47,6 +47,7 @@ const state = reactive({
  */
 function createTestComponent(key: string) {
   return defineComponent({
+    name: key,
     template: `
     <div :id="key">
     {{ key }}
@@ -196,12 +197,12 @@ leaves: {{ state.leave }}
         </router-view>
       </template>
       <template v-else-if="testCase === 'keyed'">
-        <router-view :key="$route.query.foo" class="view" />
+        <router-view :key="$route.query.foo || undefined" class="view" />
       </template>
       <template v-else-if="testCase === 'keepalivekeyed'">
         <router-view v-slot="{ Component }" >
           <keep-alive>
-            <component :is="Component" :key="$route.query.foo" class="view" />
+            <component :is="Component" :key="$route.query.foo || undefined" class="view" />
           </keep-alive>
         </router-view>
       </template>
@@ -232,4 +233,7 @@ leaves: {{ state.leave }}
 
 app.use(router)
 
+// @ts-ignore
+window.r = router
+
 app.mount('#app')
index 6b9db9ca7a311b8e4b9a70dfc74d96aa715e1018..ec78066eccc8c3cb78a6d90a04f8e465807dfa17 100644 (file)
@@ -158,7 +158,7 @@ module.exports = {
       .expect.element('#logs')
       .text.to.equal(
         [
-          // lol
+          // to force new lines formatting
           `${name}: update /f/2 - /f/2`,
           `${name}: setup:update /f/2 - /f/2`,
         ].join('\n')
index ddb0def371f8d90ea2021ff71f36637cee4b04e8..86fff50bdabbeef05b92bb3b3b361a65c711eec4 100644 (file)
@@ -69,7 +69,7 @@ export const RouterViewImpl = /*#__PURE__*/ defineComponent({
           to.instances[name] = instance
           // the component instance is reused for a different route or name so
           // we copy any saved update or leave guards
-          if (from && instance === oldInstance) {
+          if (from && from !== to && instance && instance === oldInstance) {
             to.leaveGuards = from.leaveGuards
             to.updateGuards = from.updateGuards
           }
index 6f1eda95983bd89e2baac3ea2ba9407e1cbed221..dd5aa0246da6fac64f86f0af932c6434a9750a88 100644 (file)
@@ -342,8 +342,8 @@ export function normalizeRouteRecord(
     props: normalizeRecordProps(record),
     children: record.children || [],
     instances: {},
-    leaveGuards: [],
-    updateGuards: [],
+    leaveGuards: new Set(),
+    updateGuards: new Set(),
     enterCallbacks: {},
     components:
       'components' in record
index c6526073380eedc77267d4e3bd527a08d1032cbb..bd06a206808e5df9724074c2a886f108e53d4f09 100644 (file)
@@ -49,13 +49,13 @@ export interface RouteRecordNormalized {
    *
    * @internal
    */
-  leaveGuards: NavigationGuard[]
+  leaveGuards: Set<NavigationGuard>
   /**
    * Registered update guards
    *
    * @internal
    */
-  updateGuards: NavigationGuard[]
+  updateGuards: Set<NavigationGuard>
   /**
    * Registered beforeRouteEnter callbacks passed to `next` or returned in guards
    *
index 410462823c9b016eb9c08b0dca139783ba34f3ef..7db4d4c721b08f1d374b54afdf241a455eeac02a 100644 (file)
@@ -24,21 +24,23 @@ import { RouteRecordNormalized } from './matcher/types'
 import { isESModule } from './utils'
 import { warn } from './warning'
 
-function registerGuard(list: NavigationGuard[], guard: NavigationGuard) {
+function registerGuard(
+  record: RouteRecordNormalized,
+  name: 'leaveGuards' | 'updateGuards',
+  guard: NavigationGuard
+) {
   const removeFromList = () => {
-    const index = list.indexOf(guard)
-    if (index > -1) list.splice(index, 1)
+    record[name].delete(guard)
   }
 
   onUnmounted(removeFromList)
   onDeactivated(removeFromList)
 
   onActivated(() => {
-    const index = list.indexOf(guard)
-    if (index < 0) list.push(guard)
+    record[name].add(guard)
   })
 
-  list.push(guard)
+  record[name].add(guard)
 }
 
 /**
@@ -65,7 +67,7 @@ export function onBeforeRouteLeave(leaveGuard: NavigationGuard) {
     return
   }
 
-  registerGuard(activeRecord.leaveGuards, leaveGuard)
+  registerGuard(activeRecord, 'leaveGuards', leaveGuard)
 }
 
 /**
@@ -92,7 +94,7 @@ export function onBeforeRouteUpdate(updateGuard: NavigationGuard) {
     return
   }
 
-  registerGuard(activeRecord.updateGuards, updateGuard)
+  registerGuard(activeRecord, 'updateGuards', updateGuard)
 }
 
 export function guardToPromiseFn(
index f760df144df6659c6a920e785fcc0efb1e11032c..7aa5490fcb3242123289e0b8823d278d43996e78 100644 (file)
@@ -728,9 +728,9 @@ export function createRouter(options: RouterOptions): Router {
 
     // leavingRecords is already reversed
     for (const record of leavingRecords) {
-      for (const guard of record.leaveGuards) {
+      record.leaveGuards.forEach(guard => {
         guards.push(guardToPromiseFn(guard, to, from))
-      }
+      })
     }
 
     const canceledNavigationCheck = checkCanceledNavigationAndReject.bind(
@@ -764,9 +764,9 @@ export function createRouter(options: RouterOptions): Router {
           )
 
           for (const record of updatingRecords) {
-            for (const guard of record.updateGuards) {
+            record.updateGuards.forEach(guard => {
               guards.push(guardToPromiseFn(guard, to, from))
-            }
+            })
           }
           guards.push(canceledNavigationCheck)