Skip to content

Commit bb4f022

Browse files
committed
there can be multiple wildcard children on a node because of prefix/suffix
1 parent baa2764 commit bb4f022

File tree

1 file changed

+25
-18
lines changed

1 file changed

+25
-18
lines changed

packages/router-core/src/new-process-route-tree.ts

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function parseSegments<TRouteLike extends RouteLike>(data: Uint16Array, route: T
190190
} else {
191191
const next = createOptionalNode(value, caseSensitive, prefix, suffix)
192192
nextNode = next
193-
nextNode.parent = node
193+
next.parent = node
194194
node.optional ??= []
195195
node.optional.push(next)
196196
}
@@ -204,9 +204,8 @@ function parseSegments<TRouteLike extends RouteLike>(data: Uint16Array, route: T
204204
const next = createWildcardNode(caseSensitive, prefix, suffix)
205205
nextNode = next
206206
next.parent = node
207-
next.routeId = route.id
208-
node.wildcard = next
209-
return
207+
node.wildcard ??= []
208+
node.wildcard.push(next)
210209
}
211210
}
212211
node = nextNode
@@ -341,8 +340,8 @@ type SegmentNode = {
341340
// Optional dynamic segments ({-$param})
342341
optional: Array<OptionalSegmentNode> | null
343342

344-
// Wildcard segment ($ - lowest priority)
345-
wildcard: WildcardSegmentNode | null
343+
// Wildcard segments ($ - lowest priority)
344+
wildcard: Array<WildcardSegmentNode> | null
346345

347346
// Terminal route (if this path can end here)
348347
routeId: string | null
@@ -462,6 +461,8 @@ function getNodeMatch(parts: Array<string>, segmentTree: SegmentNode) {
462461
{ node: segmentTree, partIndex: 0 }
463462
]
464463

464+
let wildcardMatch: typeof stack[0] | null = null
465+
465466
while (stack.length) {
466467
let { node, partIndex, skipped } = stack.shift()!
467468

@@ -529,25 +530,31 @@ function getNodeMatch(parts: Array<string>, segmentTree: SegmentNode) {
529530

530531
// 5. Try wildcard match
531532
if (node.wildcard) {
532-
const { prefix, suffix } = node.wildcard
533-
if (prefix) {
534-
const casePart = node.wildcard.caseSensitive ? part : part.toLowerCase()
535-
if (!casePart.startsWith(prefix)) break
536-
}
537-
if (suffix) {
538-
const part = parts[parts.length - 1]!
539-
const casePart = node.wildcard.caseSensitive ? part : part.toLowerCase()
540-
if (!casePart.endsWith(suffix)) break
533+
for (const segment of node.wildcard) {
534+
const { prefix, suffix } = segment
535+
if (prefix) {
536+
const casePart = segment.caseSensitive ? part : part.toLowerCase()
537+
if (!casePart.startsWith(prefix)) continue
538+
}
539+
if (suffix) {
540+
const part = parts[parts.length - 1]!
541+
const casePart = segment.caseSensitive ? part : part.toLowerCase()
542+
if (!casePart.endsWith(suffix)) continue
543+
}
544+
// a wildcard match terminates the loop, but we need to continue searching in case there's a longer match
545+
if (!wildcardMatch || (wildcardMatch.partIndex < partIndex)) {
546+
wildcardMatch = { node: segment, partIndex, skipped }
547+
}
548+
break main
541549
}
542-
partIndex = parts.length
543-
node = node.wildcard
544-
continue
545550
}
546551

547552
// No match found
548553
break
549554
}
550555
}
551556

557+
if (wildcardMatch) return wildcardMatch
558+
552559
return null
553560
}

0 commit comments

Comments
 (0)