[PR #99] [MERGED] fix: use AsyncLocalStorage.run() for request context isolation #309

Closed
opened 2026-05-06 12:39:06 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/99
Author: @southpolesteve
Created: 2/26/2026
Status: Merged
Merged: 2/26/2026
Merged by: @southpolesteve

Base: mainHead: fix/als-run-wrapping


📝 Commits (1)

  • cc6389e fix: use AsyncLocalStorage.run() for request context isolation

📊 Changes

10 files changed (+191 additions, -193 deletions)

View changed files

📝 packages/vinext/src/index.ts (+15 -4)
📝 packages/vinext/src/server/app-dev-server.ts (+38 -30)
📝 packages/vinext/src/server/dev-server.ts (+19 -12)
📝 packages/vinext/src/shims/cache-runtime.ts (+19 -15)
📝 packages/vinext/src/shims/cache.ts (+20 -15)
📝 packages/vinext/src/shims/fetch-cache.ts (+2 -3)
📝 packages/vinext/src/shims/head-state.ts (+18 -15)
📝 packages/vinext/src/shims/headers.ts (+25 -49)
📝 packages/vinext/src/shims/navigation-state.ts (+19 -29)
📝 packages/vinext/src/shims/router-state.ts (+16 -21)

📄 Description

Summary

Replaces enterWith() with run() across all AsyncLocalStorage-backed state modules to ensure per-request state is properly scoped. enterWith() is not supported on all runtimes (notably Cloudflare Workers), and the fallback pattern was not concurrency-safe.

What changed:

  • All 6 state modules (headers.ts, navigation-state.ts, router-state.ts, head-state.ts, cache.ts, cache-runtime.ts) now use _als.run(state, fn) instead of _enterWith() + fallback globals
  • Each module exports a runWith*() function that creates a scoped ALS context
  • The withFetchCache() init/cleanup pattern is removed; only runWithFetchCache() remains
  • All three entry points (Pages Router dev, Pages Router prod, App Router dev) wrap request handlers in a consistent nested runWith*() chain
  • SSR entry gets its own runWithNavigationContext scope since it runs in a separate Vite environment with separate module instances
  • State accessors now throw if called outside a request scope instead of silently returning stale fallback data

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/99 **Author:** [@southpolesteve](https://github.com/southpolesteve) **Created:** 2/26/2026 **Status:** ✅ Merged **Merged:** 2/26/2026 **Merged by:** [@southpolesteve](https://github.com/southpolesteve) **Base:** `main` ← **Head:** `fix/als-run-wrapping` --- ### 📝 Commits (1) - [`cc6389e`](https://github.com/cloudflare/vinext/commit/cc6389e956d3d3d5a055b4f690209ebc9d3ef09f) fix: use AsyncLocalStorage.run() for request context isolation ### 📊 Changes **10 files changed** (+191 additions, -193 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/index.ts` (+15 -4) 📝 `packages/vinext/src/server/app-dev-server.ts` (+38 -30) 📝 `packages/vinext/src/server/dev-server.ts` (+19 -12) 📝 `packages/vinext/src/shims/cache-runtime.ts` (+19 -15) 📝 `packages/vinext/src/shims/cache.ts` (+20 -15) 📝 `packages/vinext/src/shims/fetch-cache.ts` (+2 -3) 📝 `packages/vinext/src/shims/head-state.ts` (+18 -15) 📝 `packages/vinext/src/shims/headers.ts` (+25 -49) 📝 `packages/vinext/src/shims/navigation-state.ts` (+19 -29) 📝 `packages/vinext/src/shims/router-state.ts` (+16 -21) </details> ### 📄 Description ## Summary Replaces `enterWith()` with `run()` across all AsyncLocalStorage-backed state modules to ensure per-request state is properly scoped. `enterWith()` is not supported on all runtimes (notably Cloudflare Workers), and the fallback pattern was not concurrency-safe. **What changed:** - All 6 state modules (`headers.ts`, `navigation-state.ts`, `router-state.ts`, `head-state.ts`, `cache.ts`, `cache-runtime.ts`) now use `_als.run(state, fn)` instead of `_enterWith()` + fallback globals - Each module exports a `runWith*()` function that creates a scoped ALS context - The `withFetchCache()` init/cleanup pattern is removed; only `runWithFetchCache()` remains - All three entry points (Pages Router dev, Pages Router prod, App Router dev) wrap request handlers in a consistent nested `runWith*()` chain - SSR entry gets its own `runWithNavigationContext` scope since it runs in a separate Vite environment with separate module instances - State accessors now throw if called outside a request scope instead of silently returning stale fallback data --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 12:39:06 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#309
No description provided.