From 95d44c8ff2a961e052fd67b2160b87fb32d0ffb4 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 24 Nov 2020 23:25:27 +0100 Subject: [PATCH] fix(guards): correctly reuse guards (#616) Fix #614 --- __tests__/matcher/records.spec.ts | 12 ++++++------ e2e/guards-instances/index.ts | 8 ++++++-- e2e/specs/guards-instances.js | 2 +- src/RouterView.ts | 2 +- src/matcher/index.ts | 4 ++-- src/matcher/types.ts | 4 ++-- src/navigationGuards.ts | 18 ++++++++++-------- src/router.ts | 8 ++++---- 8 files changed, 32 insertions(+), 26 deletions(-) diff --git a/__tests__/matcher/records.spec.ts b/__tests__/matcher/records.spec.ts index 3ff0aa4b..698edcdf 100644 --- a/__tests__/matcher/records.spec.ts +++ b/__tests__/matcher/records.spec.ts @@ -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', diff --git a/e2e/guards-instances/index.ts b/e2e/guards-instances/index.ts index 205efd8e..b2e1f719 100644 --- a/e2e/guards-instances/index.ts +++ b/e2e/guards-instances/index.ts @@ -47,6 +47,7 @@ const state = reactive({ */ function createTestComponent(key: string) { return defineComponent({ + name: key, template: `
{{ key }} @@ -196,12 +197,12 @@ leaves: {{ state.leave }} @@ -232,4 +233,7 @@ leaves: {{ state.leave }} app.use(router) +// @ts-ignore +window.r = router + app.mount('#app') diff --git a/e2e/specs/guards-instances.js b/e2e/specs/guards-instances.js index 6b9db9ca..ec78066e 100644 --- a/e2e/specs/guards-instances.js +++ b/e2e/specs/guards-instances.js @@ -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') diff --git a/src/RouterView.ts b/src/RouterView.ts index ddb0def3..86fff50b 100644 --- a/src/RouterView.ts +++ b/src/RouterView.ts @@ -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 } diff --git a/src/matcher/index.ts b/src/matcher/index.ts index 6f1eda95..dd5aa024 100644 --- a/src/matcher/index.ts +++ b/src/matcher/index.ts @@ -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 diff --git a/src/matcher/types.ts b/src/matcher/types.ts index c6526073..bd06a206 100644 --- a/src/matcher/types.ts +++ b/src/matcher/types.ts @@ -49,13 +49,13 @@ export interface RouteRecordNormalized { * * @internal */ - leaveGuards: NavigationGuard[] + leaveGuards: Set /** * Registered update guards * * @internal */ - updateGuards: NavigationGuard[] + updateGuards: Set /** * Registered beforeRouteEnter callbacks passed to `next` or returned in guards * diff --git a/src/navigationGuards.ts b/src/navigationGuards.ts index 41046282..7db4d4c7 100644 --- a/src/navigationGuards.ts +++ b/src/navigationGuards.ts @@ -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( diff --git a/src/router.ts b/src/router.ts index f760df14..7aa5490f 100644 --- a/src/router.ts +++ b/src/router.ts @@ -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) -- 2.39.5