svelte 5.43.13 → 5.43.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "svelte",
3
3
  "description": "Cybernetically enhanced web apps",
4
4
  "license": "MIT",
5
- "version": "5.43.13",
5
+ "version": "5.43.14",
6
6
  "type": "module",
7
7
  "types": "./types/index.d.ts",
8
8
  "engines": {
@@ -1148,6 +1148,15 @@ export function expected_whitespace(node) {
1148
1148
  e(node, 'expected_whitespace', `Expected whitespace\nhttps://svelte.dev/e/expected_whitespace`);
1149
1149
  }
1150
1150
 
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
+
1151
1160
  /**
1152
1161
  * `<%name%>` does not support non-event attributes or spread attributes
1153
1162
  * @param {null | number | NodeLike} node
@@ -1058,8 +1058,6 @@ const template = {
1058
1058
  handle_identifier(node, state, path);
1059
1059
  },
1060
1060
  RegularElement(node, { state, path, next }) {
1061
- migrate_slot_usage(node, path, state);
1062
- handle_events(node, state);
1063
1061
  // Strip off any namespace from the beginning of the node name.
1064
1062
  const node_name = node.name.replace(/[a-zA-Z-]*:/g, '');
1065
1063
 
@@ -1067,8 +1065,12 @@ const template = {
1067
1065
  let trimmed_position = node.end - 2;
1068
1066
  while (state.str.original.charAt(trimmed_position - 1) === ' ') trimmed_position--;
1069
1067
  state.str.remove(trimmed_position, node.end - 1);
1070
- state.str.appendRight(node.end, `</${node.name}>`);
1068
+ state.str.appendLeft(node.end, `</${node.name}>`);
1071
1069
  }
1070
+
1071
+ migrate_slot_usage(node, path, state);
1072
+ handle_events(node, state);
1073
+
1072
1074
  next();
1073
1075
  },
1074
1076
  SvelteSelf(node, { state, next }) {
@@ -654,8 +654,7 @@ function read_attribute(parser) {
654
654
  }
655
655
  }
656
656
 
657
- /** @type {AST.Directive} */
658
- const directive = {
657
+ const directive = /** @type {AST.Directive} */ ({
659
658
  start,
660
659
  end,
661
660
  type,
@@ -664,7 +663,7 @@ function read_attribute(parser) {
664
663
  metadata: {
665
664
  expression: new ExpressionMetadata()
666
665
  }
667
- };
666
+ });
668
667
 
669
668
  // @ts-expect-error we do this separately from the declaration to avoid upsetting typescript
670
669
  directive.modifiers = modifiers;
@@ -24,6 +24,7 @@ import { extract_svelte_ignore } from '../../utils/extract_svelte_ignore.js';
24
24
  import { ignore_map, ignore_stack, pop_ignore, push_ignore } from '../../state.js';
25
25
  import { ArrowFunctionExpression } from './visitors/ArrowFunctionExpression.js';
26
26
  import { AssignmentExpression } from './visitors/AssignmentExpression.js';
27
+ import { AnimateDirective } from './visitors/AnimateDirective.js';
27
28
  import { AttachTag } from './visitors/AttachTag.js';
28
29
  import { Attribute } from './visitors/Attribute.js';
29
30
  import { AwaitBlock } from './visitors/AwaitBlock.js';
@@ -142,6 +143,7 @@ const visitors = {
142
143
  pop_ignore();
143
144
  }
144
145
  },
146
+ AnimateDirective,
145
147
  ArrowFunctionExpression,
146
148
  AssignmentExpression,
147
149
  AttachTag,
@@ -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
+ }
@@ -1,7 +1,7 @@
1
1
  /** @import { AST } from '#compiler' */
2
2
  /** @import { Context } from '../types' */
3
-
4
3
  import { mark_subtree_dynamic } from './shared/fragment.js';
4
+ import * as e from '../../../errors.js';
5
5
 
