Skip to content

Commit 48f2fa2

Browse files
Ocean-OS7nik
andauthored
fix: allow await expressions inside {#await ...} argument (#16514)
* fix: allow await expressions inside `{#await ...}` argument * add test * apply suggestion from review --------- Co-authored-by: 7nik <kifiranet@gmail.com>
1 parent 03f2e44 commit 48f2fa2

File tree

4 files changed

+75
-2
lines changed

4 files changed

+75
-2
lines changed

.changeset/long-roses-train.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: allow await expressions inside `{#await ...}` argument

packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @import { BlockStatement, Pattern, Statement } from 'estree' */
22
/** @import { AST } from '#compiler' */
33
/** @import { ComponentClientTransformState, ComponentContext } from '../types' */
4-
import { extract_identifiers } from '../../../../utils/ast.js';
4+
import { extract_identifiers, is_expression_async } from '../../../../utils/ast.js';
55
import * as b from '#compiler/builders';
66
import { create_derived } from '../utils.js';
77
import { get_value } from './shared/declarations.js';
@@ -15,7 +15,10 @@ export function AwaitBlock(node, context) {
1515
context.state.template.push_comment();
1616

1717
// Visit {#await <expression>} first to ensure that scopes are in the correct order
18-
const expression = b.thunk(build_expression(context, node.expression, node.metadata.expression));
18+
const expression = b.thunk(
19+
build_expression(context, node.expression, node.metadata.expression),
20+
node.metadata.expression.has_await
21+
);
1922

2023
let then_block;
2124
let catch_block;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { tick } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target }) {
6+
const [reset, one, two, reject] = target.querySelectorAll('button');
7+
8+
await tick();
9+
assert.htmlEqual(
10+
target.innerHTML,
11+
'<button>reset</button><button>one</button><button>two</button><button>reject</button> waiting'
12+
);
13+
14+
one.click();
15+
await tick();
16+
assert.htmlEqual(
17+
target.innerHTML,
18+
'<button>reset</button><button>one</button><button>two</button><button>reject</button> one_res'
19+
);
20+
21+
reset.click();
22+
await tick();
23+
assert.htmlEqual(
24+
target.innerHTML,
25+
'<button>reset</button><button>one</button><button>two</button><button>reject</button> waiting'
26+
);
27+
28+
two.click();
29+
await tick();
30+
assert.htmlEqual(
31+
target.innerHTML,
32+
'<button>reset</button><button>one</button><button>two</button><button>reject</button> two_res'
33+
);
34+
35+
reset.click();
36+
reject.click();
37+
await tick();
38+
assert.htmlEqual(
39+
target.innerHTML,
40+
'<button>reset</button><button>one</button><button>two</button><button>reject</button> reject_catch'
41+
);
42+
}
43+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<script>
2+
let deferred = $state(Promise.withResolvers());
3+
</script>
4+
5+
<button onclick={() => deferred = Promise.withResolvers()}>reset</button>
6+
<button onclick={() => deferred.resolve("one")}>one</button>
7+
<button onclick={() => deferred.resolve("two")}>two</button>
8+
<button onclick={() => deferred.reject("reject")}>reject</button>
9+
10+
<svelte:boundary>
11+
{#await await deferred.promise + "_res"}
12+
waiting
13+
{:then res}
14+
{res}
15+
{:catch err}
16+
{err}_catch
17+
{/await}
18+
19+
{#snippet pending()}
20+
<p>pending</p>
21+
{/snippet}
22+
</svelte:boundary>

0 commit comments

Comments
 (0)