Skip to content

refactor: use local matches in adapter Match components#7052

Draft
Sheraff wants to merge 1 commit intomainfrom
refactor/use-local-match-in-adapters
Draft

refactor: use local matches in adapter Match components#7052
Sheraff wants to merge 1 commit intomainfrom
refactor/use-local-match-in-adapters

Conversation

@Sheraff
Copy link
Copy Markdown
Contributor

@Sheraff Sheraff commented Mar 26, 2026

Summary

  • stop re-looking up matches by id in the React, Solid, and Vue Match.tsx adapters and use each adapter's existing local match source instead
  • keep the Solid and Vue pending/redirected paths wired to the local match objects they already subscribe to
  • update the Vue store-update expectations to match the lower update counts from the direct match usage

Testing

  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/react-router:test:unit --outputStyle=stream --skipRemoteCache
  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/react-router:test:types --outputStyle=stream --skipRemoteCache
  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/react-router:test:eslint --outputStyle=stream --skipRemoteCache
  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/solid-router:test:unit --outputStyle=stream --skipRemoteCache
  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/solid-router:test:types --outputStyle=stream --skipRemoteCache
  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/solid-router:test:eslint --outputStyle=stream --skipRemoteCache
  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/vue-router:test:unit --outputStyle=stream --skipRemoteCache
  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/vue-router:test:types --outputStyle=stream --skipRemoteCache
  • CI=1 NX_DAEMON=false pnpm nx run @tanstack/vue-router:test:eslint --outputStyle=stream --skipRemoteCache

Summary by CodeRabbit

  • Refactor

    • Optimized internal match state access patterns across React, Solid, and Vue router implementations for improved efficiency.
  • Tests

    • Updated navigation test assertions to reflect reduced store update counts during pending and loading states.

Stop re-looking up matches by id inside the React, Solid, and Vue Match components. Each adapter now reads the promise and pending state from its existing local match source, and the Vue store update expectations are adjusted to reflect the lower update count from that change.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

Refactored Match components across React, Solid, and Vue router packages to access pending promises directly from current match store state rather than re-looking up via router. Simplified pending-minimum handling by removing intermediate router lookups. Adjusted test expectations for store update counts.

Changes

Cohort / File(s) Summary
React Router Match Component
packages/react-router/src/Match.tsx
Replaced router.getMatch(match.id)?._nonReactive.* with direct reads from match._nonReactive for pending control promises. Removed extra router lookup in min-pending handling, now setting/clearing minPendingPromise directly on match store.
Solid Router Match Component
packages/solid-router/src/Match.tsx
Replaced router.getMatch(currentMatch().id)?._nonReactive.* with match()?._nonReactive.*. Renamed routerMatch to matchState and updated pending promise assignments to use context-derived match state directly.
Vue Router Match Component
packages/vue-router/src/Match.tsx
Replaced router.getMatch(match.value.id) with direct activeMatch.value access via local currentMatch variable. Updated redirect and pending paths to access promises directly from current match store.
Vue Router Test Updates
packages/vue-router/tests/store-updates-during-navigation.test.tsx
Adjusted expected store update counts: async loader/beforeLoad scenario from 16 to 14; sync beforeLoad scenario from 12 to 10.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Through stores and lookups, we hopped with grace,
Now matches speak directly, no router chase!
Three routers aligned in refactoring spree,
Pending promises flow more naturally—
Simpler, swifter, and cache-friendly! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main refactoring change: replacing router lookup patterns with direct local match references across React, Solid, and Vue adapter components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/use-local-match-in-adapters

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Mar 26, 2026

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 97d9842

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ❌ Failed 11m 12s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 28s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-26 22:16:40 UTC

@Sheraff Sheraff marked this pull request as draft March 26, 2026 22:04
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

No changeset entries found. Merging this PR will not cause a version bump for any packages.

@github-actions
Copy link
Copy Markdown
Contributor

