@tanstack/router-core 1.151.6 → 1.153.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/location.d.cts +27 -0
- package/dist/cjs/router.cjs +212 -81
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +32 -5
- package/dist/cjs/scroll-restoration.cjs +2 -2
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/location.d.ts +27 -0
- package/dist/esm/router.d.ts +32 -5
- package/dist/esm/router.js +212 -81
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.js +2 -2
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +5 -1
- package/src/location.ts +35 -0
- package/src/router.ts +331 -93
- package/src/scroll-restoration.ts +2 -2
package/dist/esm/router.js
CHANGED
|
@@ -47,7 +47,6 @@ class RouterCore {
|
|
|
47
47
|
this.tempLocationKey = `${Math.round(
|
|
48
48
|
Math.random() * 1e7
|
|
49
49
|
)}`;
|
|
50
|
-
this.resetNextScroll = true;
|
|
51
50
|
this.shouldViewTransition = void 0;
|
|
52
51
|
this.isViewTransitionTypesSupported = void 0;
|
|
53
52
|
this.subscribers = /* @__PURE__ */ new Set();
|
|
@@ -213,7 +212,7 @@ class RouterCore {
|
|
|
213
212
|
pathname: decodePath(url.pathname),
|
|
214
213
|
searchStr,
|
|
215
214
|
search: replaceEqualDeep(previousLocation?.search, parsedSearch),
|
|
216
|
-
hash: url.hash.split("#").reverse()[0] ?? "",
|
|
215
|
+
hash: decodePath(url.hash.split("#").reverse()[0] ?? ""),
|
|
217
216
|
state: replaceEqualDeep(previousLocation?.state, state)
|
|
218
217
|
};
|
|
219
218
|
};
|
|
@@ -315,9 +314,13 @@ class RouterCore {
|
|
|
315
314
|
path: nextTo,
|
|
316
315
|
params: nextParams
|
|
317
316
|
}).interpolatedPath;
|
|
318
|
-
const
|
|
317
|
+
const destMatches = this.matchRoutes(interpolatedNextTo, void 0, {
|
|
319
318
|
_buildLocation: true
|
|
320
|
-
})
|
|
319
|
+
});
|
|
320
|
+
const destRoutes = destMatches.map(
|
|
321
|
+
(d) => this.looseRoutesById[d.routeId]
|
|
322
|
+
);
|
|
323
|
+
const globalNotFoundMatch = destMatches.find((m) => m.globalNotFound);
|
|
321
324
|
if (Object.keys(nextParams).length > 0) {
|
|
322
325
|
for (const route of destRoutes) {
|
|
323
326
|
const fn = route.options.params?.stringify ?? route.options.stringifyParams;
|
|
@@ -368,19 +371,27 @@ class RouterCore {
|
|
|
368
371
|
const hashStr = hash ? `#${hash}` : "";
|
|
369
372
|
let nextState = dest.state === true ? currentLocation.state : dest.state ? functionalUpdate(dest.state, currentLocation.state) : {};
|
|
370
373
|
nextState = replaceEqualDeep(currentLocation.state, nextState);
|
|
374
|
+
const matchSnapshot = buildMatchSnapshotFromRoutes({
|
|
375
|
+
routes: destRoutes,
|
|
376
|
+
params: nextParams,
|
|
377
|
+
searchStr,
|
|
378
|
+
globalNotFoundRouteId: globalNotFoundMatch?.routeId
|
|
379
|
+
});
|
|
371
380
|
const fullPath = `${nextPathname}${searchStr}${hashStr}`;
|
|
372
381
|
const url = new URL(fullPath, this.origin);
|
|
373
382
|
const rewrittenUrl = executeRewriteOutput(this.rewrite, url);
|
|
383
|
+
const encodedHref = url.href.replace(url.origin, "");
|
|
374
384
|
return {
|
|
375
385
|
publicHref: rewrittenUrl.pathname + rewrittenUrl.search + rewrittenUrl.hash,
|
|
376
|
-
href:
|
|
386
|
+
href: encodedHref,
|
|
377
387
|
url: rewrittenUrl,
|
|
378
388
|
pathname: nextPathname,
|
|
379
389
|
search: nextSearch,
|
|
380
390
|
searchStr,
|
|
381
391
|
state: nextState,
|
|
382
392
|
hash: hash ?? "",
|
|
383
|
-
unmaskOnReload: dest.unmaskOnReload
|
|
393
|
+
unmaskOnReload: dest.unmaskOnReload,
|
|
394
|
+
_matchSnapshot: matchSnapshot
|
|
384
395
|
};
|
|
385
396
|
};
|
|
386
397
|
const buildWithMatches = (dest = {}, maskedDest) => {
|
|
@@ -423,7 +434,7 @@ class RouterCore {
|
|
|
423
434
|
}
|
|
424
435
|
return buildWithMatches(opts);
|
|
425
436
|
};
|
|
426
|
-
this.commitLocation = ({
|
|
437
|
+
this.commitLocation = async ({
|
|
427
438
|
viewTransition,
|
|
428
439
|
ignoreBlocker,
|
|
429
440
|
...next
|
|
@@ -452,53 +463,73 @@ class RouterCore {
|
|
|
452
463
|
});
|
|
453
464
|
if (isSameUrl && isSameState()) {
|
|
454
465
|
this.load();
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
466
|
+
return this.commitLocationPromise;
|
|
467
|
+
}
|
|
468
|
+
let {
|
|
469
|
+
// eslint-disable-next-line prefer-const
|
|
470
|
+
maskedLocation,
|
|
471
|
+
// eslint-disable-next-line prefer-const
|
|
472
|
+
hashScrollIntoView,
|
|
473
|
+
// don't pass url into history since it is a URL instance that cannot be serialized
|
|
474
|
+
// eslint-disable-next-line prefer-const
|
|
475
|
+
url: _url,
|
|
476
|
+
...nextHistory
|
|
477
|
+
} = next;
|
|
478
|
+
if (maskedLocation) {
|
|
479
|
+
nextHistory = {
|
|
480
|
+
...maskedLocation,
|
|
481
|
+
state: {
|
|
482
|
+
...maskedLocation.state,
|
|
483
|
+
__tempKey: void 0,
|
|
484
|
+
__tempLocation: {
|
|
485
|
+
...nextHistory,
|
|
486
|
+
search: nextHistory.searchStr,
|
|
487
|
+
state: {
|
|
488
|
+
...nextHistory.state,
|
|
489
|
+
__tempKey: void 0,
|
|
490
|
+
__tempLocation: void 0,
|
|
491
|
+
__TSR_key: void 0,
|
|
492
|
+
key: void 0
|
|
493
|
+
// TODO: Remove in v2 - use __TSR_key instead
|
|
483
494
|
}
|
|
484
495
|
}
|
|
485
|
-
};
|
|
486
|
-
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
487
|
-
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
488
496
|
}
|
|
497
|
+
};
|
|
498
|
+
if (nextHistory.unmaskOnReload ?? this.options.unmaskOnReload ?? false) {
|
|
499
|
+
nextHistory.state.__tempKey = this.tempLocationKey;
|
|
489
500
|
}
|
|
490
|
-
nextHistory.state.__hashScrollIntoViewOptions = hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true;
|
|
491
|
-
this.shouldViewTransition = viewTransition;
|
|
492
|
-
this.history[next.replace ? "replace" : "push"](
|
|
493
|
-
nextHistory.publicHref,
|
|
494
|
-
nextHistory.state,
|
|
495
|
-
{ ignoreBlocker }
|
|
496
|
-
);
|
|
497
501
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
502
|
+
nextHistory.state.__hashScrollIntoViewOptions = hashScrollIntoView ?? this.options.defaultHashScrollIntoView ?? true;
|
|
503
|
+
nextHistory.state.__TSR_resetScroll = next.resetScroll ?? true;
|
|
504
|
+
this.shouldViewTransition = viewTransition;
|
|
505
|
+
nextHistory.state.__TSR_sessionId = this.sessionId;
|
|
506
|
+
nextHistory.state.__TSR_matches = next._matchSnapshot ?? buildMatchSnapshot({
|
|
507
|
+
matchResult: this.getMatchedRoutes(next.pathname),
|
|
508
|
+
pathname: next.pathname,
|
|
509
|
+
searchStr: next.searchStr,
|
|
510
|
+
notFoundRoute: this.options.notFoundRoute,
|
|
511
|
+
notFoundMode: this.options.notFoundMode
|
|
512
|
+
});
|
|
513
|
+
const precomputedLocation = {
|
|
514
|
+
...next,
|
|
515
|
+
publicHref: nextHistory.publicHref,
|
|
516
|
+
state: nextHistory.state,
|
|
517
|
+
maskedLocation
|
|
518
|
+
};
|
|
519
|
+
const result = await this.history[next.replace ? "replace" : "push"](
|
|
520
|
+
nextHistory.publicHref,
|
|
521
|
+
nextHistory.state,
|
|
522
|
+
{ ignoreBlocker, skipTransitionerLoad: true }
|
|
523
|
+
);
|
|
524
|
+
if (result.type === "BLOCKED") {
|
|
525
|
+
this.commitLocationPromise?.resolve();
|
|
526
|
+
return this.commitLocationPromise;
|
|
527
|
+
}
|
|
528
|
+
if (this.history.location.href !== nextHistory.publicHref) {
|
|
529
|
+
return this.commitLocationPromise;
|
|
501
530
|
}
|
|
531
|
+
this.latestLocation = precomputedLocation;
|
|
532
|
+
this.load({ _skipUpdateLatestLocation: true });
|
|
502
533
|
return this.commitLocationPromise;
|
|
503
534
|
};
|
|
504
535
|
this.buildAndCommitLocation = ({
|
|
@@ -605,9 +636,11 @@ class RouterCore {
|
|
|
605
636
|
_isNavigate: true
|
|
606
637
|
});
|
|
607
638
|
};
|
|
608
|
-
this.beforeLoad = () => {
|
|
639
|
+
this.beforeLoad = (opts) => {
|
|
609
640
|
this.cancelMatches();
|
|
610
|
-
|
|
641
|
+
if (!opts?._skipUpdateLatestLocation) {
|
|
642
|
+
this.updateLatestLocation();
|
|
643
|
+
}
|
|
611
644
|
if (this.isServer) {
|
|
612
645
|
const nextLocation = this.buildLocation({
|
|
613
646
|
to: this.latestLocation.pathname,
|
|
@@ -622,7 +655,8 @@ class RouterCore {
|
|
|
622
655
|
throw redirect({ href });
|
|
623
656
|
}
|
|
624
657
|
}
|
|
625
|
-
const
|
|
658
|
+
const snapshot = this.latestLocation.state.__TSR_sessionId === this.sessionId ? this.latestLocation.state.__TSR_matches : void 0;
|
|
659
|
+
const pendingMatches = this.matchRoutes(this.latestLocation, { snapshot });
|
|
626
660
|
this.__store.setState((s) => ({
|
|
627
661
|
...s,
|
|
628
662
|
status: "pending",
|
|
@@ -643,7 +677,9 @@ class RouterCore {
|
|
|
643
677
|
loadPromise = new Promise((resolve) => {
|
|
644
678
|
this.startTransition(async () => {
|
|
645
679
|
try {
|
|
646
|
-
this.beforeLoad(
|
|
680
|
+
this.beforeLoad({
|
|
681
|
+
_skipUpdateLatestLocation: opts?._skipUpdateLatestLocation
|
|
682
|
+
});
|
|
647
683
|
const next = this.latestLocation;
|
|
648
684
|
const prevLocation = this.state.resolvedLocation;
|
|
649
685
|
if (!this.state.redirect) {
|
|
@@ -1000,6 +1036,7 @@ class RouterCore {
|
|
|
1000
1036
|
(d) => d.status === "notFound" || d.globalNotFound
|
|
1001
1037
|
);
|
|
1002
1038
|
};
|
|
1039
|
+
this.sessionId = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
1003
1040
|
this.update({
|
|
1004
1041
|
defaultPreloadDelay: 50,
|
|
1005
1042
|
defaultPendingMs: 1e3,
|
|
@@ -1028,46 +1065,67 @@ class RouterCore {
|
|
|
1028
1065
|
return this.routesById;
|
|
1029
1066
|
}
|
|
1030
1067
|
matchRoutesInternal(next, opts) {
|
|
1031
|
-
const
|
|
1032
|
-
const
|
|
1033
|
-
let
|
|
1034
|
-
let
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
if (
|
|
1050
|
-
|
|
1068
|
+
const snapshot = opts?.snapshot;
|
|
1069
|
+
const snapshotValid = snapshot && snapshot.routeIds.length > 0 && snapshot.routeIds.every((id) => this.routesById[id]);
|
|
1070
|
+
let matchedRoutes;
|
|
1071
|
+
let routeParams;
|
|
1072
|
+
let globalNotFoundRouteId;
|
|
1073
|
+
let parsedParams;
|
|
1074
|
+
if (snapshotValid) {
|
|
1075
|
+
matchedRoutes = snapshot.routeIds.map((id) => this.routesById[id]);
|
|
1076
|
+
routeParams = { ...snapshot.params };
|
|
1077
|
+
globalNotFoundRouteId = snapshot.globalNotFoundRouteId;
|
|
1078
|
+
parsedParams = snapshot.parsedParams;
|
|
1079
|
+
} else {
|
|
1080
|
+
const matchedRoutesResult = this.getMatchedRoutes(next.pathname);
|
|
1081
|
+
const { foundRoute, routeParams: rp } = matchedRoutesResult;
|
|
1082
|
+
routeParams = rp;
|
|
1083
|
+
matchedRoutes = matchedRoutesResult.matchedRoutes;
|
|
1084
|
+
parsedParams = matchedRoutesResult.parsedParams;
|
|
1085
|
+
let isGlobalNotFound = false;
|
|
1086
|
+
if (
|
|
1087
|
+
// If we found a route, and it's not an index route and we have left over path
|
|
1088
|
+
foundRoute ? foundRoute.path !== "/" && routeParams["**"] : (
|
|
1089
|
+
// Or if we didn't find a route and we have left over path
|
|
1090
|
+
trimPathRight(next.pathname)
|
|
1091
|
+
)
|
|
1092
|
+
) {
|
|
1093
|
+
if (this.options.notFoundRoute) {
|
|
1094
|
+
matchedRoutes = [...matchedRoutes, this.options.notFoundRoute];
|
|
1095
|
+
} else {
|
|
1096
|
+
isGlobalNotFound = true;
|
|
1097
|
+
}
|
|
1051
1098
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1099
|
+
globalNotFoundRouteId = (() => {
|
|
1100
|
+
if (!isGlobalNotFound) {
|
|
1101
|
+
return void 0;
|
|
1102
|
+
}
|
|
1103
|
+
if (this.options.notFoundMode !== "root") {
|
|
1104
|
+
for (let i = matchedRoutes.length - 1; i >= 0; i--) {
|
|
1105
|
+
const route = matchedRoutes[i];
|
|
1106
|
+
if (route.children) {
|
|
1107
|
+
return route.id;
|
|
1108
|
+
}
|
|
1057
1109
|
}
|
|
1058
1110
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
}
|
|
1111
|
+
return rootRouteId;
|
|
1112
|
+
})();
|
|
1113
|
+
}
|
|
1062
1114
|
const matches = [];
|
|
1063
1115
|
const getParentContext = (parentMatch) => {
|
|
1064
1116
|
const parentMatchId = parentMatch?.id;
|
|
1065
1117
|
const parentContext = !parentMatchId ? this.options.context ?? void 0 : parentMatch.context ?? this.options.context ?? void 0;
|
|
1066
1118
|
return parentContext;
|
|
1067
1119
|
};
|
|
1120
|
+
const canUseCachedSearch = snapshotValid && snapshot.searchStr === next.searchStr && snapshot.validatedSearches?.length === matchedRoutes.length;
|
|
1121
|
+
const validatedSearchesToCache = [];
|
|
1068
1122
|
matchedRoutes.forEach((route, index) => {
|
|
1069
1123
|
const parentMatch = matches[index - 1];
|
|
1070
1124
|
const [preMatchSearch, strictMatchSearch, searchError] = (() => {
|
|
1125
|
+
if (canUseCachedSearch) {
|
|
1126
|
+
const cached = snapshot.validatedSearches[index];
|
|
1127
|
+
return [cached.search, cached.strictSearch, void 0];
|
|
1128
|
+
}
|
|
1071
1129
|
const parentSearch = parentMatch?.search ?? next.search;
|
|
1072
1130
|
const parentStrictSearch = parentMatch?._strictSearch ?? void 0;
|
|
1073
1131
|
try {
|
|
@@ -1093,6 +1151,12 @@ class RouterCore {
|
|
|
1093
1151
|
return [parentSearch, {}, searchParamError];
|
|
1094
1152
|
}
|
|
1095
1153
|
})();
|
|
1154
|
+
if (!canUseCachedSearch) {
|
|
1155
|
+
validatedSearchesToCache.push({
|
|
1156
|
+
search: preMatchSearch,
|
|
1157
|
+
strictSearch: strictMatchSearch
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1096
1160
|
const loaderDeps = route.options.loaderDeps?.({
|
|
1097
1161
|
search: preMatchSearch
|
|
1098
1162
|
}) ?? "";
|
|
@@ -1206,6 +1270,13 @@ class RouterCore {
|
|
|
1206
1270
|
};
|
|
1207
1271
|
matches.push(match);
|
|
1208
1272
|
});
|
|
1273
|
+
if (!canUseCachedSearch && validatedSearchesToCache.length > 0) {
|
|
1274
|
+
const existingSnapshot = next.state?.__TSR_matches;
|
|
1275
|
+
if (existingSnapshot) {
|
|
1276
|
+
existingSnapshot.searchStr = next.searchStr;
|
|
1277
|
+
existingSnapshot.validatedSearches = validatedSearchesToCache;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1209
1280
|
matches.forEach((match, index) => {
|
|
1210
1281
|
const route = this.looseRoutesById[match.routeId];
|
|
1211
1282
|
const existingMatch = this.getMatch(match.id);
|
|
@@ -1293,7 +1364,7 @@ function getMatchedRoutes({
|
|
|
1293
1364
|
const routeParams = {};
|
|
1294
1365
|
const trimmedPath = trimPathRight(pathname);
|
|
1295
1366
|
let foundRoute = void 0;
|
|
1296
|
-
let parsedParams =
|
|
1367
|
+
let parsedParams = {};
|
|
1297
1368
|
const match = findRouteMatch(trimmedPath, processedTree, true);
|
|
1298
1369
|
if (match) {
|
|
1299
1370
|
foundRoute = match.route;
|
|
@@ -1303,6 +1374,64 @@ function getMatchedRoutes({
|
|
|
1303
1374
|
const matchedRoutes = match?.branch || [routesById[rootRouteId]];
|
|
1304
1375
|
return { matchedRoutes, routeParams, foundRoute, parsedParams };
|
|
1305
1376
|
}
|
|
1377
|
+
function buildMatchSnapshot({
|
|
1378
|
+
matchResult,
|
|
1379
|
+
pathname,
|
|
1380
|
+
searchStr,
|
|
1381
|
+
notFoundRoute,
|
|
1382
|
+
notFoundMode
|
|
1383
|
+
}) {
|
|
1384
|
+
const snapshot = {
|
|
1385
|
+
routeIds: matchResult.matchedRoutes.map((r) => r.id),
|
|
1386
|
+
params: matchResult.routeParams,
|
|
1387
|
+
parsedParams: matchResult.parsedParams,
|
|
1388
|
+
searchStr
|
|
1389
|
+
};
|
|
1390
|
+
const isGlobalNotFound = matchResult.foundRoute ? matchResult.foundRoute.path !== "/" && matchResult.routeParams["**"] : trimPathRight(pathname);
|
|
1391
|
+
if (isGlobalNotFound) {
|
|
1392
|
+
if (notFoundRoute) {
|
|
1393
|
+
snapshot.globalNotFoundRouteId = notFoundRoute.id;
|
|
1394
|
+
} else {
|
|
1395
|
+
if (notFoundMode !== "root") {
|
|
1396
|
+
for (let i = matchResult.matchedRoutes.length - 1; i >= 0; i--) {
|
|
1397
|
+
const route = matchResult.matchedRoutes[i];
|
|
1398
|
+
if (route.children) {
|
|
1399
|
+
snapshot.globalNotFoundRouteId = route.id;
|
|
1400
|
+
break;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
if (!snapshot.globalNotFoundRouteId) {
|
|
1405
|
+
snapshot.globalNotFoundRouteId = rootRouteId;
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
return snapshot;
|
|
1410
|
+
}
|
|
1411
|
+
function buildMatchSnapshotFromRoutes({
|
|
1412
|
+
routes,
|
|
1413
|
+
params,
|
|
1414
|
+
searchStr,
|
|
1415
|
+
globalNotFoundRouteId
|
|
1416
|
+
}) {
|
|
1417
|
+
const stringParams = {};
|
|
1418
|
+
for (const key in params) {
|
|
1419
|
+
const value = params[key];
|
|
1420
|
+
if (value != null) {
|
|
1421
|
+
stringParams[key] = String(value);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
const snapshot = {
|
|
1425
|
+
routeIds: routes.map((r) => r.id),
|
|
1426
|
+
params: stringParams,
|
|
1427
|
+
parsedParams: params,
|
|
1428
|
+
searchStr
|
|
1429
|
+
};
|
|
1430
|
+
if (globalNotFoundRouteId) {
|
|
1431
|
+
snapshot.globalNotFoundRouteId = globalNotFoundRouteId;
|
|
1432
|
+
}
|
|
1433
|
+
return snapshot;
|
|
1434
|
+
}
|
|
1306
1435
|
function applySearchMiddleware({
|
|
1307
1436
|
search,
|
|
1308
1437
|
dest,
|
|
@@ -1384,6 +1513,8 @@ export {
|
|
|
1384
1513
|
PathParamError,
|
|
1385
1514
|
RouterCore,
|
|
1386
1515
|
SearchParamError,
|
|
1516
|
+
buildMatchSnapshot,
|
|
1517
|
+
buildMatchSnapshotFromRoutes,
|
|
1387
1518
|
defaultSerializeError,
|
|
1388
1519
|
getInitialRouterState,
|
|
1389
1520
|
getLocationChangeInfo,
|