Repository navigation
fix: preserve AsyncLocalStorage context in esbuild plugin callbacks #273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -270,6 +270,25 @@ export function getCurrentRequestContext(): RequestContext | null { | |
| return asyncLocalStorage.getStore() ?? null; | ||
| } | ||
|
|
||
| /** | ||
| * Wraps a callback to preserve the current AsyncLocalStorage context. | ||
| * | ||
| * esbuild communicates with its Go binary via a child process. When esbuild's | ||
| * plugin callbacks (onResolve, onLoad) fire, they run in the child process's | ||
| * message handler context, which does NOT inherit the AsyncLocalStorage store | ||
| * from the original caller. This utility captures the current store and | ||
| * re-enters it inside the callback, so that `getAdapter()` can resolve the | ||
| * correct per-project adapter. | ||
| */ | ||
| export function wrapWithCurrentContext<T extends (...args: never[]) => unknown>(fn: T): T { | ||
| const store = asyncLocalStorage.getStore(); | ||
| if (!store) return fn; | ||
|
|
||
| return ((...args: Parameters<T>) => { | ||
| return asyncLocalStorage.run(store, () => fn(...args)); | ||
| }) as unknown as T; | ||
| } | ||
|
Comment on lines
+273
to
+290
|
||
|
|
||
| export function getRequestScopedFile(cacheKey: string): string | undefined { | ||
| return asyncLocalStorage.getStore()?.fileCache?.get(cacheKey); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrapWithCurrentContextis typed asT extends (...args: never[]) => unknown, which effectively constrains callbacks to accept no arguments. This will not type-check when wrapping callbacks like esbuildonLoadhandlers that require parameters (and can cause callers to need unsafe casts). Update the generic to accept arbitrary parameters (e.g.,T extends (...args: unknown[]) => unknown) while preservingParameters<T>/ReturnType<T>so wrapped functions remain type-safe.