Handle a purged browser cache on back navigation (#94317)
When the browser's HTTP cache entry for a back-navigation target has
been evicted between forward visit and back-press — for example with a
long-lived tab, storage pressure, or a manual cache clear — the browser
re-fetches the document fresh from the server. Previously we relied on
`type === 'back_forward'` alone to decide that the document came from
cache, which meant we treated those re-fetches as cache restores too.
The persisted-chunk lookup would miss on the fresh response, and we'd
recover with an unnecessary `location.reload()`.
The same edge case is exposed by the Playwright/WebKit combination in
the upstack PR: bfcache isn't utilized there, so back-navigations always
come over the network, and the old single-signal check classified those
re-fetches as served-from-cache and triggered the same unnecessary
reload.
With this change we split the cache-restore detection into two phases.
At script-execution time we look at `deliveryType` (Chrome ≥109, Safari
≥17) and the navigation entry's `transferSize`/`encodedBodySize` to
decide cache-restore vs fresh-response when those fields are populated.
When the body bytes haven't been measured yet — the common case for
streaming Next.js dev RSC responses on every browser, and also WebKit
leaving both size fields at zero at exec time — we suspend the readable
until `pageshow` and re-check there. On a fresh re-fetch we route
through the live WebSocket-backed channel, which already has the debug
data for the new response, and skip the reload entirely.
The new `bfcache-regression` test exercises this edge case on Chromium
by clearing the browser cache via CDP between the forward and back
navigations, using a new `clearBrowserCache()` helper on the test
browser wrapper. The same exec-time code path is naturally hit by Safari
whenever its navigation entry's size fields are still zero at
script-execution time, but the harness can't force the eviction
deterministically there.