svelte 5.2.7 → 5.2.8

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.2.7",
5
+ "version": "5.2.8",
6
6
  "type": "module",
7
7
  "types": "./types/index.d.ts",
8
8
  "engines": {
package/src/ambient.d.ts CHANGED
@@ -1,17 +1,9 @@
1
1
  declare module '*.svelte' {
2
2
  // use prettier-ignore for a while because of https://github.com/sveltejs/language-tools/commit/026111228b5814a9109cc4d779d37fb02955fb8b
3
3
  // prettier-ignore
4
- import { SvelteComponent, Component, type ComponentConstructorOptions } from 'svelte'
5
-
6
- // Support using the component as both a class and function during the transition period
7
- // prettier-ignore
8
- interface ComponentType {
9
- (
10
- ...args: Parameters<Component<Record<string, any>>>
11
- ): ReturnType<Component<Record<string, any>, Record<string, any>>>
12
- new (o: ComponentConstructorOptions): SvelteComponent
13
- }
14
- const Comp: ComponentType;
4
+ import { SvelteComponent } from 'svelte'
5
+ import { LegacyComponentType } from 'svelte/legacy';
6
+ const Comp: LegacyComponentType;
15
7
  type Comp = SvelteComponent;
16
8
  export default Comp;
17
9
  }
@@ -260,12 +260,15 @@ function apply_combinator(combinator, relative_selector, parent_selectors, rule,
260
260
  switch (name) {
261
261
  case ' ':
262
262
  case '>': {
263
- let parent = /** @type {Compiler.TemplateNode | null} */ (element.parent);
264
-
265
263
  let parent_matched = false;
266
264
  let crossed_component_boundary = false;
267
265
 
268
- while (parent) {
266
+ const path = element.metadata.path;
267
+ let i = path.length;
268
+
269
+ while (i--) {
270
+ const parent = path[i];
271
+
269
272
  if (parent.type === 'Component' || parent.type === 'SvelteComponent') {
270
273
  crossed_component_boundary = true;
271
274
  }
@@ -289,8 +292,6 @@ function apply_combinator(combinator, relative_selector, parent_selectors, rule,
289
292
 
290
293
  if (name === '>') return parent_matched;
291
294
  }
292
-
293
- parent = /** @type {Compiler.TemplateNode | null} */ (parent.parent);
294
295
  }
295
296
 
296
297
  return parent_matched || parent_selectors.every((selector) => is_global(selector, rule));
@@ -679,51 +680,50 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
679
680
  * @param {boolean} include_self
680
681
  */
681
682
  function get_following_sibling_elements(element, include_self) {
682
- /** @type {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.Root | null} */
683
- let parent = get_element_parent(element);
683
+ const path = element.metadata.path;
684
+ let i = path.length;
685
+
686
+ /** @type {Compiler.SvelteNode} */
687
+ let start = element;
688
+ let nodes = /** @type {Compiler.SvelteNode[]} */ (
689
+ /** @type {Compiler.AST.Fragment} */ (path[0]).nodes
690
+ );
691
+
692
+ // find the set of nodes to walk...
693
+ while (i--) {
694
+ const node = path[i];
684
695
 
685
- if (!parent) {
686
- parent = element;
687
- while (parent?.type !== 'Root') {
688
- parent = /** @type {any} */ (parent).parent;
696
+ if (node.type === 'RegularElement' || node.type === 'SvelteElement') {
697
+ nodes = node.fragment.nodes;
698
+ break;
699
+ }
700
+
701
+ if (node.type !== 'Fragment') {
702
+ start = node;
689
703
  }
690
704
  }
691
705
 
692
706
  /** @type {Array<Compiler.AST.RegularElement | Compiler.AST.SvelteElement>} */
693
- const sibling_elements = [];
694
- let found_parent = false;
695
-
696
- for (const el of parent.fragment.nodes) {
697
- if (found_parent) {
698
- walk(
699
- el,
700
- {},
701
- {
702
- RegularElement(node) {
703
- sibling_elements.push(node);
704
- },
705
- SvelteElement(node) {
706
- sibling_elements.push(node);
707
- }
708
- }
709
- );
710
- } else {
711
- /** @type {any} */
712
- let child = element;
713
- while (child !== el && child !== parent) {
714
- child = child.parent;
715
- }
716
- if (child === el) {
717
- found_parent = true;
707
+ const siblings = [];
708
+
709
+ // ...then walk them, starting from the node after the one
710
+ // containing the element in question
711
+ for (const node of nodes.slice(nodes.indexOf(start) + 1)) {
712
+ walk(node, null, {
713
+ RegularElement(node) {
714
+ siblings.push(node);
715
+ },
716
+ SvelteElement(node) {
717
+ siblings.push(node);
718
718
  }
719
- }
719
+ });
720
720
  }
721
721
 
722
722
  if (include_self) {
723
- sibling_elements.push(element);
723
+ siblings.push(element);
724
724
  }
725
725
 
726
- return sibling_elements;
726
+ return siblings;
727
727
  }
728
728
 
729
729
  /**
@@ -867,15 +867,18 @@ function unquote(str) {
867
867
  * @returns {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | null}
868
868
  */
869
869
  function get_element_parent(node) {
870
- /** @type {Compiler.SvelteNode | null} */
871
- let parent = node;
872
- while (
873
- // @ts-expect-error TODO figure out a more elegant solution
874
- (parent = parent.parent) &&
875
- parent.type !== 'RegularElement' &&
876
- parent.type !== 'SvelteElement'
877
- );
878
- return parent ?? null;
870
+ let path = node.metadata.path;
871
+ let i = path.length;
872
+
873
+ while (i--) {
874
+ const parent = path[i];
875
+
876
+ if (parent.type === 'RegularElement' || parent.type === 'SvelteElement') {
877
+ return parent;
878
+ }
879
+ }
880
+
881
+ return null;
879
882
  }
880
883
 
881
884
  /**
@@ -920,7 +923,7 @@ function find_previous_sibling(node) {
920
923
  while (current_node?.type === 'SlotElement') {
921
924
  const slot_children = current_node.fragment.nodes;
922
925
  if (slot_children.length > 0) {
923
- current_node = slot_children.slice(-1)[0];
926
+ current_node = slot_children[slot_children.length - 1];
924
927
  } else {
925
928
  break;
926
929
  }
@@ -952,7 +955,7 @@ function get_possible_element_siblings(node, adjacent_only) {
952
955
  if (adjacent_only) {
953
956
  break;
954
957
  }
955
- } else if (prev.type === 'EachBlock' || prev.type === 'IfBlock' || prev.type === 'AwaitBlock') {
958
+ } else if (is_block(prev)) {
956
959
  const possible_last_child = get_possible_last_child(prev, adjacent_only);
957
960
  add_to_map(possible_last_child, result);
958
961
  if (adjacent_only && has_definite_elements(possible_last_child)) {
@@ -976,7 +979,7 @@ function get_possible_element_siblings(node, adjacent_only) {
976
979
  while (
977
980
  // @ts-expect-error TODO
978
981
  (parent = parent?.parent) &&
979
- (parent.type === 'EachBlock' || parent.type === 'IfBlock' || parent.type === 'AwaitBlock')
982
+ is_block(parent)
980
983
  ) {
981
984
  const possible_siblings = get_possible_element_siblings(parent, adjacent_only);
982
985
  add_to_map(possible_siblings, result);
@@ -997,73 +1000,57 @@ function get_possible_element_siblings(node, adjacent_only) {
997
1000
  }
998
1001
 
999
1002
  /**
1000
- * @param {Compiler.AST.EachBlock | Compiler.AST.IfBlock | Compiler.AST.AwaitBlock} relative_selector
1003
+ * @param {Compiler.AST.EachBlock | Compiler.AST.IfBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock} node
1001
1004
  * @param {boolean} adjacent_only
1002
1005
  * @returns {Map<Compiler.AST.RegularElement, NodeExistsValue>}
1003
1006
  */
1004
- function get_possible_last_child(relative_selector, adjacent_only) {
1007
+ function get_possible_last_child(node, adjacent_only) {
1005
1008
  /** @typedef {Map<Compiler.AST.RegularElement, NodeExistsValue>} NodeMap */
1006
1009
 
1010
+ /** @type {Array<Compiler.AST.Fragment | undefined | null>} */
1011
+ let fragments = [];
1012
+
1013
+ switch (node.type) {
1014
+ case 'EachBlock':
1015
+ fragments.push(node.body, node.fallback);
1016
+ break;
1017
+
1018
+ case 'IfBlock':
1019
+ fragments.push(node.consequent, node.alternate);
1020
+ break;
1021
+
1022
+ case 'AwaitBlock':
1023
+ fragments.push(node.pending, node.then, node.catch);
1024
+ break;
1025
+
1026
+ case 'KeyBlock':
1027
+ fragments.push(node.fragment);
1028
+ break;
1029
+ }
1030
+
1007
1031
  /** @type {NodeMap} */
1008
1032
  const result = new Map();
1009
- if (relative_selector.type === 'EachBlock') {
1010
- /** @type {NodeMap} */
1011
- const each_result = loop_child(relative_selector.body.nodes, adjacent_only);
1012
-
1013
- /** @type {NodeMap} */
1014
- const else_result = relative_selector.fallback
1015
- ? loop_child(relative_selector.fallback.nodes, adjacent_only)
1016
- : new Map();
1017
- const not_exhaustive = !has_definite_elements(else_result);
1018
- if (not_exhaustive) {
1019
- mark_as_probably(each_result);
1020
- mark_as_probably(else_result);
1021
- }
1022
- add_to_map(each_result, result);
1023
- add_to_map(else_result, result);
1024
- } else if (relative_selector.type === 'IfBlock') {
1025
- /** @type {NodeMap} */
1026
- const if_result = loop_child(relative_selector.consequent.nodes, adjacent_only);
1027
-
1028
- /** @type {NodeMap} */
1029
- const else_result = relative_selector.alternate
1030
- ? loop_child(relative_selector.alternate.nodes, adjacent_only)
1031
- : new Map();
1032
- const not_exhaustive = !has_definite_elements(if_result) || !has_definite_elements(else_result);
1033
- if (not_exhaustive) {
1034
- mark_as_probably(if_result);
1035
- mark_as_probably(else_result);
1033
+
1034
+ let exhaustive = true;
1035
+
1036
+ for (const fragment of fragments) {
1037
+ if (fragment == null) {
1038
+ exhaustive = false;
1039
+ continue;
1036
1040
  }
1037
- add_to_map(if_result, result);
1038
- add_to_map(else_result, result);
1039
- } else if (relative_selector.type === 'AwaitBlock') {
1040
- /** @type {NodeMap} */
1041
- const pending_result = relative_selector.pending
1042
- ? loop_child(relative_selector.pending.nodes, adjacent_only)
1043
- : new Map();
1044
-
1045
- /** @type {NodeMap} */
1046
- const then_result = relative_selector.then
1047
- ? loop_child(relative_selector.then.nodes, adjacent_only)
1048
- : new Map();
1049
-
1050
- /** @type {NodeMap} */
1051
- const catch_result = relative_selector.catch
1052
- ? loop_child(relative_selector.catch.nodes, adjacent_only)
1053
- : new Map();
1054
- const not_exhaustive =
1055
- !has_definite_elements(pending_result) ||
1056
- !has_definite_elements(then_result) ||
1057
- !has_definite_elements(catch_result);
1058
- if (not_exhaustive) {
1059
- mark_as_probably(pending_result);
1060
- mark_as_probably(then_result);
1061
- mark_as_probably(catch_result);
1041
+
1042
+ const map = loop_child(fragment.nodes, adjacent_only);
1043
+ exhaustive &&= has_definite_elements(map);
1044
+
1045
+ add_to_map(map, result);
1046
+ }
1047
+
1048
+ if (!exhaustive) {
1049
+ for (const key of result.keys()) {
1050
+ result.set(key, NODE_PROBABLY_EXISTS);
1062
1051
  }
1063
- add_to_map(pending_result, result);
1064
- add_to_map(then_result, result);
1065
- add_to_map(catch_result, result);
1066
1052
  }
1053
+
1067
1054
  return result;
1068
1055
  }
1069
1056
 
@@ -1104,13 +1091,6 @@ function higher_existence(exist1, exist2) {
1104
1091
  return exist1 > exist2 ? exist1 : exist2;
1105
1092
  }
1106
1093
 
1107
- /** @param {Map<Compiler.AST.RegularElement, NodeExistsValue>} result */
1108
- function mark_as_probably(result) {
1109
- for (const key of result.keys()) {
1110
- result.set(key, NODE_PROBABLY_EXISTS);
1111
- }
1112
- }
1113
-
1114
1094
  /**
1115
1095
  * @param {Compiler.SvelteNode[]} children
1116
1096
  * @param {boolean} adjacent_only
@@ -1118,18 +1098,18 @@ function mark_as_probably(result) {
1118
1098
  function loop_child(children, adjacent_only) {
1119
1099
  /** @type {Map<Compiler.AST.RegularElement, NodeExistsValue>} */
1120
1100
  const result = new Map();
1121
- for (let i = children.length - 1; i >= 0; i--) {
1101
+
1102
+ let i = children.length;
1103
+
1104
+ while (i--) {
1122
1105
  const child = children[i];
1106
+
1123
1107
  if (child.type === 'RegularElement') {
1124
1108
  result.set(child, NODE_DEFINITELY_EXISTS);
1125
1109
  if (adjacent_only) {
1126
1110
  break;
1127
1111
  }
1128
- } else if (
1129
- child.type === 'EachBlock' ||
1130
- child.type === 'IfBlock' ||
1131
- child.type === 'AwaitBlock'
1132
- ) {
1112
+ } else if (is_block(child)) {
1133
1113
  const child_result = get_possible_last_child(child, adjacent_only);
1134
1114
  add_to_map(child_result, result);
1135
1115
  if (adjacent_only && has_definite_elements(child_result)) {
@@ -1137,5 +1117,19 @@ function loop_child(children, adjacent_only) {
1137
1117
  }
1138
1118
  }
1139
1119
  }
1120
+
1140
1121
  return result;
1141
1122
  }
1123
+
1124
+ /**
1125
+ * @param {Compiler.SvelteNode} node
1126
+ * @returns {node is Compiler.AST.IfBlock | Compiler.AST.EachBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock}
1127
+ */
1128
+ function is_block(node) {
1129
+ return (
1130
+ node.type === 'IfBlock' ||
1131
+ node.type === 'EachBlock' ||
1132
+ node.type === 'AwaitBlock' ||
1133
+ node.type === 'KeyBlock'
1134
+ );
1135
+ }
@@ -709,8 +709,8 @@ export function analyze_component(root, source, options) {
709
709
  analyze_css(analysis.css.ast, analysis);
710
710
 
711
711
  // mark nodes as scoped/unused/empty etc
712
- for (const element of analysis.elements) {
713
- prune(analysis.css.ast, element);
712
+ for (const node of analysis.elements) {
713
+ prune(analysis.css.ast, node);
714
714
  }
715
715
 
716
716
  const { comment } = analysis.css.ast.content;
@@ -724,18 +724,18 @@ export function analyze_component(root, source, options) {
724
724
  warn_unused(analysis.css.ast);
725
725
  }
726
726
 
727
- outer: for (const element of analysis.elements) {
728
- if (element.type === 'RenderTag') continue;
727
+ outer: for (const node of analysis.elements) {
728
+ if (node.type === 'RenderTag') continue;
729
729
 
730
- if (element.metadata.scoped) {
730
+ if (node.metadata.scoped) {
731
731
  // Dynamic elements in dom mode always use spread for attributes and therefore shouldn't have a class attribute added to them
732
732
  // TODO this happens during the analysis phase, which shouldn't know anything about client vs server
733
- if (element.type === 'SvelteElement' && options.generate === 'client') continue;
733
+ if (node.type === 'SvelteElement' && options.generate === 'client') continue;
734
734
 
735
735
  /** @type {AST.Attribute | undefined} */
736
736
  let class_attribute = undefined;
737
737
 
738
- for (const attribute of element.attributes) {
738
+ for (const attribute of node.attributes) {
739
739
  if (attribute.type === 'SpreadAttribute') {
740
740
  // The spread method appends the hash to the end of the class attribute on its own
741
741
  continue outer;
@@ -768,7 +768,7 @@ export function analyze_component(root, source, options) {
768
768
  }
769
769
  }
770
770
  } else {
771
- element.attributes.push(
771
+ node.attributes.push(
772
772
  create_attribute('class', -1, -1, [
773
773
  {
774
774
  type: 'Text',
@@ -780,8 +780,8 @@ export function analyze_component(root, source, options) {
780
780
  }
781
781
  ])
782
782
  );
783
- if (is_custom_element_node(element) && element.attributes.length === 1) {
784
- mark_subtree_dynamic(element.metadata.path);
783
+ if (is_custom_element_node(node) && node.attributes.length === 1) {
784
+ mark_subtree_dynamic(node.metadata.path);
785
785
  }
786
786
  }
787
787
  }
@@ -9,7 +9,9 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
9
9
  * @param {Context} context
10
10
  */
11
11
  export function ExpressionTag(node, context) {
12
- if (node.parent && context.state.parent_element) {
12
+ const in_attribute = context.path.at(-1)?.type === 'Attribute';
13
+
14
+ if (!in_attribute && context.state.parent_element) {
13
15
  if (!is_tag_valid_with_parent('#text', context.state.parent_element)) {
14
16
  e.node_invalid_placement(node, '`{expression}`', context.state.parent_element);
15
17
  }
@@ -19,11 +19,9 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
19
19
  */
20
20
  export function RegularElement(node, context) {
21
21
  validate_element(node, context);
22
-
23
- check_element(node, context.state);
22
+ check_element(node, context);
24
23
 
25
24
  node.metadata.path = [...context.path];
26
-
27
25
  context.state.analysis.elements.push(node);
28
26
 
29
27
  // Special case: Move the children of <textarea> into a value attribute if they are dynamic
@@ -12,6 +12,7 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
12
12
  export function RenderTag(node, context) {
13
13
  validate_opening_tag(node, context.state, '@');
14
14
 
15
+ node.metadata.path = [...context.path];
15
16
  context.state.analysis.elements.push(node);
16
17
 
17
18
  const callee = unwrap_optional(node.expression).callee;
@@ -12,9 +12,9 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
12
12
  */
13
13
  export function SvelteElement(node, context) {
14
14
  validate_element(node, context);
15
+ check_element(node, context);
15
16
 
16
- check_element(node, context.state);
17
-
17
+ node.metadata.path = [...context.path];
18
18
  context.state.analysis.elements.push(node);
19
19
 
20
20
  const xmlns = /** @type {AST.Attribute & { value: [AST.Text] } | undefined} */ (
@@ -9,7 +9,9 @@ import * as e from '../../../errors.js';
9
9
  * @param {Context} context
10
10
  */
11
11
  export function Text(node, context) {
12
- if (node.parent && context.state.parent_element && regex_not_whitespace.test(node.data)) {
12
+ const in_attribute = context.path.at(-1)?.type === 'Attribute';
13
+
14
+ if (!in_attribute && context.state.parent_element && regex_not_whitespace.test(node.data)) {
13
15
  if (!is_tag_valid_with_parent('#text', context.state.parent_element)) {
14
16
  e.node_invalid_placement(node, 'Text node', context.state.parent_element);
15
17
  }
@@ -1,4 +1,4 @@
1
- /** @import { AnalysisState } from '../../types.js' */
1
+ /** @import { Context } from '../../types.js' */
2
2
  /** @import { AST, SvelteNode, TemplateNode } from '#compiler' */
3
3
  /** @import { ARIARoleDefinitionKey, ARIARoleRelationConcept, ARIAProperty, ARIAPropertyDefinition, ARIARoleDefinition } from 'aria-query' */
4
4
  import { roles as roles_map, aria, elementRoles } from 'aria-query';
@@ -582,16 +582,17 @@ function get_implicit_role(name, attribute_map) {
582
582
  const invisible_elements = ['meta', 'html', 'script', 'style'];
583
583
 
584
584
  /**
585
- * @param {SvelteNode | null} parent
585
+ * @param {SvelteNode[]} path
586
586
  * @param {string[]} elements
587
587
  */
588
- function is_parent(parent, elements) {
589
- while (parent) {
588
+ function is_parent(path, elements) {
589
+ let i = path.length;
590
+ while (i--) {
591
+ const parent = path[i];
590
592
  if (parent.type === 'SvelteElement') return true; // unknown, play it safe, so we don't warn
591
593
  if (parent.type === 'RegularElement') {
592
594
  return elements.includes(parent.name);
593
595
  }
594
- parent = /** @type {TemplateNode} */ (parent).parent;
595
596
  }
596
597
  return false;
597
598
  }
@@ -683,9 +684,9 @@ function get_static_text_value(attribute) {
683
684
 
684
685
  /**
685
686
  * @param {AST.RegularElement | AST.SvelteElement} node
686
- * @param {AnalysisState} state
687
+ * @param {Context} context
687
688
  */
688
- export function check_element(node, state) {
689
+ export function check_element(node, context) {
689
690
  /** @type {Map<string, AST.Attribute>} */
690
691
  const attribute_map = new Map();
691
692
 
@@ -792,7 +793,7 @@ export function check_element(node, state) {
792
793
  }
793
794
 
794
795
  // Footers and headers are special cases, and should not have redundant roles unless they are the children of sections or articles.
795
- const is_parent_section_or_article = is_parent(node.parent, ['section', 'article']);
796
+ const is_parent_section_or_article = is_parent(context.path, ['section', 'article']);
796
797
  if (!is_parent_section_or_article) {
797
798
  const has_nested_redundant_role =
798
799
  current_role === a11y_nested_implicit_semantics.get(node.name);
@@ -1114,7 +1115,7 @@ export function check_element(node, state) {
1114
1115
  }
1115
1116
 
1116
1117
  if (node.name === 'figcaption') {
1117
- if (!is_parent(node.parent, ['figure'])) {
1118
+ if (!is_parent(context.path, ['figure'])) {
1118
1119
  w.a11y_figcaption_parent(node);
1119
1120
  }
1120
1121
  }
@@ -167,6 +167,7 @@ export namespace AST {
167
167
  metadata: {
168
168
  dynamic: boolean;
169
169
  args_with_call_expression: Set<number>;
170
+ path: SvelteNode[];
170
171
  };
171
172
  }
172
173
 
@@ -344,6 +345,7 @@ export namespace AST {
344
345
  */
345
346
  mathml: boolean;
346
347
  scoped: boolean;
348
+ path: SvelteNode[];
347
349
  };
348
350
  }
349
351
 
@@ -5,7 +5,7 @@ import { create_event, delegate } from './events.js';
5
5
  import { add_form_reset_listener, autofocus } from './misc.js';
6
6
  import * as w from '../../warnings.js';
7
7
  import { LOADING_ATTR_SYMBOL } from '../../constants.js';
8
- import { queue_idle_task, queue_micro_task } from '../task.js';
8
+ import { queue_idle_task } from '../task.js';
9
9
  import { is_capture_event, is_delegated, normalize_attribute } from '../../../../utils.js';
10
10
  import {
11
11
  active_effect,
@@ -209,8 +209,6 @@ export function set_attributes(
209
209
 
210
210
  // @ts-expect-error
211
211
  var attributes = /** @type {Record<string, unknown>} **/ (element.__attributes ??= {});
212
- /** @type {Array<[string, any, () => void]>} */
213
- var events = [];
214
212
 
215
213
  // since key is captured we use const
216
214
  for (const key in next) {
@@ -277,15 +275,7 @@ export function set_attributes(
277
275
  current[key].call(this, evt);
278
276
  }
279
277
 
280
- if (!prev) {
281
- events.push([
282
- key,
283
- value,
284
- () => (current[event_handle_key] = create_event(event_name, element, handle, opts))
285
- ]);
286
- } else {
287
- current[event_handle_key] = create_event(event_name, element, handle, opts);
288
- }
278
+ current[event_handle_key] = create_event(event_name, element, handle, opts);
289
279
  } else {
290
280
  // @ts-ignore
291
281
  element[`__${event_name}`] = value;
@@ -325,19 +315,6 @@ export function set_attributes(
325
315
  }
326
316
  }
327
317
 
328
- // On the first run, ensure that events are added after bindings so
329
- // that their listeners fire after the binding listeners
330
- if (!prev) {
331
- queue_micro_task(() => {
332
- if (!element.isConnected) return;
333
- for (const [key, value, evt] of events) {
334
- if (current[key] === value) {
335
- evt();
336
- }
337
- }
338
- });
339
- }
340
-
341
318
  return current;
342
319
  }
343
320
 
@@ -154,8 +154,10 @@ export function first_child(fragment, is_text) {
154
154
  */
155
155
  export function sibling(node, count = 1, is_text = false) {
156
156
  let next_sibling = hydrating ? hydrate_node : node;
157
+ var last_sibling;
157
158
 
158
159
  while (count--) {
160
+ last_sibling = next_sibling;
159
161
  next_sibling = /** @type {TemplateNode} */ (get_next_sibling(next_sibling));
160
162
  }
161
163
 
@@ -163,13 +165,20 @@ export function sibling(node, count = 1, is_text = false) {
163
165
  return next_sibling;
164
166
  }
165
167
 
166
- var type = next_sibling.nodeType;
168
+ var type = next_sibling?.nodeType;
167
169
 
168
170
  // if a sibling {expression} is empty during SSR, there might be no
169
171
  // text node to hydrate — we must therefore create one
170
172
  if (is_text && type !== 3) {
171
173
  var text = create_text();
172
- next_sibling?.before(text);
174
+ // If the next sibling is `null` and we're handling text then it's because
175
+ // the SSR content was empty for the text, so we need to generate a new text
176
+ // node and insert it after the last sibling
177
+ if (next_sibling === null) {
178
+ last_sibling?.after(text);
179
+ } else {
180
+ next_sibling.before(text);
181
+ }
173
182
  set_hydrate_node(text);
174
183
  return text;
175
184
  }
@@ -63,6 +63,11 @@ export function asClassComponent(component) {
63
63
  };
64
64
  }
65
65
 
66
+ /**
67
+ * Support using the component as both a class and function during the transition period
68
+ * @typedef {{new (o: ComponentConstructorOptions): SvelteComponent;(...args: Parameters<Component<Record<string, any>>>): ReturnType<Component<Record<string, any>, Record<string, any>>>;}} LegacyComponentType
69
+ */
70
+
66
71
  class Svelte4Component {
67
72
  /** @type {any} */
68
73
  #events;
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.7';
9
+ export const VERSION = '5.2.8';
10
10
  export const PUBLIC_VERSION = '5';