@@ -158,6 +158,12 @@ export function createRouterMatcher(
158
158
removeRoute ( record . name )
159
159
}
160
160
161
+ // Avoid adding a record that doesn't display anything. This allows passing through records without a component to
162
+ // not be reached and pass through the catch all route
163
+ if ( isMatchable ( matcher ) ) {
164
+ insertMatcher ( matcher )
165
+ }
166
+
161
167
if ( mainNormalizedRecord . children ) {
162
168
const children = mainNormalizedRecord . children
163
169
for ( let i = 0 ; i < children . length ; i ++ ) {
@@ -177,17 +183,6 @@ export function createRouterMatcher(
177
183
// if (parent && isAliasRecord(originalRecord)) {
178
184
// parent.children.push(originalRecord)
179
185
// }
180
-
181
- // Avoid adding a record that doesn't display anything. This allows passing through records without a component to
182
- // not be reached and pass through the catch all route
183
- if (
184
- ( matcher . record . components &&
185
- Object . keys ( matcher . record . components ) . length ) ||
186
- matcher . record . name ||
187
- matcher . record . redirect
188
- ) {
189
- insertMatcher ( matcher )
190
- }
191
186
}
192
187
193
188
return originalMatcher
@@ -514,8 +509,8 @@ function checkMissingParamsInAbsolutePath(
514
509
/**
515
510
* Performs a binary search to find the correct insertion index for a new matcher.
516
511
*
517
- * Matchers are primarily sorted by their score. If scores are tied then the matcher's depth is used instead.
518
- * The depth check ensures that a child with an empty path comes before its parent .
512
+ * Matchers are primarily sorted by their score. If scores are tied then we also consider parent/child relationships,
513
+ * with descendants coming before ancestors. If there's still a tie, new routes are inserted after existing routes .
519
514
*
520
515
* @param matcher - new matcher to be inserted
521
516
* @param matchers - existing matchers
@@ -524,38 +519,59 @@ function findInsertionIndex(
524
519
matcher : RouteRecordMatcher ,
525
520
matchers : RouteRecordMatcher [ ]
526
521
) {
527
- const depth = getDepth ( matcher )
528
-
522
+ // First phase: binary search based on score
529
523
let lower = 0
530
524
let upper = matchers . length
531
525
532
526
while ( lower !== upper ) {
533
527
const mid = ( lower + upper ) >> 1
534
- const sortOrder =
535
- comparePathParserScore ( matcher , matchers [ mid ] ) ||
536
- getDepth ( matchers [ mid ] ) - depth
528
+ const sortOrder = comparePathParserScore ( matcher , matchers [ mid ] )
537
529
538
- if ( sortOrder === 0 ) {
539
- return mid
540
- } else if ( sortOrder < 0 ) {
530
+ if ( sortOrder < 0 ) {
541
531
upper = mid
542
532
} else {
543
533
lower = mid + 1
544
534
}
545
535
}
546
536
537
+ // Second phase: check for an ancestor with the same score
538
+ const insertionAncestor = getInsertionAncestor ( matcher )
539
+
540
+ if ( insertionAncestor ) {
541
+ upper = matchers . lastIndexOf ( insertionAncestor , upper - 1 )
542
+
543
+ if ( __DEV__ && upper === - 1 ) {
544
+ // This should never happen
545
+ warn (
546
+ `Finding ancestor route ${ insertionAncestor . record . path } failed for ${ matcher . record . path } `
547
+ )
548
+ }
549
+ }
550
+
547
551
return upper
548
552
}
549
553
550
- function getDepth ( record : RouteRecordMatcher ) {
551
- let depth = 0
554
+ function getInsertionAncestor ( matcher : RouteRecordMatcher ) {
555
+ let ancestor : RouteRecordMatcher | undefined = matcher
552
556
553
- while ( record . parent ) {
554
- ++ depth
555
- record = record . parent
557
+ while ( ( ancestor = ancestor . parent ) ) {
558
+ if (
559
+ isMatchable ( ancestor ) &&
560
+ comparePathParserScore ( matcher , ancestor ) === 0
561
+ ) {
562
+ return ancestor
563
+ }
556
564
}
557
565
558
- return depth
566
+ return
567
+ }
568
+
569
+ function isMatchable ( { record } : RouteRecordMatcher ) : boolean {
570
+ return ! ! (
571
+ record . name ||
572
+ ( record . components && Object . keys ( record . components ) . length ) ||
573
+ record . redirect
574
+ )
559
575
}
560
576
561
577
export type { PathParserOptions , _PathParserOptions }
0 commit comments