From 2d05f7479a0332cc8ab1942a9792bffbbe7c53e3 Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Thu, 11 Dec 2025 17:47:48 -0700 Subject: [PATCH] final final pt2 final --- .../src/internal/server/render-context.js | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/svelte/src/internal/server/render-context.js b/packages/svelte/src/internal/server/render-context.js index fd350b9cd2..cbd01d4b51 100644 --- a/packages/svelte/src/internal/server/render-context.js +++ b/packages/svelte/src/internal/server/render-context.js @@ -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 | null} */ @@ -56,24 +56,32 @@ export async function with_render_context(fn) { /** @type {AsyncLocalStorage | null} */ let als = null; -/** @ts-ignore - we don't include node types in the production build */ -/** @type {Promise | null} */ +/** @type {Promise | null} */ let als_import = null; +let resolved_promise = null; -export async function init_render_context() { - if (als !== null) return; - try { - // 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(); - }); - await als_import; - } catch {} +/** + * + * @returns {Promise} + */ +export function init_render_context() { + if (als === null) { + try { + // 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); + 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