Encode the cache item name built by `unstable_cache` (#96937)
A cache implementation may serialize cache metadata into HTTP request
headers, whose values are limited to Latin-1. `unstable_cache` assembles
a cache item name from the request URL and the name of the cached
callback, and neither part was encoded. When that name holds a character
above U+00FF the conversion throws before the request is dispatched, so
the read never reaches the cache and the write that follows it fails the
same way. Nothing is stored, nothing is found, and the entry falls back
to the origin on every render.
The name is built by `getFetchUrlPrefix`, which reads the pathname and
the search parameters out of the request URL. The pathname stays
percent-encoded, but `URLSearchParams` returns decoded keys and values,
so a non-ASCII query parameter is the reachable case: it applies to any
dynamic route that calls `unstable_cache`, whether or not the route
reads `searchParams`, and therefore also to a parameter a caller
appends. A callback whose name holds such a character is affected too,
though a production build usually renames the binding.
This change encodes the assembled name with `encodeHeaderSafe`. That
helper only replaces characters outside the class Node accepts in a
header value, so the separating spaces and the URL punctuation are
preserved and the name keeps its documented shape. Every name that is
representable today is returned unchanged, so this is inert for existing
entries. The item name is a label: it is not the cache key, which is
derived separately from the callback's key parts and arguments, and the
Suspense Cache API neither parses nor matches on it.
The test covers the two parts of the name on separate routes so a
failure names the part it comes from, and asserts the constraint rather
than either input, since which inputs are live depends on the bundler
and on minification. A deployment checks it through the real cache
handler implementation, where the failure shows up as an entry that is
recomputed on every request.
fixes #76286