svelte 5.2.4 → 5.2.6

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.
Files changed (25) hide show
  1. package/compiler/index.js +1 -1
  2. package/elements.d.ts +18 -0
  3. package/package.json +1 -1
  4. package/src/compiler/phases/2-analyze/visitors/Attribute.js +4 -5
  5. package/src/compiler/phases/2-analyze/visitors/CallExpression.js +0 -2
  6. package/src/compiler/phases/2-analyze/visitors/ExportDefaultDeclaration.js +7 -2
  7. package/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js +0 -18
  8. package/src/compiler/phases/2-analyze/visitors/ExportSpecifier.js +2 -23
  9. package/src/compiler/phases/2-analyze/visitors/ExpressionTag.js +5 -0
  10. package/src/compiler/phases/2-analyze/visitors/Identifier.js +3 -14
  11. package/src/compiler/phases/2-analyze/visitors/MemberExpression.js +0 -3
  12. package/src/compiler/phases/2-analyze/visitors/RegularElement.js +0 -10
  13. package/src/compiler/phases/2-analyze/visitors/TaggedTemplateExpression.js +0 -1
  14. package/src/compiler/phases/2-analyze/visitors/shared/utils.js +20 -1
  15. package/src/compiler/phases/3-transform/client/utils.js +5 -5
  16. package/src/compiler/phases/3-transform/client/visitors/ClassBody.js +1 -1
  17. package/src/compiler/phases/3-transform/client/visitors/Fragment.js +5 -5
  18. package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +20 -56
  19. package/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +14 -54
  20. package/src/compiler/phases/3-transform/client/visitors/shared/utils.js +37 -55
  21. package/src/compiler/phases/nodes.js +1 -2
  22. package/src/compiler/types/index.d.ts +0 -2
  23. package/src/internal/client/index.js +0 -1
  24. package/src/utils.js +15 -2
  25. package/src/version.js +1 -1
@@ -1,4 +1,4 @@
1
- /** @import { Expression, ExpressionStatement, Identifier, MemberExpression, Statement, Super, TemplateLiteral, Node } from 'estree' */
1
+ /** @import { Expression, ExpressionStatement, Identifier, MemberExpression, Statement, Super } from 'estree' */
2
2
  /** @import { AST, SvelteNode } from '#compiler' */
3
3
  /** @import { ComponentClientTransformState } from '../../types' */
4
4
  import { walk } from 'zimmerframe';
@@ -14,7 +14,7 @@ import { locator } from '../../../../../state.js';
14
14
  * @param {Array<AST.Text | AST.ExpressionTag>} values
15
15
  * @param {(node: SvelteNode, state: any) => any} visit
16
16
  * @param {ComponentClientTransformState} state
17
- * @returns {{ value: Expression, has_state: boolean, has_call: boolean, can_inline: boolean }}
17
+ * @returns {{ value: Expression, has_state: boolean, has_call: boolean }}
18
18
  */
