@@ -955,7 +955,7 @@ function get_possible_element_siblings(node, adjacent_only) {
955955 if ( adjacent_only ) {
956956 break ;
957957 }
958- } else if ( prev . type === 'EachBlock' || prev . type === 'IfBlock' || prev . type === 'AwaitBlock' ) {
958+ } else if ( is_block ( prev ) ) {
959959 const possible_last_child = get_possible_last_child ( prev , adjacent_only ) ;
960960 add_to_map ( possible_last_child , result ) ;
961961 if ( adjacent_only && has_definite_elements ( possible_last_child ) ) {
@@ -979,7 +979,7 @@ function get_possible_element_siblings(node, adjacent_only) {
979979 while (
980980 // @ts -expect-error TODO
981981 ( parent = parent ?. parent ) &&
982- ( parent . type === 'EachBlock' || parent . type === 'IfBlock' || parent . type === 'AwaitBlock' )
982+ is_block ( parent )
983983 ) {
984984 const possible_siblings = get_possible_element_siblings ( parent , adjacent_only ) ;
985985 add_to_map ( possible_siblings , result ) ;
@@ -1000,73 +1000,57 @@ function get_possible_element_siblings(node, adjacent_only) {
10001000}
10011001
10021002/**
1003- * @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
10041004 * @param {boolean } adjacent_only
10051005 * @returns {Map<Compiler.AST.RegularElement, NodeExistsValue> }
10061006 */
1007- function get_possible_last_child ( relative_selector , adjacent_only ) {
1007+ function get_possible_last_child ( node , adjacent_only ) {
10081008 /** @typedef {Map<Compiler.AST.RegularElement, NodeExistsValue> } NodeMap */
10091009
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+
10101031 /** @type {NodeMap } */
10111032 const result = new Map ( ) ;
1012- if ( relative_selector . type === 'EachBlock' ) {
1013- /** @type {NodeMap } */
1014- const each_result = loop_child ( relative_selector . body . nodes , adjacent_only ) ;
1015-
1016- /** @type {NodeMap } */
1017- const else_result = relative_selector . fallback
1018- ? loop_child ( relative_selector . fallback . nodes , adjacent_only )
1019- : new Map ( ) ;
1020- const not_exhaustive = ! has_definite_elements ( else_result ) ;
1021- if ( not_exhaustive ) {
1022- mark_as_probably ( each_result ) ;
1023- mark_as_probably ( else_result ) ;
1024- }
1025- add_to_map ( each_result , result ) ;
1026- add_to_map ( else_result , result ) ;
1027- } else if ( relative_selector . type === 'IfBlock' ) {
1028- /** @type {NodeMap } */
1029- const if_result = loop_child ( relative_selector . consequent . nodes , adjacent_only ) ;
1030-
1031- /** @type {NodeMap } */
1032- const else_result = relative_selector . alternate
1033- ? loop_child ( relative_selector . alternate . nodes , adjacent_only )
1034- : new Map ( ) ;
1035- const not_exhaustive = ! has_definite_elements ( if_result ) || ! has_definite_elements ( else_result ) ;
1036- if ( not_exhaustive ) {
1037- mark_as_probably ( if_result ) ;
1038- 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 ;
10391040 }
1040- add_to_map ( if_result , result ) ;
1041- add_to_map ( else_result , result ) ;
1042- } else if ( relative_selector . type === 'AwaitBlock' ) {
1043- /** @type {NodeMap } */
1044- const pending_result = relative_selector . pending
1045- ? loop_child ( relative_selector . pending . nodes , adjacent_only )
1046- : new Map ( ) ;
1047-
1048- /** @type {NodeMap } */
1049- const then_result = relative_selector . then
1050- ? loop_child ( relative_selector . then . nodes , adjacent_only )
1051- : new Map ( ) ;
1052-
1053- /** @type {NodeMap } */
1054- const catch_result = relative_selector . catch
1055- ? loop_child ( relative_selector . catch . nodes , adjacent_only )
1056- : new Map ( ) ;
1057- const not_exhaustive =
1058- ! has_definite_elements ( pending_result ) ||
1059- ! has_definite_elements ( then_result ) ||
1060- ! has_definite_elements ( catch_result ) ;
1061- if ( not_exhaustive ) {
1062- mark_as_probably ( pending_result ) ;
1063- mark_as_probably ( then_result ) ;
1064- 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 ) ;
10651051 }
1066- add_to_map ( pending_result , result ) ;
1067- add_to_map ( then_result , result ) ;
1068- add_to_map ( catch_result , result ) ;
10691052 }
1053+
10701054 return result ;
10711055}
10721056
@@ -1107,13 +1091,6 @@ function higher_existence(exist1, exist2) {
11071091 return exist1 > exist2 ? exist1 : exist2 ;
11081092}
11091093
1110- /** @param {Map<Compiler.AST.RegularElement, NodeExistsValue> } result */
1111- function mark_as_probably ( result ) {
1112- for ( const key of result . keys ( ) ) {
1113- result . set ( key , NODE_PROBABLY_EXISTS ) ;
1114- }
1115- }
1116-
11171094/**
11181095 * @param {Compiler.SvelteNode[] } children
11191096 * @param {boolean } adjacent_only
@@ -1132,11 +1109,7 @@ function loop_child(children, adjacent_only) {
11321109 if ( adjacent_only ) {
11331110 break ;
11341111 }
1135- } else if (
1136- child . type === 'EachBlock' ||
1137- child . type === 'IfBlock' ||
1138- child . type === 'AwaitBlock'
1139- ) {
1112+ } else if ( is_block ( child ) ) {
11401113 const child_result = get_possible_last_child ( child , adjacent_only ) ;
11411114 add_to_map ( child_result , result ) ;
11421115 if ( adjacent_only && has_definite_elements ( child_result ) ) {
@@ -1147,3 +1120,16 @@ function loop_child(children, adjacent_only) {
11471120
11481121 return result ;
11491122}
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+ }
0 commit comments