@@ -223,17 +223,8 @@ export function createRouterMatcher(
223
223
}
224
224
225
225
function insertMatcher ( matcher : RouteRecordMatcher ) {
226
- let i = 0
227
- while (
228
- i < matchers . length &&
229
- comparePathParserScore ( matcher , matchers [ i ] ) >= 0 &&
230
- // Adding children with empty path should still appear before the parent
231
- // https://github.com/vuejs/router/issues/1124
232
- ( matcher . record . path !== matchers [ i ] . record . path ||
233
- ! isRecordChildOf ( matcher , matchers [ i ] ) )
234
- )
235
- i ++
236
- matchers . splice ( i , 0 , matcher )
226
+ const index = findInsertionIndex ( matcher , matchers )
227
+ matchers . splice ( index , 0 , matcher )
237
228
// only add the original record to the name map
238
229
if ( matcher . record . name && ! isAliasRecord ( matcher ) )
239
230
matcherMap . set ( matcher . record . name , matcher )
@@ -520,13 +511,46 @@ function checkMissingParamsInAbsolutePath(
520
511
}
521
512
}
522
513
523
- function isRecordChildOf (
524
- record : RouteRecordMatcher ,
525
- parent : RouteRecordMatcher
526
- ) : boolean {
527
- return parent . children . some (
528
- child => child === record || isRecordChildOf ( record , child )
529
- )
514
+ /**
515
+ * Performs a binary search to find the correct insertion index for a new matcher.
516
+ *
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.
519
+ *
520
+ * @param matcher - new matcher to be inserted
521
+ * @param matchers - existing matchers
522
+ */
523
+ function findInsertionIndex ( matcher : RouteRecordMatcher , matchers : RouteRecordMatcher [ ] ) {
524
+ const depth = getDepth ( matcher )
525
+
526
+ let lower = 0
527
+ let upper = matchers . length
528
+
529
+ while ( lower !== upper ) {
530
+ const mid = ( lower + upper ) >> 1
531
+ const sortOrder = comparePathParserScore ( matcher , matchers [ mid ] ) || getDepth ( matchers [ mid ] ) - depth
532
+
533
+ if ( sortOrder === 0 ) {
534
+ return mid
535
+ } else if ( sortOrder < 0 ) {
536
+ upper = mid
537
+ } else {
538
+ lower = mid + 1
539
+ }
540
+ }
541
+
542
+ return upper
543
+ }
544
+
545
+ function getDepth ( record : RouteRecordMatcher ) {
546
+ let depth = 0
547
+
548
+ while ( record . parent ) {
549
+ ++ depth
550
+ record = record . parent
551
+ }
552
+
553
+ return depth
530
554
}
531
555
532
556
export type { PathParserOptions , _PathParserOptions }
0 commit comments