From 89b6a939fe40ac657f27219d29c601fa67202eed Mon Sep 17 00:00:00 2001 From: Paolo Ricciuti Date: Tue, 5 May 2026 20:48:50 +0200 Subject: [PATCH] fix: wrap `Promise.all` in `save` during SSR (#18178) Closes #18168 Not sure if there's a deeper issue in play because the error it's only really there if you also add a title to the component. I think the issue is that with multiple arguments the top level `Promise.all` is not wrapped in `save` and that probably causes a race condition with `title` that sets the context back to `null` in a `finally`. One issue is that now the generated code looks like this ```js const [$$0, $$1] = (await $.save(Promise.all([ (async () => (await $.save(user()))().name)(), (async () => (await $.save(user()))().image)() ])))(); ``` which seems a bit redundant, but I'm not sure if we can get rid of the inner `save` since they are indeed awaiting something. --- .changeset/tough-knives-smell.md | 5 +++++ .../3-transform/server/visitors/shared/utils.js | 4 ++-- .../samples/async-multiple-attrs/_config.js | 8 ++++++++ .../samples/async-multiple-attrs/_expected.html | 1 + .../async-multiple-attrs/_expected_head.html | 1 + .../samples/async-multiple-attrs/main.svelte | 15 +++++++++++++++ 6 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 .changeset/tough-knives-smell.md create mode 100644 packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_config.js create mode 100644 packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_expected.html create mode 100644 packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_expected_head.html create mode 100644 packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/main.svelte diff --git a/.changeset/tough-knives-smell.md b/.changeset/tough-knives-smell.md new file mode 100644 index 0000000000..7687188c1a --- /dev/null +++ b/.changeset/tough-knives-smell.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: wrap `Promise.all` in `save` during SSR diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js index a87642bc4c..9b3ac3ad78 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js @@ -12,7 +12,7 @@ import { import * as b from '#compiler/builders'; import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js'; import { regex_whitespaces_strict } from '../../../../patterns.js'; -import { has_await_expression } from '../../../../../utils/ast.js'; +import { has_await_expression, save } from '../../../../../utils/ast.js'; import { ExpressionMetadata } from '../../../../nodes.js'; /** Opens an if/each block, so that we can remove nodes in the case of a mismatch */ @@ -360,7 +360,7 @@ export class PromiseOptimiser { return b.const( b.array_pattern(this.expressions.map((_, i) => b.id(`$$${i}`))), - b.await(b.call('Promise.all', promises)) + save(b.call('Promise.all', promises)) ); } diff --git a/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_config.js b/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_config.js new file mode 100644 index 0000000000..aaf40e7a52 --- /dev/null +++ b/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_config.js @@ -0,0 +1,8 @@ +import { test } from '../../test'; + +export default test({ + mode: ['async'], + compileOptions: { + dev: true + } +}); diff --git a/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_expected.html b/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_expected.html new file mode 100644 index 0000000000..93016d569c --- /dev/null +++ b/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_expected.html @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_expected_head.html b/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_expected_head.html new file mode 100644 index 0000000000..96ba2bba28 --- /dev/null +++ b/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/_expected_head.html @@ -0,0 +1 @@ +Async multiple attributes \ No newline at end of file diff --git a/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/main.svelte b/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/main.svelte new file mode 100644 index 0000000000..f14ccd088b --- /dev/null +++ b/packages/svelte/tests/server-side-rendering/samples/async-multiple-attrs/main.svelte @@ -0,0 +1,15 @@ + + + +Async multiple attributes + + +{(await