6
6
  /**
7
7
  * @param {AST.AttachTag} node
@@ -10,4 +10,8 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
10
10
  export function AttachTag(node, context) {
11
11
  mark_subtree_dynamic(context.path);
12
12
  context.next({ ...context.state, expression: node.metadata.expression });
13
+
14
+ if (node.metadata.expression.has_await) {
15
+ e.illegal_await_expression(node);
16
+ }
13
17
  }
@@ -161,6 +161,7 @@ export function BindDirective(node, context) {
161
161
 
162
162
  const [get, set] = node.expression.expressions;
163
163
  // 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
164
165
  context.visit(get.type === 'ArrowFunctionExpression' ? get.body : get, {
165
166
  ...context.state,
166
167
  expression: node.metadata.expression
@@ -169,6 +170,11 @@ export function BindDirective(node, context) {
169
170
  ...context.state,
170
171
  expression: node.metadata.expression
171
172
  });
173
+
174
+ if (node.metadata.expression.has_await) {
175
+ e.illegal_await_expression(node);
176
+ }
177
+
172
178
  return;
173
179
  }
174
180
 
@@ -267,4 +273,8 @@ export function BindDirective(node, context) {
267
273
  }
268
274
 
269
275
  context.next({ ...context.state, expression: node.metadata.expression });
276
+
277
+ if (node.metadata.expression.has_await) {
278
+ e.illegal_await_expression(node);
279
+ }
270
280
  }
@@ -1,5 +1,6 @@
1
1
  /** @import { AST } from '#compiler' */
2
2
  /** @import { Context } from '../types' */
3
+ import * as e from '../../../errors.js';
3
4
 
4
5
  import { mark_subtree_dynamic } from './shared/fragment.js';
5
6
 
@@ -10,5 +11,9 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
10
11
  export function TransitionDirective(node, context) {
11
12
  mark_subtree_dynamic(context.path);
12
13
 
13
- context.next();
14
+ context.next({ ...context.state, expression: node.metadata.expression });
15
+
16
+ if (node.metadata.expression.has_await) {
17
+ e.illegal_await_expression(node);
18
+ }
14
19
  }
@@ -1,6 +1,7 @@
1
1
  /** @import { AST } from '#compiler' */
2
2
  /** @import { Context } from '../types' */
3
3
  import { mark_subtree_dynamic } from './shared/fragment.js';
4
+ import * as e from '../../../errors.js';
4
5
 
5
6
  /**
6
7
  * @param {AST.UseDirective} node
@@ -8,5 +9,10 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
8
9
  */
9
10
  export function UseDirective(node, context) {
10
11
  mark_subtree_dynamic(context.path);
11
- context.next();
12
+
13
+ context.next({ ...context.state, expression: node.metadata.expression });
14
+
15
+ if (node.metadata.expression.has_await) {
16
+ e.illegal_await_expression(node);
17
+ }
12
18
  }
@@ -15,14 +15,24 @@ export function AnimateDirective(node, context) {
15
15
  : b.thunk(/** @type {Expression} */ (context.visit(node.expression)));
16
16
 
17
17
  // in after_update to ensure it always happens after bind:this
18
- context.state.after_update.push(
19
- b.stmt(
20
- b.call(
21
- '$.animation',
22
- context.state.node,
23
- b.thunk(/** @type {Expression} */ (context.visit(parse_directive_name(node.name)))),
24
- expression
25
- )
18
+ let statement = b.stmt(
19
+ b.call(
20
+ '$.animation',
21
+ context.state.node,
22
+ b.thunk(/** @type {Expression} */ (context.visit(parse_directive_name(node.name)))),
23
+ expression
26
24
  )
27
25
  );
26
+
27
+ if (node.metadata.expression.is_async()) {
28
+ statement = b.stmt(
29
+ b.call(
30
+ '$.run_after_blockers',
31
+ node.metadata.expression.blockers(),
32
+ b.thunk(b.block([statement]))
33
+ )
34
+ );
35
+ }
36
+
37
+ context.state.after_update.push(statement);
28
38
  }
@@ -9,6 +9,18 @@ import { build_expression } from './shared/utils.js';
9
9
  */
10
10
  export function AttachTag(node, context) {
11
11
  const expression = build_expression(context, node.expression, node.metadata.expression);
12
- context.state.init.push(b.stmt(b.call('$.attach', context.state.node, b.thunk(expression))));
12
+ let statement = b.stmt(b.call('$.attach', context.state.node, b.thunk(expression)));
13
+
14
+ if (node.metadata.expression.is_async()) {
15
+ statement = b.stmt(
16
+ b.call(
17
+ '$.run_after_blockers',
18
+ node.metadata.expression.blockers(),
19
+ b.thunk(b.block([statement]))
20
+ )
21
+ );
22
+ }
23
+
24
+ context.state.init.push(statement);
13
25
  context.next();
14
26
  }
@@ -25,5 +25,17 @@ export function TransitionDirective(node, context) {
25
25
  }
26
26
 
27
27
  // in after_update to ensure it always happens after bind:this
28
- context.state.after_update.push(b.stmt(b.call('$.transition', ...args)));
28
+ let statement = b.stmt(b.call('$.transition', ...args));
29
+
30
+ if (node.metadata.expression.is_async()) {
31
+ statement = b.stmt(
32
+ b.call(
33
+ '$.run_after_blockers',
34
+ node.metadata.expression.blockers(),
35
+ b.thunk(b.block([statement]))
36
+ )
37
+ );
38
+ }
39
+
40
+ context.state.after_update.push(statement);
29
41
  }
@@ -32,6 +32,18 @@ export function UseDirective(node, context) {
32
32
  }
33
33
 
34
34
  // actions need to run after attribute updates in order with bindings/events
35
- context.state.init.push(b.stmt(b.call('$.action', ...args)));
35
+ let statement = b.stmt(b.call('$.action', ...args));
36
+
37
+ if (node.metadata.expression.is_async()) {
38
+ statement = b.stmt(
39
+ b.call(
40
+ '$.run_after_blockers',
41
+ node.metadata.expression.blockers(),
42
+ b.thunk(b.block([statement]))
43
+ )
44
+ );
45
+ }
46
+
47
+ context.state.init.push(statement);
36
48
  context.next();
37
49
  }
