Skip to content

Commit

Permalink
fix(guards): run beforeRouteEnter with app context (#2117)
Browse files Browse the repository at this point in the history
Fix #2051
  • Loading branch information
yozi-developer committed Jan 29, 2024
1 parent c3fa9c1 commit 6a69696
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 11 deletions.
88 changes: 88 additions & 0 deletions packages/router/__tests__/guards/navigatioGuardsInjections.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,92 @@ describe('inject() within navigation guards', () => {
await router.isReady()
})
}

describe('in-component guards', () => {
it('beforeRouteEnter', async () => {
expect.assertions(1)
const router = createRouter({
routes: [
{
path: '/',
component: {
template: `<div>Page</div>`,
beforeRouteEnter() {
expect(inject('test')).toBe('hello')
},
},
},
],
})
factory(router)
await router.isReady()
await router.push('/')
})

it('beforeRouteEnter + lazy load', async () => {
expect.assertions(1)
const router = createRouter({
routes: [
{
path: '/',
component: () =>
new Promise(r =>
r({
template: `<div>Page</div>`,
beforeRouteEnter() {
expect(inject('test')).toBe('hello')
},
})
),
},
],
})
factory(router)
await router.isReady()
await router.push('/')
})

it('beforeRouteUpdate', async () => {
expect.assertions(1)
const router = createRouter({
routes: [
{
path: '/',
component: {
template: `<div>Page</div>`,
beforeRouteUpdate() {
expect(inject('test')).toBe('hello')
},
},
},
],
})
factory(router)
await router.isReady()
await router.push('/')
await router.push('/#other')
})

it('beforeRouteLeave', async () => {
expect.assertions(1)
const router = createRouter({
routes: [
{ path: '/', component: PageComponent },
{
path: '/foo',
component: {
template: `<div>Page</div>`,
beforeRouteLeave() {
expect(inject('test')).toBe('hello')
},
},
},
],
})
factory(router)
await router.isReady()
await router.push('/foo')
await router.push('/')
})
})
})
31 changes: 21 additions & 10 deletions packages/router/src/navigationGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,16 @@ export function guardToPromiseFn(
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded,
record: RouteRecordNormalized,
name: string
name: string,
runWithContext: <T>(fn: () => T) => T
): () => Promise<void>
export function guardToPromiseFn(
guard: NavigationGuard,
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded,
record?: RouteRecordNormalized,
name?: string
name?: string,
runWithContext: <T>(fn: () => T) => T = fn => fn()
): () => Promise<void> {
// keep a reference to the enterCallbackArray to prevent pushing callbacks if a new navigation took place
const enterCallbackArray =
Expand Down Expand Up @@ -173,11 +175,13 @@ export function guardToPromiseFn(
}

// wrapping with Promise.resolve allows it to work with both async and sync guards
const guardReturn = guard.call(
record && record.instances[name!],
to,
from,
__DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
const guardReturn = runWithContext(() =>
guard.call(
record && record.instances[name!],
to,
from,
__DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
)
)
let guardCall = Promise.resolve(guardReturn)

Expand Down Expand Up @@ -231,7 +235,8 @@ export function extractComponentsGuards(
matched: RouteRecordNormalized[],
guardType: GuardType,
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded
from: RouteLocationNormalizedLoaded,
runWithContext: <T>(fn: () => T) => T = fn => fn()
) {
const guards: Array<() => Promise<void>> = []

Expand Down Expand Up @@ -292,7 +297,10 @@ export function extractComponentsGuards(
const options: ComponentOptions =
(rawComponent as any).__vccOpts || rawComponent
const guard = options[guardType]
guard && guards.push(guardToPromiseFn(guard, to, from, record, name))
guard &&
guards.push(
guardToPromiseFn(guard, to, from, record, name, runWithContext)
)
} else {
// start requesting the chunk already
let componentPromise: Promise<
Expand Down Expand Up @@ -324,7 +332,10 @@ export function extractComponentsGuards(
const options: ComponentOptions =
(resolvedComponent as any).__vccOpts || resolvedComponent
const guard = options[guardType]
return guard && guardToPromiseFn(guard, to, from, record, name)()
return (
guard &&
guardToPromiseFn(guard, to, from, record, name, runWithContext)()
)
})
)
}
Expand Down
3 changes: 2 additions & 1 deletion packages/router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,8 @@ export function createRouter(options: RouterOptions): Router {
enteringRecords,
'beforeRouteEnter',
to,
from
from,
runWithContext
)
guards.push(canceledNavigationCheck)

Expand Down

0 comments on commit 6a69696

Please sign in to comment.