@@ -495,6 +495,11 @@ export interface BuildNextOptions {
495495 _fromLocation ?: ParsedLocation
496496}
497497
498+ export interface MatchedRoutesResult {
499+ matchedRoutes : Array < AnyRoute >
500+ routeParams : Record < string , string >
501+ }
502+
498503export interface DehydratedRouterState {
499504 dehydratedMatches : Array < DehydratedRouteMatch >
500505}
@@ -602,6 +607,7 @@ type MatchRoutesOpts = {
602607 preload ?: boolean
603608 throwOnError ?: boolean
604609 _buildLocation ?: boolean
610+ dest ?: BuildNextOptions
605611}
606612
607613export class Router <
@@ -1013,33 +1019,10 @@ export class Router<
10131019 next : ParsedLocation ,
10141020 opts ?: MatchRoutesOpts ,
10151021 ) : Array < AnyRouteMatch > {
1016- let routeParams : Record < string , string > = { }
1017-
1018- const foundRoute = this . flatRoutes . find ( ( route ) => {
1019- const matchedParams = matchPathname (
1020- this . basepath ,
1021- trimPathRight ( next . pathname ) ,
1022- {
1023- to : route . fullPath ,
1024- caseSensitive :
1025- route . options . caseSensitive ?? this . options . caseSensitive ,
1026- fuzzy : true ,
1027- } ,
1028- )
1029-
1030- if ( matchedParams ) {
1031- routeParams = matchedParams
1032- return true
1033- }
1034-
1035- return false
1036- } )
1037-
1038- let routeCursor : AnyRoute =
1039- foundRoute || ( this . routesById as any ) [ rootRouteId ]
1040-
1041- const matchedRoutes : Array < AnyRoute > = [ routeCursor ]
1042-
1022+ const { foundRoute, matchedRoutes, routeParams } = this . getMatchedRoutes (
1023+ next ,
1024+ opts ?. dest ,
1025+ )
10431026 let isGlobalNotFound = false
10441027
10451028 // Check to see if the route needs a 404 entry
@@ -1059,11 +1042,6 @@ export class Router<
10591042 }
10601043 }
10611044
1062- while ( routeCursor . parentRoute ) {
1063- routeCursor = routeCursor . parentRoute
1064- matchedRoutes . unshift ( routeCursor )
1065- }
1066-
10671045 const globalNotFoundRouteId = ( ( ) => {
10681046 if ( ! isGlobalNotFound ) {
10691047 return undefined
@@ -1307,6 +1285,49 @@ export class Router<
13071285 return matches as any
13081286 }
13091287
1288+ getMatchedRoutes = ( next : ParsedLocation , dest ?: BuildNextOptions ) => {
1289+ let routeParams : Record < string , string > = { }
1290+ const trimmedPath = trimPathRight ( next . pathname )
1291+ const getMatchedParams = ( route : AnyRoute ) => {
1292+ const result = matchPathname ( this . basepath , trimmedPath , {
1293+ to : route . fullPath ,
1294+ caseSensitive :
1295+ route . options . caseSensitive ?? this . options . caseSensitive ,
1296+ fuzzy : true ,
1297+ } )
1298+ return result
1299+ }
1300+
1301+ let foundRoute : AnyRoute | undefined =
1302+ dest ?. to !== undefined ? this . routesByPath [ dest . to ! ] : undefined
1303+ if ( foundRoute ) {
1304+ routeParams = getMatchedParams ( foundRoute ) !
1305+ } else {
1306+ foundRoute = this . flatRoutes . find ( ( route ) => {
1307+ const matchedParams = getMatchedParams ( route )
1308+
1309+ if ( matchedParams ) {
1310+ routeParams = matchedParams
1311+ return true
1312+ }
1313+
1314+ return false
1315+ } )
1316+ }
1317+
1318+ let routeCursor : AnyRoute =
1319+ foundRoute || ( this . routesById as any ) [ rootRouteId ]
1320+
1321+ const matchedRoutes : Array < AnyRoute > = [ routeCursor ]
1322+
1323+ while ( routeCursor . parentRoute ) {
1324+ routeCursor = routeCursor . parentRoute
1325+ matchedRoutes . unshift ( routeCursor )
1326+ }
1327+
1328+ return { matchedRoutes, routeParams, foundRoute }
1329+ }
1330+
13101331 cancelMatch = ( id : string ) => {
13111332 const match = this . getMatch ( id )
13121333
@@ -1327,7 +1348,7 @@ export class Router<
13271348 dest : BuildNextOptions & {
13281349 unmaskOnReload ?: boolean
13291350 } = { } ,
1330- matches ?: Array < MakeRouteMatch < TRouteTree > > ,
1351+ matchedRoutesResult ?: MatchedRoutesResult ,
13311352 ) : ParsedLocation => {
13321353 const fromMatches = dest . _fromLocation
13331354 ? this . matchRoutes ( dest . _fromLocation , { _buildLocation : true } )
@@ -1355,22 +1376,30 @@ export class Router<
13551376 ? last ( this . state . pendingMatches ) ?. search
13561377 : last ( fromMatches ) ?. search || this . latestLocation . search
13571378
1358- const stayingMatches = matches ? .filter ( ( d ) =>
1359- fromMatches . find ( ( e ) => e . routeId === d . routeId ) ,
1379+ const stayingMatches = matchedRoutesResult ?. matchedRoutes . filter ( ( d ) =>
1380+ fromMatches . find ( ( e ) => e . routeId === d . id ) ,
13601381 )
13611382
1362- const fromRouteByFromPathRouteId =
1363- this . routesById [
1364- stayingMatches ?. find ( ( d ) => d . pathname === fromPath )
1365- ?. routeId as keyof this[ 'routesById' ]
1366- ]
1367-
1368- let pathname = dest . to
1369- ? this . resolvePathWithBase ( fromPath , `${ dest . to } ` )
1370- : this . resolvePathWithBase (
1371- fromPath ,
1372- fromRouteByFromPathRouteId ?. to ?? fromPath ,
1373- )
1383+ let pathname : string
1384+ if ( dest . to ) {
1385+ pathname = this . resolvePathWithBase ( fromPath , `${ dest . to } ` )
1386+ } else {
1387+ const fromRouteByFromPathRouteId =
1388+ this . routesById [
1389+ stayingMatches ?. find ( ( route ) => {
1390+ const interpolatedPath = interpolatePath ( {
1391+ path : route . fullPath ,
1392+ params : matchedRoutesResult ?. routeParams ?? { } ,
1393+ } )
1394+ const pathname = joinPaths ( [ this . basepath , interpolatedPath ] )
1395+ return pathname === fromPath
1396+ } ) ?. id as keyof this[ 'routesById' ]
1397+ ]
1398+ pathname = this . resolvePathWithBase (
1399+ fromPath ,
1400+ fromRouteByFromPathRouteId ?. to ?? fromPath ,
1401+ )
1402+ }
13741403
13751404 const prevParams = { ...last ( fromMatches ) ?. params }
13761405
@@ -1380,11 +1409,10 @@ export class Router<
13801409 : { ...prevParams , ...functionalUpdate ( dest . params , prevParams ) }
13811410
13821411 if ( Object . keys ( nextParams ) . length > 0 ) {
1383- matches
1384- ?. map ( ( d ) => {
1385- const route = this . looseRoutesById [ d . routeId ]
1412+ matchedRoutesResult ?. matchedRoutes
1413+ . map ( ( route ) => {
13861414 return (
1387- route ? .options . params ?. stringify ?? route ! . options . stringifyParams
1415+ route . options . params ?. stringify ?? route . options . stringifyParams
13881416 )
13891417 } )
13901418 . filter ( Boolean )
@@ -1402,21 +1430,13 @@ export class Router<
14021430
14031431 const preSearchFilters =
14041432 stayingMatches
1405- ?. map (
1406- ( match ) =>
1407- this . looseRoutesById [ match . routeId ] ! . options . preSearchFilters ??
1408- [ ] ,
1409- )
1433+ ?. map ( ( route ) => route . options . preSearchFilters ?? [ ] )
14101434 . flat ( )
14111435 . filter ( Boolean ) ?? [ ]
14121436
14131437 const postSearchFilters =
14141438 stayingMatches
1415- ?. map (
1416- ( match ) =>
1417- this . looseRoutesById [ match . routeId ] ! . options . postSearchFilters ??
1418- [ ] ,
1419- )
1439+ ?. map ( ( route ) => route . options . postSearchFilters ?? [ ] )
14201440 . flat ( )
14211441 . filter ( Boolean ) ?? [ ]
14221442
@@ -1509,17 +1529,12 @@ export class Router<
15091529 }
15101530 }
15111531
1512- const nextMatches = this . matchRoutes ( next , { _buildLocation : true } )
1513- const maskedMatches = maskedNext
1514- ? this . matchRoutes ( maskedNext , { _buildLocation : true } )
1515- : undefined
1516- const maskedFinal = maskedNext
1517- ? build ( maskedDest , maskedMatches )
1518- : undefined
1519-
1532+ const nextMatches = this . getMatchedRoutes ( next , dest )
15201533 const final = build ( dest , nextMatches )
15211534
1522- if ( maskedFinal ) {
1535+ if ( maskedNext ) {
1536+ const maskedMatches = this . getMatchedRoutes ( maskedNext , maskedDest )
1537+ const maskedFinal = build ( maskedDest , maskedMatches )
15231538 final . maskedLocation = maskedFinal
15241539 }
15251540
@@ -2497,6 +2512,7 @@ export class Router<
24972512 let matches = this . matchRoutes ( next , {
24982513 throwOnError : true ,
24992514 preload : true ,
2515+ dest : opts ,
25002516 } )
25012517
25022518 const loadedMatchIds = Object . fromEntries (
0 commit comments