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.
pull/18183/head
Paolo Ricciuti 2 months ago committed by GitHub
parent dc5bd887b5
commit 89b6a939fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: wrap `Promise.all` in `save` during SSR

@ -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))
);
}

@ -0,0 +1,8 @@
import { test } from '../../test';
export default test({
mode: ['async'],
compileOptions: {
dev: true
}
});

@ -0,0 +1 @@
<!--1410iyz--><!----><title>Async multiple attributes</title>

@ -0,0 +1,15 @@
<script>
const user = $derived(Promise.resolve({
name: 'test',
image: '',
}))
</script>
<svelte:head>
<title>Async multiple attributes</title>
</svelte:head>
<img
alt={(await user).name}
src={(await user).image}
/>
Loading…
Cancel
Save