svelte 5.56.9 → 5.57.0

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 (94) hide show
  1. package/compiler/index.js +1 -1
  2. package/elements.d.ts +3 -0
  3. package/package.json +3 -3
  4. package/src/compiler/migrate/index.js +6 -1
  5. package/src/compiler/phases/1-parse/acorn.js +1 -1
  6. package/src/compiler/phases/1-parse/read/style.js +16 -6
  7. package/src/compiler/phases/1-parse/utils/html.js +12 -7
  8. package/src/compiler/phases/2-analyze/css/css-prune.js +10 -0
  9. package/src/compiler/phases/2-analyze/index.js +45 -18
  10. package/src/compiler/phases/2-analyze/visitors/AwaitExpression.js +10 -4
  11. package/src/compiler/phases/2-analyze/visitors/CallExpression.js +1 -1
  12. package/src/compiler/phases/2-analyze/visitors/DeclarationTag.js +2 -1
  13. package/src/compiler/phases/2-analyze/visitors/ExportNamedDeclaration.js +10 -10
  14. package/src/compiler/phases/2-analyze/visitors/SvelteBody.js +4 -4
  15. package/src/compiler/phases/2-analyze/visitors/SvelteDocument.js +4 -4
  16. package/src/compiler/phases/2-analyze/visitors/SvelteWindow.js +4 -4
  17. package/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js +14 -2
  18. package/src/compiler/phases/2-analyze/visitors/shared/element.js +2 -8
  19. package/src/compiler/phases/2-analyze/visitors/shared/utils.js +23 -1
  20. package/src/compiler/phases/3-transform/client/transform-client.js +2 -2
  21. package/src/compiler/phases/3-transform/client/transform-template/index.js +6 -0
  22. package/src/compiler/phases/3-transform/client/utils.js +35 -8
  23. package/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js +16 -3
  24. package/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js +6 -6
  25. package/src/compiler/phases/3-transform/client/visitors/BindDirective.js +10 -13
  26. package/src/compiler/phases/3-transform/client/visitors/ConstTag.js +19 -8
  27. package/src/compiler/phases/3-transform/client/visitors/DeclarationTag.js +3 -2
  28. package/src/compiler/phases/3-transform/client/visitors/EachBlock.js +4 -1
  29. package/src/compiler/phases/3-transform/client/visitors/Fragment.js +2 -7
  30. package/src/compiler/phases/3-transform/client/visitors/HtmlTag.js +2 -1
  31. package/src/compiler/phases/3-transform/client/visitors/IfBlock.js +2 -1
  32. package/src/compiler/phases/3-transform/client/visitors/KeyBlock.js +2 -1
  33. package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +119 -46
  34. package/src/compiler/phases/3-transform/client/visitors/SvelteElement.js +2 -1
  35. package/src/compiler/phases/3-transform/client/visitors/UpdateExpression.js +0 -1
  36. package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +11 -4
  37. package/src/compiler/phases/3-transform/client/visitors/shared/element.js +6 -1
  38. package/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +1 -6
  39. package/src/compiler/phases/3-transform/client/visitors/shared/utils.js +5 -5
  40. package/src/compiler/phases/3-transform/css/index.js +5 -1
  41. package/src/compiler/phases/3-transform/server/transform-server.js +20 -9
  42. package/src/compiler/phases/3-transform/server/visitors/AssignmentExpression.js +1 -1
  43. package/src/compiler/phases/3-transform/server/visitors/DeclarationTag.js +1 -1
  44. package/src/compiler/phases/3-transform/server/visitors/EachBlock.js +8 -2
  45. package/src/compiler/phases/3-transform/server/visitors/IfBlock.js +4 -4
  46. package/src/compiler/phases/3-transform/server/visitors/LabeledStatement.js +1 -0
  47. package/src/compiler/phases/3-transform/server/visitors/RegularElement.js +1 -1
  48. package/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js +9 -4
  49. package/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js +4 -2
  50. package/src/compiler/phases/3-transform/server/visitors/shared/element.js +53 -47
  51. package/src/compiler/phases/3-transform/server/visitors/shared/utils.js +31 -1
  52. package/src/compiler/phases/bindings.js +3 -1
  53. package/src/compiler/phases/nodes.js +4 -0
  54. package/src/compiler/print/index.js +95 -24
  55. package/src/easing/index.js +62 -0
  56. package/src/internal/client/constants.js +9 -0
  57. package/src/internal/client/context.js +33 -56
  58. package/src/internal/client/dev/hmr.js +15 -4
  59. package/src/internal/client/dom/blocks/boundary.js +21 -12
  60. package/src/internal/client/dom/blocks/css-props.js +3 -3
  61. package/src/internal/client/dom/blocks/slot.js +19 -0
  62. package/src/internal/client/dom/blocks/svelte-head.js +8 -0
  63. package/src/internal/client/dom/css.js +6 -1
  64. package/src/internal/client/dom/elements/attributes.js +37 -35
  65. package/src/internal/client/dom/elements/bindings/select.js +99 -9
  66. package/src/internal/client/dom/elements/bindings/this.js +7 -2
  67. package/src/internal/client/dom/elements/events.js +19 -1
  68. package/src/internal/client/dom/elements/transitions.js +81 -68
  69. package/src/internal/client/dom/operations.js +21 -1
  70. package/src/internal/client/error-handling.js +10 -2
  71. package/src/internal/client/index.js +9 -2
  72. package/src/internal/client/proxy.js +8 -3
  73. package/src/internal/client/reactivity/async.js +23 -3
  74. package/src/internal/client/reactivity/batch.js +1 -0
  75. package/src/internal/client/reactivity/effects.js +14 -1
  76. package/src/internal/client/reactivity/sources.js +7 -1
  77. package/src/internal/client/render.js +4 -8
  78. package/src/internal/client/runtime.js +45 -33
  79. package/src/internal/client/warnings.js +0 -11
  80. package/src/internal/server/abort-signal.js +8 -9
  81. package/src/internal/server/context.js +9 -48
  82. package/src/internal/server/index.js +1 -1
  83. package/src/internal/server/renderer.js +164 -52
  84. package/src/internal/shared/attributes.js +4 -2
  85. package/src/internal/shared/clone.js +2 -0
  86. package/src/internal/shared/context.js +53 -0
  87. package/src/internal/shared/errors.js +2 -2
  88. package/src/legacy/legacy-server.js +1 -1
  89. package/src/reactivity/map.js +22 -0
  90. package/src/reactivity/url.js +2 -0
  91. package/src/transition/index.js +18 -7
  92. package/src/version.js +1 -1
  93. package/types/index.d.ts +148 -46
  94. package/types/index.d.ts.map +2 -2
