Skip to content

Commit 7e84789

Browse files
authored
fix: ensure rendering starts off synchronously (#14517)
We have to invoke .then eagerly here in order to kick off rendering: it's only starting on access, and `await maybe_promise` would eagerly access the .then property but call its function only after a tick, which is too late for the paths.reset() below and for any eager getRequestEvent() calls during rendering without AsyncLocalStorage available. Fixes https://github.com/sveltejs/svelte/issues/16788
1 parent c1653ef commit 7e84789

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

.changeset/flat-ducks-attack.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: ensure rendering starts off synchronously

packages/kit/src/exports/internal/event.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,17 @@ export function getRequestEvent() {
4545
export function get_request_store() {
4646
const result = try_get_request_store();
4747
if (!result) {
48-
throw new Error('Could not get the request store. This is an internal error.');
48+
let message = 'Could not get the request store.';
49+
50+
if (als) {
51+
message += ' This is an internal error.';
52+
} else {
53+
message +=
54+
' In environments without `AsyncLocalStorage`, the request store (used by e.g. remote functions) must be accessed synchronously, not after an `await`.' +
55+
' If it was accessed synchronously then this is an internal error.';
56+
}
57+
58+
throw new Error(message);
4959
}
5060
return result;
5161
}

packages/kit/src/runtime/server/page/render.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,16 @@ export async function render_response({
205205
// portable as possible, but reset afterwards
206206
if (paths.relative) paths.override({ base, assets });
207207

208-
const rendered = options.root.render(props, render_opts);
208+
const maybe_promise = options.root.render(props, render_opts);
209+
// We have to invoke .then eagerly here in order to kick off rendering: it's only starting on access,
210+
// and `await maybe_promise` would eagerly access the .then property but call its function only after a tick, which is too late
211+
// for the paths.reset() below and for any eager getRequestEvent() calls during rendering without AsyncLocalStorage available.
212+
const rendered =
213+
options.async && 'then' in maybe_promise
214+
? /** @type {ReturnType<typeof options.root.render> & Promise<any>} */ (
215+
maybe_promise
216+
).then((r) => r)
217+
: maybe_promise;
209218

210219
// TODO 3.0 remove options.async
211220
if (options.async) {

0 commit comments

Comments
 (0)