next.js
de37cd73 - Track `searchParams` access through a Proxy to catch missing-key reads (#93549)

Commit
1 day ago
Track `searchParams` access through a Proxy to catch missing-key reads (#93549) Under `experimental.varyParams`, when a page reads `searchParams` from a URL without a query string, `createVaryingSearchParams` previously returned a plain object whose only own properties were getters for keys that already existed in the URL. With no keys present, that's an empty `{}` — so `Object.entries`, spread, `in` checks, and missing-key reads (e.g. `searchParams.foo` returning `undefined`) all silently no-opped without registering an access. The segment ended up keyed at the `Fallback` search slot in the segment cache, where it shadowed subsequent prefetches with non-empty search params via `Fallback` resolution, silently serving the stale empty-query cache entry on navigation. This switches the implementation to a `Proxy` with `get`, `has`, and `ownKeys` traps that record the `'?'` sentinel on every string access. Search params have no fixed schema, so any access — including missing-key reads, `in` checks, and enumeration — must register as varying. The `get` trap has one carve-out: `.then` reads are skipped when no `then` key exists on the target, since `Promise.resolve` and React Flight probe `.then` to test thenability and those probes shouldn't count as user dependencies. As a trade-off, a page that reads `searchParams.then` to compute its output and is prefetched without a `then` key won't register the access — accepted because `then` is reserved by the Promise protocol and essentially never used as a query parameter name. The added regression test prefetches the no-query URL first and asserts that a subsequent `?foo=1` prefetch still triggers a fresh request. Without the fix the lookup resolves to the empty-query cache entry through `Fallback`, no request is initiated, and the test times out waiting for one.
Author
Parents
Loading