@@ -7,6 +7,68 @@ import { is_void } from '../../utils.js';
7
7
  /** Threshold for when content should be formatted on separate lines */
8
8
  const LINE_BREAK_THRESHOLD = 50;
9
9
 
10
+ /** Characters that are valid in a CSS identifier without escaping */
11
+ const REGEX_IDENTIFIER_CHAR = /^[a-zA-Z0-9_-]$/;
12
+
13
+ /** Hex digits — a backslash followed by one of these is read as a hex escape */
14
+ const REGEX_HEX_DIGIT = /[0-9a-fA-F]/;
15
+
16
+ /**
17
+ * Re-escape a CSS identifier name so that it prints as valid CSS.
18
+ *
19
+ * `parse` decodes CSS escape sequences when building the AST — `\31` becomes `1`,
20
+ * `\a` becomes a newline — but keeps single-character escapes such as `\.` and
21
+ * escaped backslashes intact. When printing we therefore only need to escape the
22
+ * characters that would be illegal in a bare identifier: a leading digit, `-`
23
+ * followed by a digit, whitespace and control characters, and anything else that
24
+ * is not already escaped.
25
+ * @param {string} name
26
+ */
27
+ function escape_identifier(name) {
28
+ let escaped = '';
29
+ let i = 0;
30
+
31
+ while (i < name.length) {
32
+ const char = name[i];
33
+
34
+ if (char === '\\') {
35
+ const next = name.charAt(i + 1);
36
+ if (next === '' || REGEX_HEX_DIGIT.test(next)) {
37
+ // A literal backslash in a name must itself be escaped: `\5c `
38
+ // re-parses to a backslash, whereas a backslash followed by a hex
39
+ // digit (or by nothing) would be read back as a hex escape.
40
+ escaped += '\\5c ';
41
+ i += 1;
42
+ continue;
43
+ }
44
+
45
+ // Already escaped — copy the backslash and the escaped character as-is.
46
+ escaped += '\\' + next;
47
+ i += 2;
48
+ continue;
49
+ }
50
+
51
+ const code = /** @type {number} */ (char.codePointAt(0));
52
+ const is_leading_digit = i === 0 && char >= '0' && char <= '9';
53
+ const is_leading_hyphen_digit =
54
+ i === 0 && char === '-' && name.charAt(i + 1) >= '0' && name.charAt(i + 1) <= '9';
55
+
56
+ if (
57
+ is_leading_digit ||
58
+ is_leading_hyphen_digit ||
59
+ !(REGEX_IDENTIFIER_CHAR.test(char) || code >= 160)
60
+ ) {
61
+ escaped += `\\${code.toString(16)} `;
62
+ } else {
63
+ escaped += char;
64
+ }
65
+
66
+ i += 1;
67
+ }
68
+
69
+ return escaped;
70
+ }
71
+
10
72
  /**
11
73
  * `print` converts a Svelte AST node back into Svelte source code.
12
74
  * It is primarily intended for tools that parse and transform components using the compiler’s modern AST representation.
@@ -324,7 +386,7 @@ function css_visitors(comments, js_comments) {
324
386
 
325
387
  return {
326
388
  Atrule(node, context) {
327
- context.write(`@${node.name}`);
389
+ context.write(`@${escape_identifier(node.name)}`);
328
390
 
329
391
  const prelude_end = node.block?.start ?? node.end;
330
392
  if (node.prelude || has_comment_before(prelude_end)) {
@@ -341,7 +403,7 @@ function css_visitors(comments, js_comments) {
341
403
  },
342
404
 
343
405
  AttributeSelector(node, context) {
344
- context.write(`[${node.name}`);
406
+ context.write(`[${escape_identifier(node.name)}`);
345
407
  if (node.matcher) {
346
408
  context.write(node.matcher);
347
409
  context.write(`"${node.value}"`);
@@ -365,7 +427,7 @@ function css_visitors(comments, js_comments) {
365
427
  },
366
428
 
367
429
  ClassSelector(node, context) {
368
- context.write(`.${node.name}`);
430
+ context.write(`.${escape_identifier(node.name)}`);
369
431
  },
370
432
 
371
433
  ComplexSelector(node, context) {
@@ -379,7 +441,7 @@ function css_visitors(comments, js_comments) {
379
441
  },
380
442
 
381
443
  IdSelector(node, context) {
382
- context.write(`#${node.name}`);
444
+ context.write(`#${escape_identifier(node.name)}`);
383
445
  },
384
446
 
385
447
  NestingSelector(node, context) {
@@ -395,7 +457,7 @@ function css_visitors(comments, js_comments) {
395
457
  },
396
458
 
397
459
  PseudoClassSelector(node, context) {
398
- context.write(`:${node.name}`);
460
+ context.write(`:${escape_identifier(node.name)}`);
399
461
 
400
462
  if (node.args) {
401
463
  context.write('(');
@@ -409,7 +471,7 @@ function css_visitors(comments, js_comments) {
409
471
  },
410
472
 
411
473
  PseudoElementSelector(node, context) {
412
- context.write(`::${node.name}`);
474
+ context.write(`::${escape_identifier(node.name)}`);
413
475
  if (node.args) {
414
476
  context.write('(');
415
477
  context.visit(node.args);
@@ -458,7 +520,11 @@ function css_visitors(comments, js_comments) {
458
520
  },
459
521
 
460
522
  TypeSelector(node, context) {
461
- context.write(node.name);
523
+ if (node.namespace !== undefined) {
524
+ context.write(node.namespace === '*' ? '*' : escape_identifier(node.namespace));
525
+ context.write('|');
526
+ }
527
+ context.write(node.name === '*' ? node.name : escape_identifier(node.name));
462
528
  }
463
529
  };
464
530
  }
@@ -521,15 +587,19 @@ const svelte_visitors = (comments, state) => ({
521
587
  last?.type === 'Text' &&
522
588
  /\s$/.test(last.data);
523
589
 
524
- /** @type {AST.SvelteNode[][]} */
590
+ /** @type {{ nodes: AST.SvelteNode[]; leading_whitespace: boolean }[]} */
525
591
  const items = [];
