mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[PR #1081] [MERGED] refactor(als): dedupe AsyncLocalStorage globalThis registration #1078
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#1078
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/cloudflare/vinext/pull/1081
Author: @james-elicx
Created: 5/5/2026
Status: ✅ Merged
Merged: 5/5/2026
Merged by: @james-elicx
Base:
main← Head:refactor/dedupe-als-registration📝 Commits (1)
4d0d56erefactor(als): dedupe AsyncLocalStorage globalThis registration📊 Changes
11 files changed (+77 additions, -46 deletions)
View changed files
📝
packages/vinext/src/shims/cache-runtime.ts(+3 -8)📝
packages/vinext/src/shims/cache.ts(+3 -7)📝
packages/vinext/src/shims/fetch-cache.ts(+2 -4)📝
packages/vinext/src/shims/head-state.ts(+2 -3)📝
packages/vinext/src/shims/headers.ts(+3 -4)📝
packages/vinext/src/shims/i18n-state.ts(+2 -3)➕
packages/vinext/src/shims/internal/als-registry.ts(+53 -0)📝
packages/vinext/src/shims/navigation-state.ts(+2 -4)📝
packages/vinext/src/shims/request-context.ts(+2 -5)📝
packages/vinext/src/shims/router-state.ts(+2 -4)📝
packages/vinext/src/shims/unified-request-context.ts(+3 -4)📄 Description
Summary
Extracts the repeated
Symbol.for(...) + globalThis ??= new AsyncLocalStorage<T>()pattern into a single helper,
getOrCreateAls<T>(key: string), inpackages/vinext/src/shims/internal/als-registry.ts.The pattern was inlined in 12 sites across 10 modules:
shims/headers.ts—vinext.nextHeadersShim.alsshims/cache.ts—vinext.cache.als,vinext.unstableCache.alsshims/cache-runtime.ts—vinext.cacheRuntime.contextAls(exported),vinext.cacheRuntime.privateAlsshims/fetch-cache.ts—vinext.fetchCache.alsshims/request-context.ts—vinext.requestContext.alsshims/unified-request-context.ts—vinext.unifiedRequestContext.alsshims/router-state.ts—vinext.router.alsshims/i18n-state.ts—vinext.i18n.alsshims/head-state.ts—vinext.head.alsshims/navigation-state.ts—vinext.navigation.alsThe 12 sites used identical structure: same
Symbol.for(key)registry-sidelookup, same
??=semantics, same fallback-typeAsyncLocalStorage<T>().No site initialised the ALS with a sentinel store value or wrapped it in a
container object — they were all clean candidates.
Net: 11 files changed, +77/-46 (the new helper module is the bulk of
+77; call sites collapse from 4 lines to 1).Cross-bundle singleton property — preserved
This is the load-bearing invariant for ALS bugs and is the reason the
inline pattern existed in the first place. The helper preserves it:
Symbol.for(key)consults the global symbol registry and returns thesame symbol no matter which module instance calls it.
globalThis[sym]is one slot shared by every module instance.??=only assigns when the slot is empty, so the first caller wins andevery later caller (in any module instance, in any Vite environment)
reads the same
AsyncLocalStorageinstance.The helper module itself never closes over the ALS — it always
round-trips through
globalThis. So even ifals-registry.tsis loadedunder multiple specifiers (Vite RSC/SSR/client environments, HMR), every
copy hands back the one true ALS for a given key. There is no new
"ownership-by-reference" layer introduced by the helper.
The unrelated
_FALLBACK_KEY/_fallbackStatepattern in some shims(plain-object cross-bundle singletons with shape varying per call site)
is intentionally left inline.
Files changed
packages/vinext/src/shims/internal/als-registry.ts(new)packages/vinext/src/shims/headers.tspackages/vinext/src/shims/cache.tspackages/vinext/src/shims/cache-runtime.tspackages/vinext/src/shims/fetch-cache.tspackages/vinext/src/shims/request-context.tspackages/vinext/src/shims/unified-request-context.tspackages/vinext/src/shims/router-state.tspackages/vinext/src/shims/i18n-state.tspackages/vinext/src/shims/head-state.tspackages/vinext/src/shims/navigation-state.tsFollow-up to #1058.
Test plan
pnpm fmt --writeon touched filesnpx tsc --noEmitinpackages/vinext— cleanpnpm knip— cleanpnpm vp test runforapp-router,pages-router,cache-control,cache-for-request,fetch-cache,head,request-context,unified-request-context,pages-router-concurrency— 683 tests passing. The single suite-level failure (pages-router.test.ts > allowedDevOrigins configafterAlltimeout) reproduces on cleanmainwith the changes stashed; it is a pre-existing flaky teardown unrelated to this refactor.🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.