final final pt2 final

pull/17350/head
Elliott Johnson 1 week ago
parent 794403ddb0
commit 2d05f7479a

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

Loading…
Cancel
Save