Properly handle hanging promise rejections during prerendering (#81754)
We are using hanging promises for excluding request-specific data from a
prerender. When prerendering is aborted, we reject all hanging promises.
In dev mode, React uses these rejections to construct more detailed
owner stacks. This allows us to provide better errors during the
prerender validation.
For this to work reliably, we need to ensure that all hanging promises
are rejected after React's rendering is aborted. However, some hanging
promises are created before React starts rendering (when creating the
RSC component tree). Furthermore, for memory reasons, the first hanging
promise adds a single abort listener that's shared with all subsequent
hanging promises (see #77480). In this case, the shared abort listener
for rejections is added before React can add its own abort listener.
When using the same abort signal for both the React render and the
hanging promises, the hanging promises would be rejected too early,
preventing React from properly constructing the owner stacks.
To ensure that the order of operations is correct, we now use a separate
abort signal for React's rendering that is aborted before the "render
signal" [^1], which is used by the hanging promises, is aborted. For
parity, we're doing this not only in dev mode but also in production
mode, so that the hanging promise rejection handling is always the same.
Technically, I don't think this change is necessary for the SSR
prerender pass, but it felt cleaner to apply it there as well. However,
we could revisit that when we properly split the two prerender stores.
For example, the `cacheSignal` and `prerenderResumeDataCache` also don't
need to be present on the client prerender store.
Reverts #81501.
[^1]: This is an unfortunate name clash. We could also call this one
"cache signal", which would be in line with `React.cacheSignal()` – its
potential successor. But that clashes with our current `cacheSignal`,
which tracks the cache reads. We might revisit this naming problem in a
future PR.