[Cache Components] separate runtime stage in dev render (#84644)
This PR extends dev rendering with an extra stage - Runtime, where we
resolve Runtime APIs (`cookies()`, `params`, etc), but not dynamic APIs
(e.g. `connection()`, uncached fetches). This separation requires some
changes to `makeDevtoolsIOPromise` and other tasky delay code that we've
had in place before.|
I've implemented this as `StagedRenderingController` (generally accessed
via `requestStore.stagedRendering`), which allows creating promises that
resolve in the correct stage.
```ts
stagedRendering.delayUntilStage(RenderStage.Runtime, cookiesObject) // resolves in the runtime stage
stagedRendering.delayUntilStage(RenderStage.Dynamic, somethingDynamic) // resolves in the dynamic stage
```
Notably, in the case where the initial render has cache misses and we
only use it as a cache warmup, we can also use this to _not_ resolve
dynamic promises, which saves us from doing some unncecessary (uncached)
work. This means that, if the render ends up being a warmup, dynamic
promises can be left hanging (and later aborted), similar to how
`makeHangingPromise` works in a prerender.
For simplicity and compatibility with other codepaths, most callsites
that need a staged promise still use `makeDevtoolsIOAwarePromise`, but
now they pass in a stage argument to control the timing if we are
rendering with stages.
---
Based on the stage, we now add a third environment label -- "Prefetch",
to correspond with runtime prefetches. This label is currently applied
even if there's no prefetch config in place, which is a bit confusing,
and will be addressed in a follow-up (if there's no runtime prefetch
config, we want to label runtime logs as "Server" even if they run in a
separate stage).