feat(after): allow request APIs in after (actions/handlers) (#73345)
This PR relaxes some of the limitations around calling request APIs
(`headers()`, `cookies()`, `connection()`) inside `unstable_after`
(which was previously blanket-forbidden since #71231).
We're now allowing it in server actions and route handlers[1]:
```tsx
// route.ts ✅
export function POST() {
unstable_after(async () => console.log(await headers()));
}
```
```tsx
// action.ts ✅
export function myAction() {
"use server"
unstable_after(async () => console.log(await headers()));
}
```
however using it in server components remains banned:
```tsx
// page.tsx ❌
export default function Page() {
unstable_after(async () => console.log(await headers()));
}
```
### Implementation notes
The way to detect actions and route handlers is to check if
`workUnitStore.phase === "action"` [2]. But we can't use the existing
`workUnitStore.phase` for this because it's deliberately mutable, so
it'd have changed by the time we get to executing the callbacks and the
actual `headers()` call.
To solve this, I'm introducing a new ALS store - `afterTaskStore`. It
currently only stores the phase that the (topmost) `after` was called
in. But this info is also specific to each "task"/callback (or rather,
task chain -- nested afters inherit the context of their parents), so we
can't use any of the existing stores.
I 'm also going to need task-specific info for upcoming devtools work
(more useful callstacks, see
https://github.com/vercel/next.js/blob/54465dbe782f505fd0105258d2d053a6439457ed/packages/next/src/server/app-render/after-task-async-storage.external.ts#L14),
so i think introducing a new store is justified.
---
[1] - Note that if it's in a prerendered GET handler (with `dynamic =
'error'`), `headers()` & co. will still error, but that's because
they're dynamic, not because they were called within `after`!
[2] - `actionAsyncStorage` is a no-go, because `actionStore.isAction`
can remain true in the render triggered by an action (or in promises
passed into it), which was the reason we introduced `phase` in the first
place.