@@ -955,7 +955,7 @@ function get_possible_element_siblings(node, adjacent_only) {
955
955
if ( adjacent_only ) {
956
956
break ;
957
957
}
958
- } else if ( prev . type === 'EachBlock' || prev . type === 'IfBlock' || prev . type === 'AwaitBlock' ) {
958
+ } else if ( is_block ( prev ) ) {
959
959
const possible_last_child = get_possible_last_child ( prev , adjacent_only ) ;
960
960
add_to_map ( possible_last_child , result ) ;
961
961
if ( adjacent_only && has_definite_elements ( possible_last_child ) ) {
@@ -979,7 +979,7 @@ function get_possible_element_siblings(node, adjacent_only) {
979
979
while (
980
980
// @ts -expect-error TODO
981
981
( parent = parent ?. parent ) &&
982
- ( parent . type === 'EachBlock' || parent . type === 'IfBlock' || parent . type === 'AwaitBlock' )
982
+ is_block ( parent )
983
983
) {
984
984
const possible_siblings = get_possible_element_siblings ( parent , adjacent_only ) ;
985
985
add_to_map ( possible_siblings , result ) ;
@@ -1000,73 +1000,57 @@ function get_possible_element_siblings(node, adjacent_only) {
1000
1000
}
1001
1001
1002
1002
/**
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
1004
1004
* @param {boolean } adjacent_only
1005
1005
* @returns {Map<Compiler.AST.RegularElement, NodeExistsValue> }
1006
1006
*/
1007
- function get_possible_last_child ( relative_selector , adjacent_only ) {
1007
+ function get_possible_last_child ( node , adjacent_only ) {
1008
1008
/** @typedef {Map<Compiler.AST.RegularElement, NodeExistsValue> } NodeMap */
1009
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
+
1010
1031
/** @type {NodeMap } */
1011
1032
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 ;
1039
1040
}
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 ) ;
1065
1051
}
1066
- add_to_map ( pending_result , result ) ;
1067
- add_to_map ( then_result , result ) ;
1068
- add_to_map ( catch_result , result ) ;
1069
1052
}
1053
+
1070
1054
return result ;
1071
1055
}
1072
1056
@@ -1107,13 +1091,6 @@ function higher_existence(exist1, exist2) {
1107
1091
return exist1 > exist2 ? exist1 : exist2 ;
1108
1092
}
1109
1093
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
-
1117
1094
/**
1118
1095
* @param {Compiler.SvelteNode[] } children
1119
1096
* @param {boolean } adjacent_only
@@ -1132,11 +1109,7 @@ function loop_child(children, adjacent_only) {
1132
1109
if ( adjacent_only ) {
1133
1110
break ;
1134
1111
}
1135
- } else if (
1136
- child . type === 'EachBlock' ||
1137
- child . type === 'IfBlock' ||
1138
- child . type === 'AwaitBlock'
1139
- ) {
1112
+ } else if ( is_block ( child ) ) {
1140
1113
const child_result = get_possible_last_child ( child , adjacent_only ) ;
1141
1114
add_to_map ( child_result , result ) ;
1142
1115
if ( adjacent_only && has_definite_elements ( child_result ) ) {
@@ -1147,3 +1120,16 @@ function loop_child(children, adjacent_only) {
1147
1120
1148
1121
return result ;
1149
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
+ }
0 commit comments