fix: race condition when importing `AsyncLocalStorage` (#17350)

* fix: race condition when importing `AsyncLocalStorage`

* types:

* tweak

* remove a line

* comment

* dumb esbuild

* final final pt2 final

* ugh
pull/17353/head
Elliott Johnson 2 days ago committed by GitHub
parent a544a9d5f3
commit 00459a1d78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: race condition when importing `AsyncLocalStorage`

@ -2,7 +2,7 @@
/** @import { AsyncLocalStorage } from 'node:async_hooks' */
/** @import { RenderContext } from '#server' */
import { deferred } from '../shared/utils.js';
import { deferred, noop } from '../shared/utils.js';
import * as e from './errors.js';
/** @type {Promise<void> | null} */
@ -56,14 +56,26 @@ export async function with_render_context(fn) {
/** @type {AsyncLocalStorage<RenderContext | null> | null} */
let als = null;
/** @type {Promise<void> | null} */
let als_import = null;
export async function init_render_context() {
if (als !== null) return;
try {
// @ts-ignore -- we don't include node types in the production build
const { AsyncLocalStorage } = await import('node:async_hooks');
als = new AsyncLocalStorage();
} catch {}
/**
*
* @returns {Promise<void>}
*/
export function init_render_context() {
// It's important the right side of this assignment can run a maximum of one time
// otherwise it's possible for a very, very well-timed race condition to assign to `als`
// at the beginning of a render, and then another render to assign to it again, which causes
// the first render's second half to use a new instance of `als` which doesn't have its
// context anymore.
// @ts-ignore -- we don't include node types in the production build
als_import ??= import('node:async_hooks')
.then((hooks) => {
als = new hooks.AsyncLocalStorage();
})
.then(noop, noop);
return als_import;
}
// this has to be a function because rollup won't treeshake it if it's a constant

@ -164,6 +164,7 @@ async function run_test(
}
],
bundle: true,
platform: 'node',
format: 'iife',
globalName: 'test_ssr'
});

Loading…
Cancel
Save