@@ -237,20 +237,13 @@ function parseSegments<TRouteLike extends RouteLike>(
237237 case SEGMENT_TYPE_PARAM :
238238 case SEGMENT_TYPE_OPTIONAL_PARAM :
239239 case SEGMENT_TYPE_WILDCARD : {
240- const prefix_raw = path . substring ( start , segment [ 1 ] )
241- const suffix_raw = path . substring ( segment [ 4 ] , end )
242- const actuallyCaseSensitive =
243- caseSensitive && ! ! ( prefix_raw || suffix_raw )
244- const prefix = ! prefix_raw
245- ? undefined
246- : actuallyCaseSensitive
247- ? prefix_raw
248- : prefix_raw . toLowerCase ( )
249- const suffix = ! suffix_raw
250- ? undefined
251- : actuallyCaseSensitive
252- ? suffix_raw
253- : suffix_raw . toLowerCase ( )
240+ let prefix = path . substring ( start , segment [ 1 ] )
241+ let suffix = path . substring ( segment [ 4 ] , end )
242+ const actuallyCaseSensitive = caseSensitive && ! ! ( prefix || suffix )
243+ if ( ! caseSensitive ) {
244+ prefix = prefix . toLowerCase ( )
245+ suffix = suffix . toLowerCase ( )
246+ }
254247 const siblings =
255248 kind === SEGMENT_TYPE_PARAM
256249 ? node . dynamic
@@ -357,15 +350,15 @@ function parseSegments<TRouteLike extends RouteLike>(
357350
358351function sortDynamic (
359352 a : {
360- prefix ? : string
361- suffix ? : string
353+ prefix : string
354+ suffix : string
362355 caseSensitive : boolean
363356 parse : null | ( ( params : Record < string , string > ) => unknown )
364357 priority : number
365358 } ,
366359 b : {
367- prefix ? : string
368- suffix ? : string
360+ prefix : string
361+ suffix : string
369362 caseSensitive : boolean
370363 parse : null | ( ( params : Record < string , string > ) => unknown )
371364 priority : number
@@ -426,8 +419,8 @@ function createDynamicNode<T extends RouteLike>(
426419 | typeof SEGMENT_TYPE_OPTIONAL_PARAM ,
427420 fullPath : string ,
428421 caseSensitive : boolean ,
429- prefix ? : string ,
430- suffix ? : string ,
422+ prefix : string ,
423+ suffix : string ,
431424) : DynamicSegmentNode < T > {
432425 return {
433426 kind,
@@ -462,8 +455,8 @@ type DynamicSegmentNode<T extends RouteLike> = SegmentNode<T> & {
462455 | typeof SEGMENT_TYPE_PARAM
463456 | typeof SEGMENT_TYPE_WILDCARD
464457 | typeof SEGMENT_TYPE_OPTIONAL_PARAM
465- prefix ? : string
466- suffix ? : string
458+ prefix : string
459+ suffix : string
467460 caseSensitive : boolean
468461}
469462
@@ -818,12 +811,12 @@ function extractParams<T extends RouteLike>(
818811 if ( node . kind === SEGMENT_TYPE_PARAM ) {
819812 nodeParts ??= leaf . node . fullPath . split ( '/' )
820813 const nodePart = nodeParts [ segmentCount ] !
821- const preLength = node . prefix ? .length ?? 0
814+ const preLength = node . prefix . length
822815 // we can't rely on the presence of prefix/suffix to know whether it's curly-braced or not, because `/{$param}/` is valid, but has no prefix/suffix
823816 const isCurlyBraced = nodePart . charCodeAt ( preLength ) === 123 // '{'
824817 // param name is extracted at match-time so that tree nodes that are identical except for param name can share the same node
825818 if ( isCurlyBraced ) {
826- const sufLength = node . suffix ? .length ?? 0
819+ const sufLength = node . suffix . length
827820 const name = nodePart . substring (
828821 preLength + 2 ,
829822 nodePart . length - sufLength - 1 ,
@@ -842,8 +835,8 @@ function extractParams<T extends RouteLike>(
842835 }
843836 nodeParts ??= leaf . node . fullPath . split ( '/' )
844837 const nodePart = nodeParts [ segmentCount ] !
845- const preLength = node . prefix ? .length ?? 0
846- const sufLength = node . suffix ? .length ?? 0
838+ const preLength = node . prefix . length
839+ const sufLength = node . suffix . length
847840 const name = nodePart . substring (
848841 preLength + 3 ,
849842 nodePart . length - sufLength - 1 ,
@@ -856,8 +849,8 @@ function extractParams<T extends RouteLike>(
856849 } else if ( node . kind === SEGMENT_TYPE_WILDCARD ) {
857850 const n = node
858851 const value = path . substring (
859- currentPathIndex + ( n . prefix ? .length ?? 0 ) ,
860- path . length - ( n . suffix ? .length ?? 0 ) ,
852+ currentPathIndex + n . prefix . length ,
853+ path . length - n . suffix . length ,
861854 )
862855 const splat = decodeURIComponent ( value )
863856 // TODO: Deprecate *
@@ -1061,9 +1054,17 @@ function getNodeMatch<T extends RouteLike>(
10611054 }
10621055 if ( suffix ) {
10631056 if ( isBeyondPath ) continue
1064- const end = parts . slice ( index ) . join ( '/' ) . slice ( - suffix . length )
1065- const casePart = segment . caseSensitive ? end : end . toLowerCase ( )
1066- if ( casePart !== suffix ) continue
1057+ const end = parts . slice ( index ) . join ( '/' )
1058+ const suffixPart = end . slice ( - suffix . length )
1059+ const casePart = segment . caseSensitive
1060+ ? suffixPart
1061+ : suffixPart . toLowerCase ( )
1062+ if (
1063+ casePart !== suffix ||
1064+ end . length - suffix . length < prefix . length
1065+ ) {
1066+ continue
1067+ }
10671068 }
10681069 // wildcard matches consume the rest of the URL and cannot have children
10691070 stack . push ( {
@@ -1106,7 +1107,13 @@ function getNodeMatch<T extends RouteLike>(
11061107 ? part !
11071108 : ( lowerPart ??= part ! . toLowerCase ( ) )
11081109 if ( prefix && ! casePart . startsWith ( prefix ) ) continue
1109- if ( suffix && ! casePart . endsWith ( suffix ) ) continue
1110+ if (
1111+ suffix &&
1112+ casePart . indexOf ( suffix , casePart . length - suffix . length ) <
1113+ prefix . length
1114+ ) {
1115+ continue
1116+ }
11101117 }
11111118 stack . push ( {
11121119 node : segment ,
@@ -1132,7 +1139,13 @@ function getNodeMatch<T extends RouteLike>(
11321139 ? part
11331140 : ( lowerPart ??= part . toLowerCase ( ) )
11341141 if ( prefix && ! casePart . startsWith ( prefix ) ) continue
1135- if ( suffix && ! casePart . endsWith ( suffix ) ) continue
1142+ if (
1143+ suffix &&
1144+ casePart . indexOf ( suffix , casePart . length - suffix . length ) <
1145+ prefix . length
1146+ ) {
1147+ continue
1148+ }
11361149 }
11371150 stack . push ( {
11381151 node : segment ,
0 commit comments