@@ -223,17 +223,8 @@ export function createRouterMatcher(
223223 }
224224
225225 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 )
237228 // only add the original record to the name map
238229 if ( matcher . record . name && ! isAliasRecord ( matcher ) )
239230 matcherMap . set ( matcher . record . name , matcher )
@@ -520,13 +511,46 @@ function checkMissingParamsInAbsolutePath(
520511 }
521512}
522513
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
530554}
531555
532556export type { PathParserOptions , _PathParserOptions }
0 commit comments