Skip to content

Commit 91486fa

Browse files
authored
fix: take async into account for bindings/transitions/animations/attachments (#17198)
* fix: take async into account for bindings/transitions/animations/attachments - block on async work - error at compile time on await expressions. Right now it gives confusing errors later at compile time or at runtime Fixes #17194 * this was weird
1 parent a17dc3c commit 91486fa

File tree

28 files changed

+240
-25
lines changed

28 files changed

+240
-25
lines changed

.changeset/itchy-forks-greet.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: error at compile time instead of at runtime on await expressions inside bindings/transitions/animations/attachments

.changeset/plain-bikes-smile.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: take async blockers into account for bindings/transitions/animations/attachments

documentation/docs/98-reference/.generated/compile-errors.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,12 @@ Cannot use `await` in deriveds and template expressions, or at the top level of
561561
`$host()` can only be used inside custom element component instances
562562
```
563563

564+
### illegal_await_expression
565+
566+
```
567+
`use:`, `transition:` and `animate:` directives, attachments and bindings do not support await expressions
568+
```
569+
564570
### illegal_element_attribute
565571

566572
```

packages/svelte/messages/compile-errors/template.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ The same applies to components:
231231

232232
> Expected whitespace
233233
234+
## illegal_await_expression
235+
236+
> `use:`, `transition:` and `animate:` directives, attachments and bindings do not support await expressions
237+
234238
## illegal_element_attribute
235239

236240
> `<%name%>` does not support non-event attributes or spread attributes

packages/svelte/src/compiler/errors.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,15 @@ export function expected_whitespace(node) {
11481148
e(node, 'expected_whitespace', `Expected whitespace\nhttps://svelte.dev/e/expected_whitespace`);
11491149
}
11501150

1151+
/**
1152+
* `use:`, `transition:` and `animate:` directives, attachments and bindings do not support await expressions
1153+
* @param {null | number | NodeLike} node
1154+
* @returns {never}
1155+
*/
1156+
export function illegal_await_expression(node) {
1157+
e(node, 'illegal_await_expression', `\`use:\`, \`transition:\` and \`animate:\` directives, attachments and bindings do not support await expressions\nhttps://svelte.dev/e/illegal_await_expression`);
1158+
}
1159+
11511160
/**
11521161
* `<%name%>` does not support non-event attributes or spread attributes
11531162
* @param {null | number | NodeLike} node

packages/svelte/src/compiler/phases/1-parse/state/element.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -654,8 +654,7 @@ function read_attribute(parser) {
654654
}
655655
}
656656

657-
/** @type {AST.Directive} */
658-
const directive = {
657+
const directive = /** @type {AST.Directive} */ ({
659658
start,
660659
end,
661660
type,
@@ -664,7 +663,7 @@ function read_attribute(parser) {
664663
metadata: {
665664
expression: new ExpressionMetadata()
666665
}
667-
};
666+
});
668667

669668
// @ts-expect-error we do this separately from the declaration to avoid upsetting typescript
670669
directive.modifiers = modifiers;

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { extract_svelte_ignore } from '../../utils/extract_svelte_ignore.js';
2424
import { ignore_map, ignore_stack, pop_ignore, push_ignore } from '../../state.js';
2525
import { ArrowFunctionExpression } from './visitors/ArrowFunctionExpression.js';
2626
import { AssignmentExpression } from './visitors/AssignmentExpression.js';
27+
import { AnimateDirective } from './visitors/AnimateDirective.js';
2728
import { AttachTag } from './visitors/AttachTag.js';
2829
import { Attribute } from './visitors/Attribute.js';
2930
import { AwaitBlock } from './visitors/AwaitBlock.js';
@@ -142,6 +143,7 @@ const visitors = {
142143
pop_ignore();
143144
}
144145
},
146+
AnimateDirective,
145147
ArrowFunctionExpression,
146148
AssignmentExpression,
147149
AttachTag,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/** @import { Context } from '../types' */
2+
/** @import { AST } from '#compiler'; */
3+
import * as e from '../../../errors.js';
4+
5+
/**
6+
* @param {AST.AnimateDirective} node
7+
* @param {Context} context
8+
*/
9+
export function AnimateDirective(node, context) {
10+
context.next({ ...context.state, expression: node.metadata.expression });
11+
12+
if (node.metadata.expression.has_await) {
13+
e.illegal_await_expression(node);
14+
}
15+
}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @import { AST } from '#compiler' */
22
/** @import { Context } from '../types' */
3-
43
import { mark_subtree_dynamic } from './shared/fragment.js';
4+
import * as e from '../../../errors.js';
55

66
/**
77
* @param {AST.AttachTag} node
@@ -10,4 +10,8 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
1010
export function AttachTag(node, context) {
1111
mark_subtree_dynamic(context.path);
1212
context.next({ ...context.state, expression: node.metadata.expression });
13+
14+
if (node.metadata.expression.has_await) {
15+
e.illegal_await_expression(node);
16+
}
1317
}

packages/svelte/src/compiler/phases/2-analyze/visitors/BindDirective.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ export function BindDirective(node, context) {
161161

162162
const [get, set] = node.expression.expressions;
163163
// We gotta jump across the getter/setter functions to avoid the expression metadata field being reset to null
164+
// as we want to collect the functions' blocker/async info
164165
context.visit(get.type === 'ArrowFunctionExpression' ? get.body : get, {
165166
...context.state,
166167
expression: node.metadata.expression
@@ -169,6 +170,11 @@ export function BindDirective(node, context) {
169170
...context.state,
170171
expression: node.metadata.expression
171172
});
173+
174+
if (node.metadata.expression.has_await) {
175+
e.illegal_await_expression(node);
176+
}
177+
172178
return;
173179
}
174180

@@ -267,4 +273,8 @@ export function BindDirective(node, context) {
267273
}
268274

269275
context.next({ ...context.state, expression: node.metadata.expression });
276+
277+
if (node.metadata.expression.has_await) {
278+
e.illegal_await_expression(node);
279+
}
270280
}

0 commit comments

Comments
 (0)