526
592
 
527
593
  /** @type {AST.SvelteNode[]} */
528
594
  let sequence = [];
595
+ let leading_whitespace = false;
529
596
 
530
597
  const flush = () => {
531
- items.push(sequence);
532
- sequence = [];
598
+ if (sequence.length > 0) {
599
+ items.push({ nodes: sequence, leading_whitespace });
600
+ sequence = [];
601
+ leading_whitespace = false;
602
+ }
533
603
  };
534
604
 
535
605
  for (let i = 0; i < node.nodes.length; i += 1) {
@@ -558,6 +628,7 @@ const svelte_visitors = (comments, state) => ({
558
628
 
559
629
  if (child_node.data.startsWith(' ') && prev && prev.type !== 'ExpressionTag') {
560
630
  flush();
631
+ leading_whitespace = true;
561
632
  child_node.data = child_node.data.trimStart();
562
633
  }
563
634
 
@@ -596,20 +667,18 @@ const svelte_visitors = (comments, state) => ({
596
667
  let multiline = false;
597
668
  let width = 0;
598
669
 
599
- const child_contexts = items
600
- .filter((x) => x.length > 0)
601
- .map((sequence) => {
602
- const child_context = context.new();
670
+ const child_contexts = items.map(({ nodes, leading_whitespace }) => {
671
+ const child_context = context.new();
603
672
 
604
- for (const node of sequence) {
605
- child_context.visit(node);
606
- multiline ||= child_context.multiline;
607
- }
673
+ for (const node of nodes) {
674
+ child_context.visit(node);
675
+ multiline ||= child_context.multiline;
676
+ }
608
677
 
609
- width += child_context.measure();
678
+ width += child_context.measure() + (leading_whitespace ? 1 : 0);
610
679
 
611
- return child_context;
612
- });
680
+ return { context: child_context, leading_whitespace };
681
+ });
613
682
 
614
683
  multiline ||= width > LINE_BREAK_THRESHOLD;
615
684
  // Normally context.newline() also makes context.multiline true, but the below loop only
@@ -621,14 +690,16 @@ const svelte_visitors = (comments, state) => ({
621
690
  const prev = child_contexts[i];
622
691
  const next = child_contexts[i + 1];
623
692
 
624
- context.append(prev);
693
+ context.append(prev.context);
625
694
 
626
695
  if (next) {
627
- if (prev.multiline || next.multiline) {
696
+ if (prev.context.multiline || next.context.multiline) {
628
697
  context.margin();
629
698
  context.newline();
630
699
  } else if (multiline) {
631
700
  context.newline();
701
+ } else if (next.leading_whitespace) {
702
+ context.write(' ');
632
703
  }
633
704
  }
634
705
  }
@@ -701,7 +772,7 @@ const svelte_visitors = (comments, state) => ({
701
772
  }
702
773
 
703
774
  if (node.catch) {
704
- context.write(node.value ? 'catch ' : 'catch');
775
+ context.write(node.error ? 'catch ' : 'catch');
705
776
  if (node.error) context.visit(node.error);
706
777
  context.write('}');
707
778
 
@@ -4,6 +4,8 @@ Distributed under MIT License https://github.com/mattdesl/eases/blob/master/LICE
4
4
  */
5
5
 
6
6
  /**
7
+ * Returns value as is.
8
+ *
7
9
  * @param {number} t
8
10
  * @returns {number}
9
11
  */
@@ -12,6 +14,8 @@ export function linear(t) {
12
14
  }
13
15
 
14
16
  /**
17
+ * Rebound effect on start and end of value range.
18
+ *
15
19
  * @param {number} t
16
20
  * @returns {number}
17
21
  */
@@ -22,6 +26,8 @@ export function backInOut(t) {
22
26
  }
23
27
 
24
28
  /**
29
+ * Rebound effect on start.
30
+ *
25
31
  * @param {number} t
26
32
  * @returns {number}
27
33
  */
@@ -31,6 +37,8 @@ export function backIn(t) {
31
37
  }
32
38
 
33
39
  /**
40
+ * Rebound effect on end.
41
+ *
34
42
  * @param {number} t
35
43
  * @returns {number}
36
44
  */
@@ -40,6 +48,8 @@ export function backOut(t) {
40
48
  }
41
49
 
42
50
  /**
51
+ * Bounce effect on end.
52
+ *
43
53
  * @param {number} t
44
54
  * @returns {number}
45
55
  */
@@ -61,6 +71,8 @@ export function bounceOut(t) {
61
71
  }
62
72
 
63
73
  /**
74
+ * Bounce effect on start and end.
75
+ *
64
76
  * @param {number} t
65
77
  * @returns {number}
66
78
  */
@@ -69,6 +81,8 @@ export function bounceInOut(t) {
69
81
  }
70
82
 
71
83
  /**
84
+ * Bounce effect on start.
85
+ *
72
86
  * @param {number} t
73
87
  * @returns {number}
74
88
  */
@@ -77,6 +91,8 @@ export function bounceIn(t) {
77
91
  }
78
92
 
79
93
  /**
94
+ * Circular effect, accelerate on start, decelerate towards end.
95
+ *
80
96
  * @param {number} t
81
97
  * @returns {number}
82
98
  */
@@ -86,6 +102,8 @@ export function circInOut(t) {
86
102
  }
87
103
 
88
104
  /**
105
+ * Circular effect, accelerate on start.
106
+ *
89
107
  * @param {number} t
90
108
  * @returns {number}
91
109
  */
@@ -94,6 +112,8 @@ export function circIn(t) {
94
112
  }
95
113
 
96
114
  /**
115
+ * Circular effect, decelerate towards end.
116
+ *
97
117
  * @param {number} t
98
118
  * @returns {number}
99
119
  */
@@ -102,6 +122,8 @@ export function circOut(t) {
102
122
  }
103
123
 
104
124
  /**
125
+ * Cubic scaling, accelerate on start, decelerate towards end.
126
+ *
105
127
  * @param {number} t
106
128
  * @returns {number}
107
129
  */
@@ -110,6 +132,8 @@ export function cubicInOut(t) {
110
132
  }
111
133
 
112
134
  /**
135
+ * Cubic scaling, accelerate on start
136
+ *
113
137
  * @param {number} t
114
138
  * @returns {number}
115
139
  */
@@ -118,6 +142,8 @@ export function cubicIn(t) {
118
142
  }
119
143
 
120
144
  /**
145
+ * Cubic scaling, decelerate towards end.
146
+ *
121
147
  * @param {number} t
122
148
  * @returns {number}
123
149
  */
@@ -127,6 +153,8 @@ export function cubicOut(t) {
127
153
  }
128
154
 
129
155
  /**
156
+ * Elastic effect on start and end.
157
+ *
130
158
  * @param {number} t
131
159
  * @returns {number}
132
160
  */
@@ -140,6 +168,8 @@ export function elasticInOut(t) {
140
168
  }
141
169
 
142
170
  /**
171
+ * Elastic effect on start.
172
+ *
143
173
  * @param {number} t
144
174
  * @returns {number}
145
175
  */
@@ -148,6 +178,8 @@ export function elasticIn(t) {
148
178
  }
149
179
 
150
180
  /**
181
+ * Elastic effect on end.
182
+ *
151
183
  * @param {number} t
152
184
  * @returns {number}
153
185
  */
@@ -156,6 +188,8 @@ export function elasticOut(t) {
156
188
  }
157
189
 
158
190
  /**
191
+ * Exponential effect on start and end.
192
+ *
159
193
  * @param {number} t
160
194
  * @returns {number}
161
195
  */
@@ -168,6 +202,8 @@ export function expoInOut(t) {
168
202
  }
169
203
 
170
204
  /**
205
+ * Exponential effect on start.
206
+ *
171
207
  * @param {number} t
172
208
  * @returns {number}
173
209
  */
@@ -176,6 +212,8 @@ export function expoIn(t) {
176
212
  }
177
213
 
178
214
  /**
215
+ * Exponential effect on end.
216
+ *
179
217
  * @param {number} t
180
218
  * @returns {number}
181
219
  */
@@ -184,6 +222,8 @@ export function expoOut(t) {
184
222
  }
185
223
 
186
224
  /**
225
+ * Quadratic scaling, accelerate on start, decelerate towards end.
226
+ *
187
227
  * @param {number} t
188
228
  * @returns {number}
189
229
  */
@@ -195,6 +235,8 @@ export function quadInOut(t) {
195
235
  }
196
236
 
197
237
  /**
238
+ * Quadratic scaling, accelerate on start.
239
+ *
198
240
  * @param {number} t
199
241
  * @returns {number}
200
242
  */
@@ -203,6 +245,8 @@ export function quadIn(t) {
203
245
  }
204
246
 
205
247
  /**
248
+ * Quadratic scaling, decelerate towards end.
249
+ *
206
250
  * @param {number} t
207
251
  * @returns {number}
208
252
  */
@@ -211,6 +255,8 @@ export function quadOut(t) {
211
255
  }
212
256
 
213
257
  /**
258
+ * Quartic scaling, accelerate on start, decelerate towards end.
259
+ *
214
260
  * @param {number} t
215
261
  * @returns {number}
216
262
  */
@@ -219,6 +265,8 @@ export function quartInOut(t) {
219
265
  }
220
266
 
221
267
  /**
268
+ * Quartic scaling, accelerate on start.
269
+ *
222
270
  * @param {number} t
223
271
  * @returns {number}
224
272
  */
@@ -227,6 +275,8 @@ export function quartIn(t) {
227
275
  }
228
276
 
229
277
  /**
278
+ * Quartic scaling, decelerate towards end.
279
+ *
230
280
  * @param {number} t
231
281
  * @returns {number}
232
282
  */
@@ -235,6 +285,8 @@ export function quartOut(t) {
235
285
  }
236
286
 
237
287
  /**
288
+ * Quintic scaling, accelerate on start, decelerate towards end.
289
+ *
238
290
  * @param {number} t
239
291
  * @returns {number}
240
292
  */
@@ -244,6 +296,8 @@ export function quintInOut(t) {
244
296
  }
245
297
 
246
298
  /**
299
+ * Quintic scaling, accelerate on start.
300
+ *
247
301
  * @param {number} t
248
302
  * @returns {number}
249
303
  */
@@ -252,6 +306,8 @@ export function quintIn(t) {
252
306
  }
253
307
 
254
308
  /**
309
+ * Quintic scaling, decelerate towards end.
310
+ *
255
311
  * @param {number} t
256
312
  * @returns {number}
257
313
  */
@@ -260,6 +316,8 @@ export function quintOut(t) {
260
316
  }
261
317
 
262
318
  /**
319
+ * Sinusoidal effect, accelerate on start, decelerate towards end.
320
+ *
263
321
  * @param {number} t
264
322
  * @returns {number}
265
323
  */
@@ -268,6 +326,8 @@ export function sineInOut(t) {
268
326
  }
269
327
 
270
328
  /**
329
+ * Sinusoidal effect, accelerate on start.
330
+ *
271
331
  * @param {number} t
272
332
  * @returns {number}
273
333
  */
@@ -278,6 +338,8 @@ export function sineIn(t) {
278
338
  }
279
339
 
280
340
  /**
341
+ * Sinusoidal effect, decelerate towards end.
342
+ *
281
343
  * @param {number} t
282
344
  * @returns {number}
283
345
  */
@@ -15,6 +15,13 @@ export const BLOCK_EFFECT = 1 << 4;
15
15
  export const BRANCH_EFFECT = 1 << 5;
16
16
  export const ROOT_EFFECT = 1 << 6;
17
17
  export const BOUNDARY_EFFECT = 1 << 7;
18
+ /**
19
+ * Set on the effect that `pause_effect` was called on, i.e. the root of a paused subtree,
20
+ * as opposed to its descendants which are merely `INERT`. This allows `resume_effect` on
21
+ * an ancestor to skip subtrees that were paused for their own reasons (such as a block
22
+ * whose condition is still false) rather than resurrecting them
23
+ */
24
+ export const PAUSED = 1 << 8;
18
25
  /**
19
26
  * Indicates that a reaction is connected to an effect root — either it is an effect,
20
27
  * or it is a derived that is depended on by at least one effect. If a derived has
@@ -60,6 +67,8 @@ export const ASYNC = 1 << 22;
60
67
  export const ERROR_VALUE = 1 << 23;
61
68
 
62
69
  export const STATE_SYMBOL = Symbol('$state');
70
+ /** Marks component export objects, so that `proxy(...)` leaves them untouched */
71
+ export const COMPONENT_SYMBOL = Symbol('component');
63
72
  export const LEGACY_PROPS = Symbol('legacy props');
64
73
  export const LOADING_ATTR_SYMBOL = Symbol('');
65
74
  export const PROXY_PATH_SYMBOL = Symbol('proxy path');
@@ -5,7 +5,9 @@ import { active_effect, active_reaction } from './runtime.js';
5
5
  import { create_user_effect } from './reactivity/effects.js';
6
6
  import { async_mode_flag, legacy_mode_flag } from '../flags/index.js';
7
7
  import { FILENAME } from '../../constants.js';
8
- import { BRANCH_EFFECT } from './constants.js';
8
+ import { BRANCH_EFFECT, COMPONENT_SYMBOL } from './constants.js';
9
+ import { define_property } from '../shared/utils.js';
10
+ import { create_context, get_or_init_context_map } from '../shared/context.js';
9
11
 
10
12
  /** @type {ComponentContext | null} */
11
13
  export let component_context = null;
@@ -70,31 +72,25 @@ export function set_dev_current_component_function(fn) {
70
72
  }
71
73
 
72
74
  /**
73
- * Returns a `[get, set]` pair of functions for working with context in a type-safe way.
75
+ * Returns a `[get, set, has]` triplet of functions for working with context in a type-safe way.
74
76
  *
75
- * `get` will throw an error if no parent component called `set`.
77
+ * `get` will throw an error if `set` has not yet been called in the current component or any of
78
+ * its ancestors.
76
79
  *
77
80
  * @template T
78
- * @returns {[() => T, (context: T) => T]}
81
+ * @returns {[() => T, (context: T) => T, () => boolean]}
79
82
  * @since 5.40.0
80
83
  */
81
84
  export function createContext() {
82
- const key = {};
83
-
84
- return [
85
- () => {
86
- if (!hasContext(key)) {
87
- e.missing_context();
88
- }
89
-
90
- return getContext(key);
91
- },
92
- (context) => setContext(key, context)
93
- ];
85
+ return /** @type {[() => T, (context: T) => T, () => boolean]} */ (
86
+ create_context(getContext, setContext, hasContext)
87
+ );
94
88
  }
95
89
 
96
90
  /**
97
- * Retrieves the context that belongs to the closest parent component with the specified `key`.
91
+ * Retrieves the context set with the specified `key` in the current component or any of its
92
+ * ancestors. If multiple components set the same key, the value from the closest one is returned.
93
+ * A `setContext` call in the current component is only visible to `getContext` calls that run after it.
98
94
  * Must be called during component initialisation.
99
95
  *
100
96
  * [`createContext`](https://svelte.dev/docs/svelte/svelte#createContext) is a type-safe alternative.
@@ -104,15 +100,15 @@ export function createContext() {
104
100
  * @returns {T}
105
101
  */
106
102
  export function getContext(key) {
107
- const context_map = get_or_init_context_map('getContext');
103
+ const context_map = get_or_init_context_map(component_context, 'getContext');
108
104
  const result = /** @type {T} */ (context_map.get(key));
109
105
  return result;
110
106
  }
111
107
 
112
108
  /**
113
109
  * Associates an arbitrary `context` object with the current component and the specified `key`
114
- * and returns that object. The context is then available to children of the component
115
- * (including slotted content) with `getContext`.
110
+ * and returns that object. The context is then available to the component itself and all of its
111
+ * descendants (including slotted content) with `getContext`.
116
112
  *
117
113
  * Like lifecycle functions, this must be called during component initialisation.
118
114
  *
@@ -124,7 +120,7 @@ export function getContext(key) {
124
120
  * @returns {T}
125
121
  */
126
122
  export function setContext(key, context) {
127
- const context_map = get_or_init_context_map('setContext');
123
+ const context_map = get_or_init_context_map(component_context, 'setContext');
128
124
 
129
125
  if (async_mode_flag) {
130
126
  var flags = /** @type {Effect} */ (active_effect).f;
@@ -144,27 +140,27 @@ export function setContext(key, context) {
144
140
  }
145
141
 
146
142
  /**
147
- * Checks whether a given `key` has been set in the context of a parent component.
148
- * Must be called during component initialisation.
143
+ * Checks whether a given `key` has been set in the context of the current component or any of
144
+ * its ancestors. Must be called during component initialisation.
149
145
  *
150
146
  * @param {any} key
151
147
  * @returns {boolean}
152
148
  */
153
149
  export function hasContext(key) {
154
- const context_map = get_or_init_context_map('hasContext');
150
+ const context_map = get_or_init_context_map(component_context, 'hasContext');
155
151
  return context_map.has(key);
156
152
  }
157
153
 
158
154
  /**
159
- * Retrieves the whole context map that belongs to the closest parent component.
160
- * Must be called during component initialisation. Useful, for example, if you
161
- * programmatically create a component and want to pass the existing context to it.
155
+ * Retrieves the whole context map that belongs to the current component, including entries
156
+ * inherited from its ancestors. Must be called during component initialisation. Useful, for
157
+ * example, if you programmatically create a component and want to pass the existing context to it.
162
158
  *
163
159
  * @template {Map<any, any>} [T=Map<any, any>]
164
160
  * @returns {T}
165
161
  */
166
162
  export function getAllContexts() {
167
- const context_map = get_or_init_context_map('getAllContexts');
163
+ const context_map = get_or_init_context_map(component_context, 'getAllContexts');
168
164
  return /** @type {T} */ (context_map);
169
165
  }
170
166
 
@@ -222,38 +218,19 @@ export function pop(component) {
222
218
  dev_current_component_function = component_context?.function ?? null;
223
219
  }
224
220
 
225
- return component ?? /** @type {T} */ ({});
226
- }
227
-
228
- /** @returns {boolean} */
229
- export function is_runes() {
230
- return !legacy_mode_flag || (component_context !== null && component_context.l === null);
221
+ return mark_as_component(component);
231
222
  }
232
223
 
233
224
  /**
234
- * @param {string} name
235
- * @returns {Map<unknown, unknown>}
225
+ * Add a symbol to the object (or create one if undefined) to mark it as a component so it isn't proxified.
226
+ * @param {any} component
236
227
  */
237
- function get_or_init_context_map(name) {
238
- if (component_context === null) {
239
- e.lifecycle_outside_component(name);
240
- }
241
-
242
- return (component_context.c ??= new Map(get_parent_context(component_context) || undefined));
228
+ export function mark_as_component(component = {}) {
229
+ define_property(component, COMPONENT_SYMBOL, { value: true });
230
+ return component;
243
231
  }
244
232
 
245
- /**
246
- * @param {ComponentContext} component_context
247
- * @returns {Map<unknown, unknown> | null}
248
- */
249
- function get_parent_context(component_context) {
250
- let parent = component_context.p;
251
- while (parent !== null) {
252
- const context_map = parent.c;
253
- if (context_map !== null) {
254
- return context_map;
255
- }
256
- parent = parent.p;
257
- }
258
- return null;
233
+ /** @returns {boolean} */
234
+ export function is_runes() {
235
+ return !legacy_mode_flag || (component_context !== null && component_context.l === null);
259
236
  }
@@ -57,10 +57,21 @@ export function hmr(fn) {
57
57
  if (ran) set_should_intro(true);
58
58
  });
59
59
 
60
- // Forward the nodes from the inner effect to the outer active effect which would
61
- // get them if the HMR wrapper wasn't there. Do this inside the block not outside
62
- // so that HMR updates to the component will also update the nodes on the active effect.
63
- /** @type {Effect} */ (active_effect).nodes = effect.nodes;
60
+ // Forward the start/end DOM nodes from the inner effect to the outer active effect
61
+ // which would get them if the HMR wrapper wasn't there. Do this inside the block not
62
+ // outside so that HMR updates to the component will also update the nodes on the
63
+ // active effect. We copy only start/end, not the full nodes object, so that
64
+ // pause_children does not collect transitions from both effects and fire outroend twice.
65
+ var inner_nodes = effect.nodes;
66
+ if (inner_nodes) {
67
+ var ae = /** @type {Effect} */ (active_effect);
68
+ if (ae.nodes) {
69
+ ae.nodes.start = inner_nodes.start;
70
+ ae.nodes.end = inner_nodes.end;
71
+ } else {
72
+ ae.nodes = { start: inner_nodes.start, end: inner_nodes.end, a: null, t: null };
73
+ }
74
+ }
64
75
  }, EFFECT_TRANSPARENT);
65
76
 
66
77
  ran = true;