@@ -45,6 +45,7 @@ import type {
4545} from './cache-key'
4646import {
4747 doesStaticSegmentAppearInURL ,
48+ getCacheKeyForDynamicParam ,
4849 getRenderedPathname ,
4950 getRenderedSearch ,
5051 parseDynamicParamFromURLPart ,
@@ -900,8 +901,11 @@ function convertRootTreePrefetchToRouteTree(
900901 // Remove trailing and leading slashes
901902 const pathnameParts = renderedPathname . split ( '/' ) . filter ( ( p ) => p !== '' )
902903 const index = 0
904+ const rootSegment = ROOT_SEGMENT_CACHE_KEY
903905 return convertTreePrefetchToRouteTree (
904906 rootTree . tree ,
907+ rootSegment ,
908+ null ,
905909 ROOT_SEGMENT_REQUEST_KEY ,
906910 ROOT_SEGMENT_CACHE_KEY ,
907911 pathnameParts ,
@@ -911,6 +915,8 @@ function convertRootTreePrefetchToRouteTree(
911915
912916function convertTreePrefetchToRouteTree (
913917 prefetch : TreePrefetch ,
918+ segment : FlightRouterStateSegment ,
919+ param : RouteParam | null ,
914920 requestKey : SegmentRequestKey ,
915921 cacheKey : SegmentCacheKey ,
916922 pathnameParts : Array < string > ,
@@ -922,52 +928,71 @@ function convertTreePrefetchToRouteTree(
922928 // it once instead of on every access. This same cache key is also used to
923929 // request the segment from the server.
924930
925- let segment = prefetch . segment
926-
927- let doesAppearInURL : boolean
928- let param : RouteParam | null = null
929- if ( Array . isArray ( segment ) ) {
930- // This segment is parameterized. Get the param from the pathname.
931- const paramType = segment [ 2 ] as DynamicParamTypesShort
932- const paramValue = parseDynamicParamFromURLPart (
933- paramType ,
934- pathnameParts ,
935- pathnamePartsIndex
936- )
937- param = {
938- name : segment [ 0 ] ,
939- value : paramValue ,
940- type : paramType ,
941- }
942-
943- // Assign a cache key to the segment, based on the param value. In the
944- // pre-Segment Cache implementation, the server computes this and sends it
945- // in the body of the response. In the Segment Cache implementation, the
946- // server sends an empty string and we fill it in here.
947- // TODO: This will land in a follow up PR.
948- // segment[1] = getCacheKeyForDynamicParam(paramValue)
949-
950- doesAppearInURL = true
951- } else {
952- doesAppearInURL = doesStaticSegmentAppearInURL ( segment )
953- }
954-
955- // Only increment the index if the segment appears in the URL. If it's a
956- // "virtual" segment, like a route group, it remains the same.
957- const childPathnamePartsIndex = doesAppearInURL
958- ? pathnamePartsIndex + 1
959- : pathnamePartsIndex
960-
961931 let slots : { [ parallelRouteKey : string ] : RouteTree } | null = null
962932 const prefetchSlots = prefetch . slots
963933 if ( prefetchSlots !== null ) {
964934 slots = { }
965935 for ( let parallelRouteKey in prefetchSlots ) {
966936 const childPrefetch = prefetchSlots [ parallelRouteKey ]
967- const childSegment = childPrefetch . segment
968- // TODO: Eventually, the param values will not be included in the response
969- // from the server. We'll instead fill them in on the client by parsing
970- // the URL. This is where we'll do that.
937+ const childParamName = childPrefetch . name
938+ const childParamType = childPrefetch . paramType
939+ const childServerSentParamKey = childPrefetch . paramKey
940+
941+ let childDoesAppearInURL : boolean
942+ let childParam : RouteParam | null = null
943+ let childSegment : FlightRouterStateSegment
944+ if ( childParamType !== null ) {
945+ // This segment is parameterized. Get the param from the pathname.
946+ const childParamValue = parseDynamicParamFromURLPart (
947+ childParamType ,
948+ pathnameParts ,
949+ pathnamePartsIndex
950+ )
951+
952+ // Assign a cache key to the segment, based on the param value. In the
953+ // pre-Segment Cache implementation, the server computes this and sends
954+ // it in the body of the response. In the Segment Cache implementation,
955+ // the server sends an empty string and we fill it in here.
956+
957+ // TODO: We're intentionally not adding the search param to page
958+ // segments here; it's tracked separately and added back during a read.
959+ // This would clearer if we waited to construct the segment until it's
960+ // read from the cache, since that's effectively what we're
961+ // doing anyway.
962+ const renderedSearch = '' as NormalizedSearch
963+ const childParamKey =
964+ // The server omits this field from the prefetch response when
965+ // clientParamParsing is enabled. The flag only exists while we're
966+ // testing the feature, in case there's a bug and we need to revert.
967+ // TODO: Remove once clientParamParsing is enabled everywhere.
968+ childServerSentParamKey !== null
969+ ? childServerSentParamKey
970+ : // If no param key was sent, use the value parsed on the client.
971+ getCacheKeyForDynamicParam ( childParamValue , renderedSearch )
972+
973+ childParam = {
974+ name : childParamName ,
975+ value : childParamValue ,
976+ type : childParamType ,
977+ }
978+ childSegment = [
979+ childParamName ,
980+ childParamKey ,
981+ childParamType ,
982+ childParamValue ,
983+ ]
984+ childDoesAppearInURL = true
985+ } else {
986+ childSegment = childParamName
987+ childDoesAppearInURL = doesStaticSegmentAppearInURL ( childParamName )
988+ }
989+
990+ // Only increment the index if the segment appears in the URL. If it's a
991+ // "virtual" segment, like a route group, it remains the same.
992+ const childPathnamePartsIndex = childDoesAppearInURL
993+ ? pathnamePartsIndex + 1
994+ : pathnamePartsIndex
995+
971996 const childRequestKeyPart = createSegmentRequestKeyPart ( childSegment )
972997 const childRequestKey = appendSegmentRequestKeyPart (
973998 requestKey ,
@@ -981,6 +1006,8 @@ function convertTreePrefetchToRouteTree(
9811006 )
9821007 slots [ parallelRouteKey ] = convertTreePrefetchToRouteTree (
9831008 childPrefetch ,
1009+ childSegment ,
1010+ childParam ,
9841011 childRequestKey ,
9851012 childCacheKey ,
9861013 pathnameParts ,
0 commit comments