Refactor fetchStrategy -> stage and completeness (#99706)
This is a refactor of the FetchStrategy type.
As the Partial Prefetching design has evolved, FetchStrategy has come to
represent two independent concepts, which we now model separately: the
_stage_ (AppStage) of the navigation that an entry was rendered through
(shell, prefetch, or navigation), and the _completeness_ (Completeness)
of the rendering through that stage (needs runtime request, cache
complete but with dynamic holes, or fully complete with no dynamic
holes). Everywhere that used to accept a FetchStrategy now accepts
either one or both of these types.
(Note: I've called the type AppStage to distinguish it from the internal
stages used on the server as part of the rendering algorithm. The stages
used on the client are the ones we document publicly as part of
`ensureStatic` and the `prefetch()` and `navigation()` APIs.)
The `completeness` field also replaces the `isPartial` field.
It's possible to express much of the logic using a single enum, as in
the FetchStrategy model. To prove this, I've extracted most of the
behavioral changes into earlier PRs, to make this one easier to review.
But the resulting logic in the new model should be easier to follow. So
on net, we have the same number of fields but expressed in a way that
better fits the underlying design:
- Every prefetch task (e.g. a visible Link) has a target stage and level
of completeness. The task finishes when the cache has entries that match
_both_ targets.
- When deciding whether to overwrite an existing entry, a more less
complete entry must never overwrite a less complete one, even if it
represents a later rendering stage. For example, a response rendered at
the Navigation stage cannot overwrite a response written at the Prefetch
stage if it does not include cookie-dependent data; we must discard it
and perform a new request.
---------
Co-authored-by: sparkly-dev <338975655+sparkly-dev@users.noreply.github.com>