@@ -296,6 +296,9 @@ export function build_component(node, component_name, context) {
296
296
  );
297
297
  }
298
298
 
299
+ // TODO also support await expressions here?
300
+ memoizer.check_blockers(attribute.metadata.expression);
301
+
299
302
  push_prop(b.prop('init', b.call('$.attachment'), expression, true));
300
303
  }
301
304
  }
@@ -142,6 +142,10 @@ export function build_inline_component(node, expression, context) {
142
142
  true
143
143
  );
144
144
  }
145
+ } else if (attribute.type === 'AttachTag') {
146
+ // While we don't run attachments on the server, on the client they might generate a surrounding blocker function which generates
147
+ // extra comments, and to prevent hydration mismatches we therefore have to account for them here to generate similar comments on the server.
148
+ optimiser.check_blockers(attribute.metadata.expression);
145
149
  }
146
150
  }
147
151
 
@@ -1,13 +1,7 @@
1
1
  /** @import { AnimateFn, Animation, AnimationConfig, EachItem, Effect, TransitionFn, TransitionManager } from '#client' */
2
2
  import { noop, is_function } from '../../../shared/utils.js';
3
3
  import { effect } from '../../reactivity/effects.js';
4
- import {
5
- active_effect,
6
- active_reaction,
7
- set_active_effect,
8
- set_active_reaction,
9
- untrack
10
- } from '../../runtime.js';
4
+ import { active_effect, untrack } from '../../runtime.js';
11
5
  import { loop } from '../../loop.js';
12
6
  import { should_intro } from '../../render.js';
13
7
  import { current_each_item } from '../blocks/each.js';
@@ -26,6 +26,7 @@ import {
26
26
  } from './deriveds.js';
27
27
  import { aborted } from './effects.js';
28
28
  import { hydrate_next, hydrating, set_hydrate_node, skip_nodes } from '../dom/hydration.js';
29
+ import { current_each_item, set_current_each_item } from '../dom/blocks/each.js';
29
30
 
30
31
  /**
31
32
  * @param {Array<Promise<void>>} blockers
@@ -89,7 +90,11 @@ export function flatten(blockers, sync, async, fn) {
89
90
  * @param {(values: Value[]) => any} fn
90
91
  */
91
92
  export function run_after_blockers(blockers, fn) {
92
- flatten(blockers, [], [], fn);
93
+ var each_item = current_each_item; // TODO should this be part of capture?
94
+ flatten(blockers, [], [], (v) => {
95
+ set_current_each_item(each_item);
96
+ fn(v);
97
+ });
93
98
  }
94
99
 
95
100
  /**
package/src/version.js CHANGED
@@ -4,5 +4,5 @@
4
4
  * The current version, as set in package.json.
5
5
  * @type {string}
6
6
  */
7
- export const VERSION = '5.43.13';
7
+ export const VERSION = '5.43.14';
8
8
  export const PUBLIC_VERSION = '5';