Skip to content

Commit bd15fd3

Browse files
committed
chore: add back navigation info to guards
1 parent eac6b63 commit bd15fd3

File tree

5 files changed

+69
-36
lines changed

5 files changed

+69
-36
lines changed

packages/router/src/history/common.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ export interface NavigationInformation {
4848
type: NavigationType
4949
direction: NavigationDirection
5050
delta: number
51+
/**
52+
* True if the navigation was triggered by the browser back button.
53+
*/
54+
isBackBrowserButton?: boolean
55+
/**
56+
* True if the navigation was triggered by the browser forward button.
57+
*/
58+
isForwardBrowserButton?: boolean
5159
}
5260

5361
export interface NavigationCallback {

packages/router/src/navigation-api/index.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,14 @@ export function createNavigationApiRouter(options: RouterApiOptions): Router {
142142
leavingRecords.reverse(),
143143
'beforeRouteLeave',
144144
to,
145-
from
145+
from,
146+
navigationInfo
146147
)
147148

148149
// leavingRecords is already reversed
149150
for (const record of leavingRecords) {
150151
record.leaveGuards.forEach(guard => {
151-
guards.push(guardToPromiseFn(guard, to, from))
152+
guards.push(guardToPromiseFn(guard, to, from, { info: navigationInfo }))
152153
})
153154
}
154155

@@ -162,7 +163,7 @@ export function createNavigationApiRouter(options: RouterApiOptions): Router {
162163
// check global guards beforeEach
163164
guards = []
164165
for (const guard of beforeGuards.list()) {
165-
guards.push(guardToPromiseFn(guard, to, from))
166+
guards.push(guardToPromiseFn(guard, to, from, { info: navigationInfo }))
166167
}
167168
guards.push(canceledNavigationCheck)
168169
await runGuardQueue(guards)
@@ -172,7 +173,8 @@ export function createNavigationApiRouter(options: RouterApiOptions): Router {
172173
updatingRecords,
173174
'beforeRouteUpdate',
174175
to,
175-
from
176+
from,
177+
navigationInfo
176178
)
177179
guards.push(canceledNavigationCheck)
178180
await runGuardQueue(guards)
@@ -183,9 +185,15 @@ export function createNavigationApiRouter(options: RouterApiOptions): Router {
183185
if (record.beforeEnter) {
184186
if (isArray(record.beforeEnter)) {
185187
for (const beforeEnter of record.beforeEnter)
186-
guards.push(guardToPromiseFn(beforeEnter, to, from))
188+
guards.push(
189+
guardToPromiseFn(beforeEnter, to, from, { info: navigationInfo })
190+
)
187191
} else {
188-
guards.push(guardToPromiseFn(record.beforeEnter, to, from))
192+
guards.push(
193+
guardToPromiseFn(record.beforeEnter, to, from, {
194+
info: navigationInfo,
195+
})
196+
)
189197
}
190198
}
191199
}
@@ -202,6 +210,7 @@ export function createNavigationApiRouter(options: RouterApiOptions): Router {
202210
'beforeRouteEnter',
203211
to,
204212
from,
213+
navigationInfo,
205214
runWithContext
206215
)
207216
guards.push(canceledNavigationCheck)
@@ -210,7 +219,7 @@ export function createNavigationApiRouter(options: RouterApiOptions): Router {
210219
// check global guards beforeResolve
211220
guards = []
212221
for (const guard of beforeResolveGuards.list()) {
213-
guards.push(guardToPromiseFn(guard, to, from))
222+
guards.push(guardToPromiseFn(guard, to, from, { info: navigationInfo }))
214223
}
215224
guards.push(canceledNavigationCheck)
216225
await runGuardQueue(guards)
@@ -634,9 +643,9 @@ export function createNavigationApiRouter(options: RouterApiOptions): Router {
634643
delta > 0
635644
? NavigationDirection.forward
636645
: NavigationDirection.back,
637-
delta /*,
646+
delta,
638647
isBackBrowserButton: delta < 0,
639-
isForwardBrowserButton: delta > 0*/,
648+
isForwardBrowserButton: delta > 0,
640649
}
641650
} else if (
642651
event.navigationType === 'push' ||
@@ -711,9 +720,9 @@ export function createNavigationApiRouter(options: RouterApiOptions): Router {
711720
type: NavigationType.pop,
712721
direction:
713722
delta > 0 ? NavigationDirection.forward : NavigationDirection.back,
714-
delta /*,
723+
delta,
715724
isBackBrowserButton: delta < 0,
716-
isForwardBrowserButton: delta > 0*/,
725+
isForwardBrowserButton: delta > 0,
717726
}
718727

719728
pendingLocation = to

packages/router/src/navigationGuards.ts

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { matchedRouteKey } from './injectionSymbols'
2222
import { RouteRecordNormalized } from './matcher/types'
2323
import { isESModule, isRouteComponent } from './utils'
2424
import { warn } from './warning'
25+
import { NavigationInformation } from './history/common'
2526

2627
function registerGuard(
2728
record: RouteRecordNormalized,
@@ -106,27 +107,21 @@ export function onBeforeRouteUpdate(updateGuard: NavigationGuard) {
106107
registerGuard(activeRecord, 'updateGuards', updateGuard)
107108
}
108109

109-
export function guardToPromiseFn(
110-
guard: NavigationGuard,
111-
to: RouteLocationNormalized,
112-
from: RouteLocationNormalizedLoaded
113-
): () => Promise<void>
114-
export function guardToPromiseFn(
115-
guard: NavigationGuard,
116-
to: RouteLocationNormalized,
117-
from: RouteLocationNormalizedLoaded,
118-
record: RouteRecordNormalized,
119-
name: string,
120-
runWithContext: <T>(fn: () => T) => T
121-
): () => Promise<void>
110+
interface GuardToPromiseFnOptions {
111+
record?: RouteRecordNormalized
112+
name?: string
113+
runWithContext?: <T>(fn: () => T) => T
114+
info?: NavigationInformation
115+
}
116+
122117
export function guardToPromiseFn(
123118
guard: NavigationGuard,
124119
to: RouteLocationNormalized,
125120
from: RouteLocationNormalizedLoaded,
126-
record?: RouteRecordNormalized,
127-
name?: string,
128-
runWithContext: <T>(fn: () => T) => T = fn => fn()
121+
options: GuardToPromiseFnOptions = {}
129122
): () => Promise<void> {
123+
const { record, name, runWithContext = fn => fn(), info } = options
124+
130125
// keep a reference to the enterCallbackArray to prevent pushing callbacks if a new navigation took place
131126
const enterCallbackArray =
132127
record &&
@@ -179,7 +174,7 @@ export function guardToPromiseFn(
179174
record && record.instances[name!],
180175
to,
181176
from,
182-
__DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
177+
__DEV__ ? canOnlyBeCalledOnce(next, to, from, info) : next
183178
)
184179
)
185180
let guardCall = Promise.resolve(guardReturn)
@@ -214,14 +209,19 @@ export function guardToPromiseFn(
214209
function canOnlyBeCalledOnce(
215210
next: NavigationGuardNext,
216211
to: RouteLocationNormalized,
217-
from: RouteLocationNormalized
212+
from: RouteLocationNormalized,
213+
info?: NavigationInformation
218214
): NavigationGuardNext {
219215
let called = 0
220216
return function () {
221-
if (called++ === 1)
217+
if (called++ === 1) {
218+
const showInfo = info
219+
? ` (type=${info.type},direction=${info.direction},delta=${info.delta},back=${info.isBackBrowserButton === true},forward=${info.isForwardBrowserButton === true})`
220+
: ''
222221
warn(
223-
`The "next" callback was called more than once in one navigation guard when going from "${from.fullPath}" to "${to.fullPath}". It should be called exactly one time in each navigation guard. This will fail in production.`
222+
`The "next" callback was called more than once in one navigation guard when going from "${from.fullPath}" to "${to.fullPath}${showInfo}". It should be called exactly one time in each navigation guard. This will fail in production.`
224223
)
224+
}
225225
// @ts-expect-error: we put it in the original one because it's easier to check
226226
next._called = true
227227
if (called === 1) next.apply(null, arguments as any)
@@ -235,6 +235,7 @@ export function extractComponentsGuards(
235235
guardType: GuardType,
236236
to: RouteLocationNormalized,
237237
from: RouteLocationNormalizedLoaded,
238+
info?: NavigationInformation,
238239
runWithContext: <T>(fn: () => T) => T = fn => fn()
239240
) {
240241
const guards: Array<() => Promise<void>> = []
@@ -298,7 +299,12 @@ export function extractComponentsGuards(
298299
const guard = options[guardType]
299300
guard &&
300301
guards.push(
301-
guardToPromiseFn(guard, to, from, record, name, runWithContext)
302+
guardToPromiseFn(guard, to, from, {
303+
record,
304+
name,
305+
runWithContext,
306+
info,
307+
})
302308
)
303309
} else {
304310
// start requesting the chunk already
@@ -334,7 +340,12 @@ export function extractComponentsGuards(
334340

335341
return (
336342
guard &&
337-
guardToPromiseFn(guard, to, from, record, name, runWithContext)()
343+
guardToPromiseFn(guard, to, from, {
344+
record,
345+
name,
346+
runWithContext,
347+
info,
348+
})()
338349
)
339350
})
340351
)

packages/router/src/router.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,7 @@ export function createRouter(options: RouterOptions): Router {
923923
'beforeRouteEnter',
924924
to,
925925
from,
926+
undefined,
926927
runWithContext
927928
)
928929
guards.push(canceledNavigationCheck)

packages/router/src/typed-routes/navigation-guards.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
} from './route-location'
77
import type { TypesConfig } from '../config'
88
import type { NavigationFailure } from '../errors'
9+
import type { NavigationInformation } from '../history/common'
910
import { ComponentPublicInstance } from 'vue'
1011

1112
/**
@@ -25,7 +26,8 @@ export interface NavigationGuardWithThis<T> {
2526
to: RouteLocationNormalized,
2627
from: RouteLocationNormalizedLoaded,
2728
// intentionally not typed to make people use the return
28-
next: NavigationGuardNext
29+
next: NavigationGuardNext,
30+
info?: NavigationInformation
2931
): _Awaitable<NavigationGuardReturn>
3032
}
3133

@@ -41,7 +43,8 @@ export interface _NavigationGuardResolved {
4143
to: RouteLocationNormalizedLoaded,
4244
from: RouteLocationNormalizedLoaded,
4345
// intentionally not typed to make people use the return
44-
next: NavigationGuardNext
46+
next: NavigationGuardNext,
47+
info?: NavigationInformation
4548
): _Awaitable<NavigationGuardReturn>
4649
}
4750

@@ -53,7 +56,8 @@ export interface NavigationGuard {
5356
to: RouteLocationNormalized,
5457
from: RouteLocationNormalizedLoaded,
5558
// intentionally not typed to make people use the return
56-
next: NavigationGuardNext
59+
next: NavigationGuardNext,
60+
info?: NavigationInformation
5761
): _Awaitable<NavigationGuardReturn>
5862
}
5963

0 commit comments

Comments
 (0)