Skip to content

Commit 6a69696

Browse files
fix(guards): run beforeRouteEnter with app context (#2117)
Fix #2051
1 parent c3fa9c1 commit 6a69696

File tree

3 files changed

+111
-11
lines changed

3 files changed

+111
-11
lines changed

packages/router/__tests__/guards/navigatioGuardsInjections.spec.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,92 @@ describe('inject() within navigation guards', () => {
4848
await router.isReady()
4949
})
5050
}
51+
52+
describe('in-component guards', () => {
53+
it('beforeRouteEnter', async () => {
54+
expect.assertions(1)
55+
const router = createRouter({
56+
routes: [
57+
{
58+
path: '/',
59+
component: {
60+
template: `<div>Page</div>`,
61+
beforeRouteEnter() {
62+
expect(inject('test')).toBe('hello')
63+
},
64+
},
65+
},
66+
],
67+
})
68+
factory(router)
69+
await router.isReady()
70+
await router.push('/')
71+
})
72+
73+
it('beforeRouteEnter + lazy load', async () => {
74+
expect.assertions(1)
75+
const router = createRouter({
76+
routes: [
77+
{
78+
path: '/',
79+
component: () =>
80+
new Promise(r =>
81+
r({
82+
template: `<div>Page</div>`,
83+
beforeRouteEnter() {
84+
expect(inject('test')).toBe('hello')
85+
},
86+
})
87+
),
88+
},
89+
],
90+
})
91+
factory(router)
92+
await router.isReady()
93+
await router.push('/')
94+
})
95+
96+
it('beforeRouteUpdate', async () => {
97+
expect.assertions(1)
98+
const router = createRouter({
99+
routes: [
100+
{
101+
path: '/',
102+
component: {
103+
template: `<div>Page</div>`,
104+
beforeRouteUpdate() {
105+
expect(inject('test')).toBe('hello')
106+
},
107+
},
108+
},
109+
],
110+
})
111+
factory(router)
112+
await router.isReady()
113+
await router.push('/')
114+
await router.push('/#other')
115+
})
116+
117+
it('beforeRouteLeave', async () => {
118+
expect.assertions(1)
119+
const router = createRouter({
120+
routes: [
121+
{ path: '/', component: PageComponent },
122+
{
123+
path: '/foo',
124+
component: {
125+
template: `<div>Page</div>`,
126+
beforeRouteLeave() {
127+
expect(inject('test')).toBe('hello')
128+
},
129+
},
130+
},
131+
],
132+
})
133+
factory(router)
134+
await router.isReady()
135+
await router.push('/foo')
136+
await router.push('/')
137+
})
138+
})
51139
})

packages/router/src/navigationGuards.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,16 @@ export function guardToPromiseFn(
117117
to: RouteLocationNormalized,
118118
from: RouteLocationNormalizedLoaded,
119119
record: RouteRecordNormalized,
120-
name: string
120+
name: string,
121+
runWithContext: <T>(fn: () => T) => T
121122
): () => Promise<void>
122123
export function guardToPromiseFn(
123124
guard: NavigationGuard,
124125
to: RouteLocationNormalized,
125126
from: RouteLocationNormalizedLoaded,
126127
record?: RouteRecordNormalized,
127-
name?: string
128+
name?: string,
129+
runWithContext: <T>(fn: () => T) => T = fn => fn()
128130
): () => Promise<void> {
129131
// keep a reference to the enterCallbackArray to prevent pushing callbacks if a new navigation took place
130132
const enterCallbackArray =
@@ -173,11 +175,13 @@ export function guardToPromiseFn(
173175
}
174176

175177
// wrapping with Promise.resolve allows it to work with both async and sync guards
176-
const guardReturn = guard.call(
177-
record && record.instances[name!],
178-
to,
179-
from,
180-
__DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
178+
const guardReturn = runWithContext(() =>
179+
guard.call(
180+
record && record.instances[name!],
181+
to,
182+
from,
183+
__DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
184+
)
181185
)
182186
let guardCall = Promise.resolve(guardReturn)
183187

@@ -231,7 +235,8 @@ export function extractComponentsGuards(
231235
matched: RouteRecordNormalized[],
232236
guardType: GuardType,
233237
to: RouteLocationNormalized,
234-
from: RouteLocationNormalizedLoaded
238+
from: RouteLocationNormalizedLoaded,
239+
runWithContext: <T>(fn: () => T) => T = fn => fn()
235240
) {
236241
const guards: Array<() => Promise<void>> = []
237242

@@ -292,7 +297,10 @@ export function extractComponentsGuards(
292297
const options: ComponentOptions =
293298
(rawComponent as any).__vccOpts || rawComponent
294299
const guard = options[guardType]
295-
guard && guards.push(guardToPromiseFn(guard, to, from, record, name))
300+
guard &&
301+
guards.push(
302+
guardToPromiseFn(guard, to, from, record, name, runWithContext)
303+
)
296304
} else {
297305
// start requesting the chunk already
298306
let componentPromise: Promise<
@@ -324,7 +332,10 @@ export function extractComponentsGuards(
324332
const options: ComponentOptions =
325333
(resolvedComponent as any).__vccOpts || resolvedComponent
326334
const guard = options[guardType]
327-
return guard && guardToPromiseFn(guard, to, from, record, name)()
335+
return (
336+
guard &&
337+
guardToPromiseFn(guard, to, from, record, name, runWithContext)()
338+
)
328339
})
329340
)
330341
}

packages/router/src/router.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,8 @@ export function createRouter(options: RouterOptions): Router {
879879
enteringRecords,
880880
'beforeRouteEnter',
881881
to,
882-
from
882+
from,
883+
runWithContext
883884
)
884885
guards.push(canceledNavigationCheck)
885886

0 commit comments

Comments
 (0)