Bundle Size Benchmarks

  • Commit: 0e0a2817c300
  • Measured at: 2026-03-26T22:06:13.691Z
  • Baseline source: history:70b222513720
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.51 KiB -18 B (-0.02%) 275.81 KiB 76.03 KiB ████▇▇▃▃▁▁▁▁
react-router.full 90.80 KiB -16 B (-0.02%) 286.99 KiB 78.88 KiB ▇███▇▇▂▂▁▁▁▁
solid-router.minimal 35.55 KiB -14 B (-0.04%) 107.16 KiB 31.95 KiB ████▅▅▅▅▁▁▁▁
solid-router.full 40.03 KiB -14 B (-0.03%) 120.70 KiB 35.88 KiB ▅███▃▃▃▃▂▂▂▁
vue-router.minimal 53.42 KiB -3 B (-0.01%) 153.15 KiB 47.97 KiB ██████▁▁▁▁▁▁
vue-router.full 58.28 KiB -6 B (-0.01%) 168.61 KiB 52.15 KiB ▆█████▂▂▁▁▁▁
react-start.minimal 102.01 KiB -19 B (-0.02%) 323.98 KiB 88.21 KiB ▆███▆▆▂▂▁▁▁▁
react-start.full 105.39 KiB -15 B (-0.01%) 334.33 KiB 91.12 KiB ▇███▆▆▂▂▁▁▁▁
solid-start.minimal 49.64 KiB -10 B (-0.02%) 153.35 KiB 43.73 KiB ████▄▄▄▄▁▁▁▁
solid-start.full 55.15 KiB -15 B (-0.03%) 169.58 KiB 48.49 KiB ▅███▃▃▃▃▂▂▂▁

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 26, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@7052

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@7052

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@7052

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@7052

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@7052

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@7052

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@7052

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@7052

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@7052

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@7052

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@7052

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@7052

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@7052

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@7052

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@7052

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@7052

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@7052

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@7052

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@7052

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@7052

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@7052

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@7052

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@7052

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@7052

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@7052

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@7052

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@7052

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@7052

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@7052

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@7052

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@7052

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@7052

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@7052

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@7052

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@7052

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@7052

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@7052

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@7052

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@7052

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@7052

commit: 97d9842

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 97d98428e9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
}
throw router.getMatch(match.id)?._nonReactive.loadPromise
throw match._nonReactive.loadPromise
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resolve pending suspense from current match pool

Use of match._nonReactive.loadPromise here can suspend on a stale promise when a new navigation starts before the current pending navigation finishes and both active/pending pools contain the same match.id. In that overlap, router updates and promise resolution target the pending pool first (updateMatch/getMatch behavior in router-core), so the active-store promise can be canceled or left stale while the live pending promise is elsewhere; throwing the active promise can keep the fallback stuck until a later remount instead of tracking the in-flight navigation.

Useful? React with 👍 / 👎.

await new Promise((r) => setTimeout(r, 0))
return router.getMatch(currentMatch().id)?._nonReactive
.loadPromise
return match()?._nonReactive.loadPromise
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Read loader promise from live pool in Solid pending path

This resource now reads match()?._nonReactive.loadPromise from the locally active match object, which has the same stale-promise problem during overlapping navigations with duplicate ids across active and pending pools. Because core load updates resolve promises on the pending pool entry first, binding the Suspense resource to the active object's promise can desynchronize the UI from the real in-flight load and prolong fallback rendering until the route tree is replaced.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/react-router/src/Match.tsx`:
- Around line 400-410: The timeout callback currently mutates the closed-over
match object by setting match._nonReactive.minPendingPromise = undefined, which
can leave stale state if the match is replaced; instead, when the timer fires
use the store/router API to clear the pending flag (e.g. call
matchStore.setState(...) or router.updateMatch(...) to set
_nonReactive.minPendingPromise to undefined for that match id) so the live store
is updated atomically rather than mutating the captured match object; locate the
timeout in the block that creates minPendingPromise and replace the direct
mutation with a store/router update using the match's identifier.

In `@packages/solid-router/src/Match.tsx`:
- Around line 301-316: The timeout callback is closing over the captured
matchState and clears matchState._nonReactive.minPendingPromise directly, which
can leave the live store holding stale state if the match object was replaced;
instead, when creating the minPendingPromise for matchState (from match()),
store its id and use router.updateMatch(matchId, updater) (or the store's update
method) inside the timeout to clear the minPendingPromise on the live match
object by id; locate the block around match(), createControlledPromise(), and
where _nonReactive.minPendingPromise is assigned and replace the direct mutation
in the setTimeout with a router.updateMatch keyed by matchState.id that sets
_nonReactive.minPendingPromise = undefined.