19
19
  export function build_template_chunk(values, visit, state) {
20
20
  /** @type {Expression[]} */
@@ -25,23 +25,15 @@ export function build_template_chunk(values, visit, state) {
25
25
 
26
26
  let has_call = false;
27
27
  let has_state = false;
28
- let can_inline = true;
29
28
  let contains_multiple_call_expression = false;
30
29
 
31
30
  for (const node of values) {
32
31
  if (node.type === 'ExpressionTag') {
33
- if (node.metadata.expression.has_call) {
34
- if (has_call) contains_multiple_call_expression = true;
35
- has_call = true;
36
- }
37
-
38
- if (node.metadata.expression.has_state) {
39
- has_state = true;
40
- }
32
+ const metadata = node.metadata.expression;
41
33
 
42
- if (!node.metadata.expression.can_inline) {
43
- can_inline = false;
44
- }
34
+ contains_multiple_call_expression ||= has_call && metadata.has_call;
35
+ has_call ||= metadata.has_call;
36
+ has_state ||= metadata.has_state;
45
37
  }
46
38
  }
47
39
 
@@ -50,49 +42,39 @@ export function build_template_chunk(values, visit, state) {
50
42
 
51
43
  if (node.type === 'Text') {
52
44
  quasi.value.cooked += node.data;
45
+ } else if (node.type === 'ExpressionTag' && node.expression.type === 'Literal') {
46
+ if (node.expression.value != null) {
47
+ quasi.value.cooked += node.expression.value + '';
48
+ }
53
49
  } else {
54
- const expression = /** @type {Expression} */ (visit(node.expression, state));
55
-
56
- if (expression.type === 'Literal') {
57
- if (expression.value != null) {
58
- quasi.value.cooked += expression.value + '';
59
- }
50
+ if (contains_multiple_call_expression) {
51
+ const id = b.id(state.scope.generate('stringified_text'));
52
+ state.init.push(
53
+ b.const(
54
+ id,
55
+ create_derived(
56
+ state,
57
+ b.thunk(
58
+ b.logical(
59
+ '??',
60
+ /** @type {Expression} */ (visit(node.expression, state)),
61
+ b.literal('')
62
+ )
63
+ )
64
+ )
65
+ )
66
+ );
67
+ expressions.push(b.call('$.get', id));
68
+ } else if (values.length === 1) {
69
+ // If we have a single expression, then pass that in directly to possibly avoid doing
70
+ // extra work in the template_effect (instead we do the work in set_text).
71
+ return { value: visit(node.expression, state), has_state, has_call };
60
72
  } else {
61
- let value = expression;
62
-
63
- // if we don't know the value, we need to add `?? ''` to replace
64
- // `null` and `undefined` with the empty string
65
- let needs_fallback = true;
66
-
67
- if (value.type === 'Identifier') {
68
- const binding = state.scope.get(value.name);
69
-
70
- if (binding && binding.initial?.type === 'Literal' && !binding.reassigned) {
71
- needs_fallback = binding.initial.value === null;
72
- }
73
- }
74
-
75
- if (needs_fallback) {
76
- value = b.logical('??', expression, b.literal(''));
77
- }
78
-
79
- if (contains_multiple_call_expression) {
80
- const id = b.id(state.scope.generate('stringified_text'));
81
-
82
- state.init.push(b.const(id, create_derived(state, b.thunk(value))));
83
-
84
- expressions.push(b.call('$.get', id));
85
- } else if (values.length === 1) {
86
- // If we have a single expression, then pass that in directly to possibly avoid doing
87
- // extra work in the template_effect (instead we do the work in set_text).
88
- return { value: visit(node.expression, state), has_state, has_call, can_inline };
89
- } else {
90
- expressions.push(value);
91
- }
92
-
93
- quasi = b.quasi('', i + 1 === values.length);
94
- quasis.push(quasi);
73
+ expressions.push(b.logical('??', visit(node.expression, state), b.literal('')));
95
74
  }
75
+
76
+ quasi = b.quasi('', i + 1 === values.length);
77
+ quasis.push(quasi);
96
78
  }
97
79
  }
98
80
 
@@ -102,7 +84,7 @@ export function build_template_chunk(values, visit, state) {
102
84
 
103
85
  const value = b.template(quasis, expressions);
104
86
 
105
- return { value, has_state, has_call, can_inline };
87
+ return { value, has_state, has_call };
106
88
  }
107
89
 
108
90
  /**
@@ -58,7 +58,6 @@ export function create_expression_metadata() {
58
58
  return {
59
59
  dependencies: new Set(),
60
60
  has_state: false,
61
- has_call: false,
62
- can_inline: true
61
+ has_call: false
63
62
  };
64
63
  }
@@ -317,8 +317,6 @@ export interface ExpressionMetadata {
317
317
  has_state: boolean;
318
318
  /** True if the expression involves a call expression (often, it will need to be wrapped in a derived) */
319
319
  has_call: boolean;
320
- /** True if the expression can be inlined into a template */
321
- can_inline: boolean;
322
320
  }
323
321
 
324
322
  export * from './template.js';
@@ -1,5 +1,4 @@
1
1
  export { FILENAME, HMR, NAMESPACE_SVG } from '../../constants.js';
2
- export { escape_html as escape } from '../../escaping.js';
3
2
  export { cleanup_styles } from './dev/css.js';
4
3
  export { add_locations } from './dev/elements.js';
5
4
  export { hmr } from './dev/hmr.js';
package/src/utils.js CHANGED
@@ -192,7 +192,8 @@ const ATTRIBUTE_ALIASES = {
192
192
  ismap: 'isMap',
193
193
  nomodule: 'noModule',
194
194
  playsinline: 'playsInline',
195
- readonly: 'readOnly'
195
+ readonly: 'readOnly',
196
+ srcobject: 'srcObject'
196
197
  };
197
198
 
198
199
  /**
@@ -212,7 +213,8 @@ const DOM_PROPERTIES = [
212
213
  'readOnly',
213
214
  'value',
214
215
  'inert',
215
- 'volume'
216
+ 'volume',
217
+ 'srcObject'
216
218
  ];
217
219
 
218
220
  /**
@@ -222,6 +224,17 @@ export function is_dom_property(name) {
222
224
  return DOM_PROPERTIES.includes(name);
223
225
  }
224
226
 
227
+ const NON_STATIC_PROPERTIES = ['autofocus', 'muted'];
228
+
229
+ /**
230
+ * Returns `true` if the given attribute cannot be set through the template
231
+ * string, i.e. needs some kind of JavaScript handling to work.
232
+ * @param {string} name
233
+ */
234
+ export function cannot_be_set_statically(name) {
235
+ return NON_STATIC_PROPERTIES.includes(name);
236
+ }
237
+
225
238
  /**
226
239
  * Subset of delegated events which should be passive by default.
227
240
  * These two are already passive via browser defaults on window, document and body.
package/src/version.js CHANGED
@@ -6,5 +6,5 @@
6
6
  * https://svelte.dev/docs/svelte-compiler#svelte-version
7
7
  * @type {string}
8
8
  */
9
- export const VERSION = '5.2.4';
9
+ export const VERSION = '5.2.6';
10
10
  export const PUBLIC_VERSION = '5';