Files
Andrew Clark 5dc3ae1fe7 Fix Nav Inspector request loop on repeat captures (#97050)
## Summary

Repro (from #96692): enable the Nav Inspector, click a `<Link
prefetch={true}>`, close the inspector, navigate home, re-enable it, and
click the same link. The app hung in a pending "Compiling..." state
while firing prefetch requests in an infinite loop (~30/sec).

The Instant Navigation Testing lock restricted navigation reads to
entries created within the current lock scope (`ownedEntries`), enforced
as a post-hoc filter after the cache lookup. But the segment cache
resolves lookups by most-specific-match, so a previous scope's
runtime-prefetch entries at concrete param keypaths kept winning the
lookup, the filter kept rejecting them, and the locked prefetch created
its replacement at a more generic keypath that could never win — every
scheduler pass discarded and refetched forever.

Rather than patch the filter, this replaces the `ownedEntries`
mechanism:

- Each lock scope owns a private segment `CacheMap` that starts empty
and is discarded at release, so a captured navigation structurally
observes only data fetched under the lock — cross-scope shadowing
becomes impossible by construction.
- The map is an explicit capability bound when work is created: a
prefetch task captures its map when scheduled
(`PrefetchTask.segmentCacheMap` — the single place that consults lock
state), a locked navigation inherits its driving task's map, and
everything else — unlocked navigations, hydration, refreshes,
traversals, server actions and patches — binds to the shared map. Reads
and response writes receive the map explicitly, so a request that
straddles a scope boundary still writes into the map its entries live
in.

In production builds without the testing API this compiles down to the
previous single-map behavior.

Includes the failing test from #96692 (thanks @samselikoff), hardened to
use the retry-based panel-reopen helper the sibling tests use.

## Verification

- `pnpm test-dev-turbo
test/development/app-dir/instant-navs-devtools/instant-navs-devtools.test.ts`
(32/32, includes the new regression test)
- `pnpm test-dev-webpack
test/development/app-dir/instant-navs-devtools/instant-navs-devtools.test.ts
-t "repeat clicks"`
- `pnpm test-dev-turbo
test/e2e/app-dir/instant-navigation-testing-api/instant-navigation-testing-api.test.ts`
- `pnpm test-start-turbo
test/e2e/app-dir/instant-navigation-testing-api/instant-navigation-testing-api.test.ts`
- `pnpm test-start-turbo
test/e2e/app-dir/segment-cache/basic/segment-cache-basic.test.ts`
(production paths unregressed)

<!-- NEXT_JS_LLM -->

---------

Co-authored-by: Sam Selikoff <sam.selikoff@gmail.com>
2026-08-10 20:39:29 +00:00
..