In `@packages/vue-router/src/Match.tsx`:
- Around line 422-437: The timeout currently mutates the captured
currentMatch._nonReactive.minPendingPromise directly which can leave stale state
if the router replaces the match; instead, inside the setTimeout callback
resolve the controlled promise but clear the minPendingPromise through the
router's match update API (e.g., call router.updateMatch(currentMatch.id, {
_nonReactive: { minPendingPromise: undefined } }) or use the match store update
function) using the currentMatch.id so the live store is updated atomically
rather than mutating the closed-over currentMatch object; keep creating and
assigning the controlled promise to currentMatch._nonReactive.minPendingPromise
before scheduling the timeout, but ensure the timeout uses router.updateMatch
(or equivalent) to clear it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f92cc9d0-f35f-4921-ab40-1f68c1ef2168

📥 Commits

Reviewing files that changed from the base of the PR and between 0e0a281 and 97d9842.

📒 Files selected for processing (4)
  • packages/react-router/src/Match.tsx
  • packages/solid-router/src/Match.tsx
  • packages/vue-router/src/Match.tsx
  • packages/vue-router/tests/store-updates-during-navigation.test.tsx

Comment on lines +400 to +410
if (!match._nonReactive.minPendingPromise) {
// Create a promise that will resolve after the minPendingMs
if (!(isServer ?? router.isServer)) {
const minPendingPromise = createControlledPromise<void>()

routerMatch._nonReactive.minPendingPromise = minPendingPromise
match._nonReactive.minPendingPromise = minPendingPromise

setTimeout(() => {
minPendingPromise.resolve()
// We've handled the minPendingPromise, so we can delete it
routerMatch._nonReactive.minPendingPromise = undefined
match._nonReactive.minPendingPromise = undefined
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Clear minPendingPromise through the store in the timeout.

At Lines 407-410, the callback mutates the closed-over match object. Match stores replace their state object on updates, so if this match is replaced before the timer fires, the live store keeps stale min-pending state and can remain forced-pending. Please clear it through matchStore.setState(...) or router.updateMatch(...) instead of mutating the captured object. The analogous SSR hydrate path already does this.

Suggested fix
           setTimeout(() => {
             minPendingPromise.resolve()
             // We've handled the minPendingPromise, so we can delete it
-            match._nonReactive.minPendingPromise = undefined
+            matchStore.setState((prev) => {
+              if (prev._nonReactive.minPendingPromise === minPendingPromise) {
+                prev._nonReactive.minPendingPromise = undefined
+                return { ...prev }
+              }
+              return prev
+            })
           }, pendingMinMs)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/src/Match.tsx` around lines 400 - 410, The timeout
callback currently mutates the closed-over match object by setting
match._nonReactive.minPendingPromise = undefined, which can leave stale state if
the match is replaced; instead, when the timer fires use the store/router API to
clear the pending flag (e.g. call matchStore.setState(...) or
router.updateMatch(...) to set _nonReactive.minPendingPromise to undefined for
that match id) so the live store is updated atomically rather than mutating the
captured match object; locate the timeout in the block that creates
minPendingPromise and replace the direct mutation with a store/router update
using the match's identifier.

Comment on lines +301 to +316
const matchState = match()
if (
routerMatch &&
!routerMatch._nonReactive.minPendingPromise
matchState &&
!matchState._nonReactive.minPendingPromise
) {
// Create a promise that will resolve after the minPendingMs
if (!(isServer ?? router.isServer)) {
const minPendingPromise = createControlledPromise<void>()

routerMatch._nonReactive.minPendingPromise =
matchState._nonReactive.minPendingPromise =
minPendingPromise

setTimeout(() => {
minPendingPromise.resolve()
// We've handled the minPendingPromise, so we can delete it
routerMatch._nonReactive.minPendingPromise = undefined
matchState._nonReactive.minPendingPromise = undefined
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Clear min-pending state against the live match, not the captured matchState.

At Lines 313-316, the timer closes over matchState and mutates _nonReactive directly. If the match store swaps to a newer state object before this fires, the cleanup hits an orphaned match while the live one keeps stale min-pending state. Please route this through router.updateMatch(...) (or the underlying store) keyed by matchState.id.

Suggested fix
                     if (!(isServer ?? router.isServer)) {
                       const minPendingPromise = createControlledPromise<void>()
+                      const matchId = matchState.id
 
                       matchState._nonReactive.minPendingPromise =
                         minPendingPromise
 
                       setTimeout(() => {
                         minPendingPromise.resolve()
                         // We've handled the minPendingPromise, so we can delete it
-                        matchState._nonReactive.minPendingPromise = undefined
+                        router.updateMatch(matchId, (prev) => {
+                          if (
+                            prev._nonReactive.minPendingPromise ===
+                            minPendingPromise
+                          ) {
+                            prev._nonReactive.minPendingPromise = undefined
+                            return { ...prev }
+                          }
+                          return prev
+                        })
                       }, pendingMinMs)
                     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/solid-router/src/Match.tsx` around lines 301 - 316, The timeout
callback is closing over the captured matchState and clears
matchState._nonReactive.minPendingPromise directly, which can leave the live
store holding stale state if the match object was replaced; instead, when
creating the minPendingPromise for matchState (from match()), store its id and
use router.updateMatch(matchId, updater) (or the store's update method) inside
the timeout to clear the minPendingPromise on the live match object by id;
locate the block around match(), createControlledPromise(), and where
_nonReactive.minPendingPromise is assigned and replace the direct mutation in
the setTimeout with a router.updateMatch keyed by matchState.id that sets
_nonReactive.minPendingPromise = undefined.

Comment on lines 422 to 437
if (
pendingMinMs &&
routerMatch &&
!routerMatch._nonReactive.minPendingPromise
currentMatch &&
!currentMatch._nonReactive.minPendingPromise
) {
// Create a promise that will resolve after the minPendingMs
if (!(isServer ?? router.isServer)) {
const minPendingPromise = createControlledPromise<void>()

routerMatch._nonReactive.minPendingPromise = minPendingPromise
currentMatch._nonReactive.minPendingPromise = minPendingPromise

setTimeout(() => {
minPendingPromise.resolve()
// We've handled the minPendingPromise, so we can delete it
routerMatch._nonReactive.minPendingPromise = undefined
currentMatch._nonReactive.minPendingPromise = undefined
}, pendingMinMs)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid clearing min-pending state on the captured currentMatch.

At Lines 433-436, the timeout mutates currentMatch._nonReactive directly. If the router replaces that match object before the timer fires, the live store keeps stale min-pending state. Please clear it via router.updateMatch(...) (or the match store) keyed by the current match id instead of mutating the closed-over object.

Suggested fix
         if (
           pendingMinMs &&
           currentMatch &&
           !currentMatch._nonReactive.minPendingPromise
         ) {
+          const matchId = currentMatch.id
           // Create a promise that will resolve after the minPendingMs
           if (!(isServer ?? router.isServer)) {
             const minPendingPromise = createControlledPromise<void>()
 
             currentMatch._nonReactive.minPendingPromise = minPendingPromise
 
             setTimeout(() => {
               minPendingPromise.resolve()
               // We've handled the minPendingPromise, so we can delete it
-              currentMatch._nonReactive.minPendingPromise = undefined
+              router.updateMatch(matchId, (prev) => {
+                if (prev._nonReactive.minPendingPromise === minPendingPromise) {
+                  prev._nonReactive.minPendingPromise = undefined
+                  return { ...prev }
+                }
+                return prev
+              })
             }, pendingMinMs)
           }
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vue-router/src/Match.tsx` around lines 422 - 437, The timeout
currently mutates the captured currentMatch._nonReactive.minPendingPromise
directly which can leave stale state if the router replaces the match; instead,
inside the setTimeout callback resolve the controlled promise but clear the
minPendingPromise through the router's match update API (e.g., call
router.updateMatch(currentMatch.id, { _nonReactive: { minPendingPromise:
undefined } }) or use the match store update function) using the currentMatch.id
so the live store is updated atomically rather than mutating the closed-over
currentMatch object; keep creating and assigning the controlled promise to
currentMatch._nonReactive.minPendingPromise before scheduling the timeout, but
ensure the timeout uses router.updateMatch (or equivalent) to clear it.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 26, 2026

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing refactor/use-local-match-in-adapters (97d9842) with main (70b2225)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (0e0a281) during the generation of this report, so 70b2225 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant