From c7ff589f762092f7fda0fa808b88859a0c7e8130 Mon Sep 17 00:00:00 2001 From: Sheraff Date: Wed, 29 Oct 2025 11:55:56 +0100 Subject: [PATCH 1/7] fix(router-core): process route tree should avoid float arithmetics --- .../router-core/src/process-route-tree.ts | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/router-core/src/process-route-tree.ts b/packages/router-core/src/process-route-tree.ts index 85a3b7a1e76..a4aaa970ed7 100644 --- a/packages/router-core/src/process-route-tree.ts +++ b/packages/router-core/src/process-route-tree.ts @@ -10,17 +10,17 @@ import { import type { Segment } from './path' import type { RouteLike } from './route' -const SLASH_SCORE = 0.75 -const STATIC_SEGMENT_SCORE = 1 -const REQUIRED_PARAM_BASE_SCORE = 0.5 -const OPTIONAL_PARAM_BASE_SCORE = 0.4 -const WILDCARD_PARAM_BASE_SCORE = 0.25 -const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 0.2 -const BOTH_PRESENCE_BASE_SCORE = 0.05 -const PREFIX_PRESENCE_BASE_SCORE = 0.02 -const SUFFIX_PRESENCE_BASE_SCORE = 0.01 -const PREFIX_LENGTH_SCORE_MULTIPLIER = 0.0002 -const SUFFIX_LENGTH_SCORE_MULTIPLIER = 0.0001 +const SLASH_SCORE = 7500 +const STATIC_SEGMENT_SCORE = 10000 +const REQUIRED_PARAM_BASE_SCORE = 5000 +const OPTIONAL_PARAM_BASE_SCORE = 4000 +const WILDCARD_PARAM_BASE_SCORE = 2500 +const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 2000 +const BOTH_PRESENCE_BASE_SCORE = 500 +const PREFIX_PRESENCE_BASE_SCORE = 200 +const SUFFIX_PRESENCE_BASE_SCORE = 100 +const PREFIX_LENGTH_SCORE_MULTIPLIER = 2 +const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1 function handleParam(segment: Segment, baseScore: number) { if (segment.prefixSegment && segment.suffixSegment) { From 907712d4c58e0d4ea7cff0dae26587350f59dd2c Mon Sep 17 00:00:00 2001 From: Sheraff Date: Wed, 29 Oct 2025 12:08:22 +0100 Subject: [PATCH 2/7] try without Object.values --- packages/router-core/src/process-route-tree.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/router-core/src/process-route-tree.ts b/packages/router-core/src/process-route-tree.ts index a4aaa970ed7..c867f39a727 100644 --- a/packages/router-core/src/process-route-tree.ts +++ b/packages/router-core/src/process-route-tree.ts @@ -201,6 +201,7 @@ export function processRouteTree({ }): ProcessRouteTreeResult { const routesById = {} as Record const routesByPath = {} as Record + const order = [] as Array const recurseRoutes = (childRoutes: Array) => { childRoutes.forEach((childRoute, i) => { @@ -214,6 +215,7 @@ export function processRouteTree({ ) routesById[childRoute.id] = childRoute + order.push(childRoute.id) if (!childRoute.isRoot && childRoute.path) { const trimmedFullPath = trimPathRight(childRoute.fullPath) @@ -235,7 +237,7 @@ export function processRouteTree({ recurseRoutes([routeTree]) - const flatRoutes = sortRoutes(Object.values(routesById)) + const flatRoutes = sortRoutes(order.map((id) => routesById[id]!)) return { routesById, routesByPath, flatRoutes } } From 058304017cfb532871300e46e2c488e6c6d475b1 Mon Sep 17 00:00:00 2001 From: Sheraff Date: Wed, 29 Oct 2025 12:47:10 +0100 Subject: [PATCH 3/7] try pre-sorting routes --- packages/router-core/src/process-route-tree.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/router-core/src/process-route-tree.ts b/packages/router-core/src/process-route-tree.ts index c867f39a727..6794fe86b0e 100644 --- a/packages/router-core/src/process-route-tree.ts +++ b/packages/router-core/src/process-route-tree.ts @@ -237,7 +237,7 @@ export function processRouteTree({ recurseRoutes([routeTree]) - const flatRoutes = sortRoutes(order.map((id) => routesById[id]!)) + const flatRoutes = sortRoutes(order.sort().map((id) => routesById[id]!)) return { routesById, routesByPath, flatRoutes } } From b07066cbc6e64ee022b4340ecf362ce9d0e741cb Mon Sep 17 00:00:00 2001 From: Sheraff Date: Wed, 29 Oct 2025 14:03:42 +0100 Subject: [PATCH 4/7] unit test --- .../router-core/src/process-route-tree.ts | 33 +++++++++---------- .../tests/processRouteTree.test.ts | 21 ++++++++++++ 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/packages/router-core/src/process-route-tree.ts b/packages/router-core/src/process-route-tree.ts index 6794fe86b0e..bd1199928cc 100644 --- a/packages/router-core/src/process-route-tree.ts +++ b/packages/router-core/src/process-route-tree.ts @@ -10,17 +10,17 @@ import { import type { Segment } from './path' import type { RouteLike } from './route' -const SLASH_SCORE = 7500 -const STATIC_SEGMENT_SCORE = 10000 -const REQUIRED_PARAM_BASE_SCORE = 5000 -const OPTIONAL_PARAM_BASE_SCORE = 4000 -const WILDCARD_PARAM_BASE_SCORE = 2500 -const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 2000 -const BOTH_PRESENCE_BASE_SCORE = 500 -const PREFIX_PRESENCE_BASE_SCORE = 200 -const SUFFIX_PRESENCE_BASE_SCORE = 100 -const PREFIX_LENGTH_SCORE_MULTIPLIER = 2 -const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1 +const SLASH_SCORE = 0.75 +const STATIC_SEGMENT_SCORE = 1 +const REQUIRED_PARAM_BASE_SCORE = 0.5 +const OPTIONAL_PARAM_BASE_SCORE = 0.4 +const WILDCARD_PARAM_BASE_SCORE = 0.25 +const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 0.2 +const BOTH_PRESENCE_BASE_SCORE = 0.05 +const PREFIX_PRESENCE_BASE_SCORE = 0.02 +const SUFFIX_PRESENCE_BASE_SCORE = 0.01 +const PREFIX_LENGTH_SCORE_MULTIPLIER = 0.0002 +const SUFFIX_LENGTH_SCORE_MULTIPLIER = 0.0001 function handleParam(segment: Segment, baseScore: number) { if (segment.prefixSegment && segment.suffixSegment) { @@ -201,16 +201,15 @@ export function processRouteTree({ }): ProcessRouteTreeResult { const routesById = {} as Record const routesByPath = {} as Record - const order = [] as Array + const order: Array = [] const recurseRoutes = (childRoutes: Array) => { - childRoutes.forEach((childRoute, i) => { + for (let i = 0; i < childRoutes.length; i++) { + const childRoute = childRoutes[i]! initRoute?.(childRoute, i) - const existingRoute = routesById[childRoute.id] - invariant( - !existingRoute, + !(childRoute.id in routesById), `Duplicate routes found with id: ${String(childRoute.id)}`, ) @@ -232,7 +231,7 @@ export function processRouteTree({ if (children?.length) { recurseRoutes(children) } - }) + } } recurseRoutes([routeTree]) diff --git a/packages/router-core/tests/processRouteTree.test.ts b/packages/router-core/tests/processRouteTree.test.ts index 3a509a3376f..4087a710649 100644 --- a/packages/router-core/tests/processRouteTree.test.ts +++ b/packages/router-core/tests/processRouteTree.test.ts @@ -439,4 +439,25 @@ describe('processRouteTree', () => { }, ) }) + + describe.only('foo', () => { + const routes = [ + "/_breadcrumbsLayout/$accountId/vulnerabilities/settings/ticket-lifecycle/automations/{-$id}/{-$ruleIndex}/audit/$automationId/", + "/_breadcrumbsLayout/$accountId/assets/settings/rule-set/create/$ruleIndex/", + "/_breadcrumbsLayout/$accountId/assets/settings/rule-set/create", + ] + it.each([ + [0, 1, 2], + [0, 2, 1], + [1, 0, 2], + [1, 2, 0], + [2, 0, 1], + [2, 1, 0], + ])('should sort correctly %#', (...routeIndexes) => { + const shuffledRoutes = routeIndexes.map((i) => routes[i]!) + const routeTree = createRouteTree(shuffledRoutes) + const result = processRouteTree({ routeTree }) + expect(result.flatRoutes.map((r) => r.id)).toEqual(routes) + }) + }) }) From 680f08bace64d68634646b1d230822e77fa059a3 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:04:46 +0000 Subject: [PATCH 5/7] ci: apply automated fixes --- packages/router-core/tests/processRouteTree.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/router-core/tests/processRouteTree.test.ts b/packages/router-core/tests/processRouteTree.test.ts index 4087a710649..70e20ce356a 100644 --- a/packages/router-core/tests/processRouteTree.test.ts +++ b/packages/router-core/tests/processRouteTree.test.ts @@ -442,9 +442,9 @@ describe('processRouteTree', () => { describe.only('foo', () => { const routes = [ - "/_breadcrumbsLayout/$accountId/vulnerabilities/settings/ticket-lifecycle/automations/{-$id}/{-$ruleIndex}/audit/$automationId/", - "/_breadcrumbsLayout/$accountId/assets/settings/rule-set/create/$ruleIndex/", - "/_breadcrumbsLayout/$accountId/assets/settings/rule-set/create", + '/_breadcrumbsLayout/$accountId/vulnerabilities/settings/ticket-lifecycle/automations/{-$id}/{-$ruleIndex}/audit/$automationId/', + '/_breadcrumbsLayout/$accountId/assets/settings/rule-set/create/$ruleIndex/', + '/_breadcrumbsLayout/$accountId/assets/settings/rule-set/create', ] it.each([ [0, 1, 2], From 57302c1a952f7eb2a4c8383654738e4421547e10 Mon Sep 17 00:00:00 2001 From: Sheraff Date: Wed, 29 Oct 2025 14:04:44 +0100 Subject: [PATCH 6/7] pouet --- .../router-core/src/process-route-tree.ts | 22 +++++++++---------- .../tests/processRouteTree.test.ts | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/router-core/src/process-route-tree.ts b/packages/router-core/src/process-route-tree.ts index bd1199928cc..4243de19993 100644 --- a/packages/router-core/src/process-route-tree.ts +++ b/packages/router-core/src/process-route-tree.ts @@ -10,17 +10,17 @@ import { import type { Segment } from './path' import type { RouteLike } from './route' -const SLASH_SCORE = 0.75 -const STATIC_SEGMENT_SCORE = 1 -const REQUIRED_PARAM_BASE_SCORE = 0.5 -const OPTIONAL_PARAM_BASE_SCORE = 0.4 -const WILDCARD_PARAM_BASE_SCORE = 0.25 -const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 0.2 -const BOTH_PRESENCE_BASE_SCORE = 0.05 -const PREFIX_PRESENCE_BASE_SCORE = 0.02 -const SUFFIX_PRESENCE_BASE_SCORE = 0.01 -const PREFIX_LENGTH_SCORE_MULTIPLIER = 0.0002 -const SUFFIX_LENGTH_SCORE_MULTIPLIER = 0.0001 +const SLASH_SCORE = 7500 +const STATIC_SEGMENT_SCORE = 10000 +const REQUIRED_PARAM_BASE_SCORE = 5000 +const OPTIONAL_PARAM_BASE_SCORE = 4000 +const WILDCARD_PARAM_BASE_SCORE = 2500 +const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 2000 +const BOTH_PRESENCE_BASE_SCORE = 500 +const PREFIX_PRESENCE_BASE_SCORE = 200 +const SUFFIX_PRESENCE_BASE_SCORE = 100 +const PREFIX_LENGTH_SCORE_MULTIPLIER = 2 +const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1 function handleParam(segment: Segment, baseScore: number) { if (segment.prefixSegment && segment.suffixSegment) { diff --git a/packages/router-core/tests/processRouteTree.test.ts b/packages/router-core/tests/processRouteTree.test.ts index 70e20ce356a..7a61b40624a 100644 --- a/packages/router-core/tests/processRouteTree.test.ts +++ b/packages/router-core/tests/processRouteTree.test.ts @@ -440,7 +440,7 @@ describe('processRouteTree', () => { ) }) - describe.only('foo', () => { + describe('#5635 - sort result is independant of initial route order', () => { const routes = [ '/_breadcrumbsLayout/$accountId/vulnerabilities/settings/ticket-lifecycle/automations/{-$id}/{-$ruleIndex}/audit/$automationId/', '/_breadcrumbsLayout/$accountId/assets/settings/rule-set/create/$ruleIndex/', From bb7543e8f33f4f4280a6ad5aed56159ea2081cf9 Mon Sep 17 00:00:00 2001 From: Flo Date: Wed, 29 Oct 2025 15:26:08 +0100 Subject: [PATCH 7/7] Update packages/router-core/tests/processRouteTree.test.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- packages/router-core/tests/processRouteTree.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/router-core/tests/processRouteTree.test.ts b/packages/router-core/tests/processRouteTree.test.ts index 7a61b40624a..b027e46320c 100644 --- a/packages/router-core/tests/processRouteTree.test.ts +++ b/packages/router-core/tests/processRouteTree.test.ts @@ -440,7 +440,7 @@ describe('processRouteTree', () => { ) }) - describe('#5635 - sort result is independant of initial route order', () => { + describe('#5635 - sort result is independent of initial route order', () => { const routes = [ '/_breadcrumbsLayout/$accountId/vulnerabilities/settings/ticket-lifecycle/automations/{-$id}/{-$ruleIndex}/audit/$automationId/', '/_breadcrumbsLayout/$accountId/assets/settings/rule-set/create/$ruleIndex/',