@@ -7,7 +7,6 @@ import { get_attribute_chunks, is_text_attribute } from '../../../utils/ast.js';
77
88/**
99 * @typedef {{
10- * stylesheet: Compiler.Css.StyleSheet;
1110 * element: Compiler.AST.RegularElement | Compiler.AST.SvelteElement;
1211 * from_render_tag: boolean;
1312 * }} State
@@ -61,9 +60,9 @@ export function prune(stylesheet, element) {
6160 const parent = get_element_parent ( element ) ;
6261 if ( ! parent ) return ;
6362
64- walk ( stylesheet , { stylesheet , element : parent , from_render_tag : true } , visitors ) ;
63+ walk ( stylesheet , { element : parent , from_render_tag : true } , visitors ) ;
6564 } else {
66- walk ( stylesheet , { stylesheet , element, from_render_tag : false } , visitors ) ;
65+ walk ( stylesheet , { element, from_render_tag : false } , visitors ) ;
6766 }
6867}
6968
@@ -882,125 +881,71 @@ function get_element_parent(node) {
882881}
883882
884883/**
885- * Finds the given node's previous sibling in the DOM
886- *
887- * The Svelte `<slot>` is just a placeholder and is not actually real. Any children nodes
888- * in `<slot>` are 'flattened' and considered as the same level as the `<slot>`'s siblings
889- *
890- * e.g.
891- * ```html
892- * <h1>Heading 1</h1>
893- * <slot>
894- * <h2>Heading 2</h2>
895- * </slot>
896- * ```
897- *
898- * is considered to look like:
899- * ```html
900- * <h1>Heading 1</h1>
901- * <h2>Heading 2</h2>
902- * ```
903- * @param {Compiler.SvelteNode } node
904- * @returns {Compiler.SvelteNode }
905- */
906- function find_previous_sibling ( node ) {
907- /** @type {Compiler.SvelteNode } */
908- let current_node = node ;
909-
910- while (
911- // @ts -expect-error TODO
912- ! current_node . prev &&
913- // @ts -expect-error TODO
914- current_node . parent ?. type === 'SlotElement'
915- ) {
916- // @ts -expect-error TODO
917- current_node = current_node . parent ;
918- }
919-
920- // @ts -expect-error
921- current_node = current_node . prev ;
922-
923- while ( current_node ?. type === 'SlotElement' ) {
924- const slot_children = current_node . fragment . nodes ;
925- if ( slot_children . length > 0 ) {
926- current_node = slot_children [ slot_children . length - 1 ] ;
927- } else {
928- break ;
929- }
930- }
931-
932- return current_node ;
933- }
934-
935- /**
936- * @param {Compiler.SvelteNode } node
884+ * @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement } element
937885 * @param {boolean } adjacent_only
938886 * @returns {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.SlotElement | Compiler.AST.RenderTag, NodeExistsValue> }
939887 */
940- function get_possible_element_siblings ( node , adjacent_only ) {
888+ function get_possible_element_siblings ( element , adjacent_only ) {
941889 /** @type {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.SlotElement | Compiler.AST.RenderTag, NodeExistsValue> } */
942890 const result = new Map ( ) ;
891+ const path = element . metadata . path ;
943892
944893 /** @type {Compiler.SvelteNode } */
945- let prev = node ;
946- while ( ( prev = find_previous_sibling ( prev ) ) ) {
947- if ( prev . type === 'RegularElement' ) {
948- if (
949- ! prev . attributes . find (
894+ let current = element ;
895+
896+ let i = path . length ;
897+
898+ while ( i -- ) {
899+ const fragment = /** @type {Compiler.AST.Fragment } */ ( path [ i -- ] ) ;
900+ let j = fragment . nodes . indexOf ( current ) ;
901+
902+ while ( j -- ) {
903+ const node = fragment . nodes [ j ] ;
904+
905+ if ( node . type === 'RegularElement' ) {
906+ const has_slot_attribute = node . attributes . some (
950907 ( attr ) => attr . type === 'Attribute' && attr . name . toLowerCase ( ) === 'slot'
951- )
952- ) {
953- result . set ( prev , NODE_DEFINITELY_EXISTS ) ;
954- }
955- if ( adjacent_only ) {
956- break ;
957- }
958- } else if ( is_block ( prev ) ) {
959- const possible_last_child = get_possible_last_child ( prev , adjacent_only ) ;
960- add_to_map ( possible_last_child , result ) ;
961- if ( adjacent_only && has_definite_elements ( possible_last_child ) ) {
962- return result ;
963- }
964- } else if (
965- prev . type === 'SlotElement' ||
966- prev . type === 'RenderTag' ||
967- prev . type === 'SvelteElement'
968- ) {
969- result . set ( prev , NODE_PROBABLY_EXISTS ) ;
970- // Special case: slots, render tags and svelte:element tags could resolve to no siblings,
971- // so we want to continue until we find a definite sibling even with the adjacent-only combinator
972- }
973- }
908+ ) ;
974909
975- if ( ! prev || ! adjacent_only ) {
976- /** @type {Compiler.SvelteNode | null } */
977- let parent = node ;
910+ if ( ! has_slot_attribute ) {
911+ result . set ( node , NODE_DEFINITELY_EXISTS ) ;
978912
979- while (
980- // @ts -expect-error TODO
981- ( parent = parent ?. parent ) &&
982- is_block ( parent )
983- ) {
984- const possible_siblings = get_possible_element_siblings ( parent , adjacent_only ) ;
985- add_to_map ( possible_siblings , result ) ;
913+ if ( adjacent_only ) {
914+ return result ;
915+ }
916+ }
917+ } else if ( is_block ( node ) ) {
918+ if ( node . type === 'SlotElement' ) {
919+ result . set ( node , NODE_PROBABLY_EXISTS ) ;
920+ }
986921
987- // @ts -expect-error
988- if ( parent . type === 'EachBlock' && ! parent . fallback ?. nodes . includes ( node ) ) {
989- // `{#each ...}<a /><b />{/each}` — `<b>` can be previous sibling of `<a />`
990- add_to_map ( get_possible_last_child ( parent , adjacent_only ) , result ) ;
922+ const possible_last_child = get_possible_last_child ( node , adjacent_only ) ;
923+ add_to_map ( possible_last_child , result ) ;
924+ if ( adjacent_only && has_definite_elements ( possible_last_child ) ) {
925+ return result ;
926+ }
927+ } else if ( node . type === 'RenderTag' || node . type === 'SvelteElement' ) {
928+ result . set ( node , NODE_PROBABLY_EXISTS ) ;
929+ // Special case: slots, render tags and svelte:element tags could resolve to no siblings,
930+ // so we want to continue until we find a definite sibling even with the adjacent-only combinator
991931 }
932+ }
992933
993- if ( adjacent_only && has_definite_elements ( possible_siblings ) ) {
994- break ;
995- }
934+ current = path [ i ] ;
935+
936+ if ( ! current || ! is_block ( current ) ) break ;
937+
938+ if ( current . type === 'EachBlock' && fragment === current . body ) {
939+ // `{#each ...}<a /><b />{/each}` — `<b>` can be previous sibling of `<a />`
940+ add_to_map ( get_possible_last_child ( current , adjacent_only ) , result ) ;
996941 }
997942 }
998943
999944 return result ;
1000945}
1001946
1002947/**
1003- * @param {Compiler.AST.EachBlock | Compiler.AST.IfBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock } node
948+ * @param {Compiler.AST.EachBlock | Compiler.AST.IfBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock | Compiler.AST.SlotElement } node
1004949 * @param {boolean } adjacent_only
1005950 * @returns {Map<Compiler.AST.RegularElement, NodeExistsValue> }
1006951 */
@@ -1024,14 +969,15 @@ function get_possible_last_child(node, adjacent_only) {
1024969 break ;
1025970
1026971 case 'KeyBlock' :
972+ case 'SlotElement' :
1027973 fragments . push ( node . fragment ) ;
1028974 break ;
1029975 }
1030976
1031977 /** @type {NodeMap } */
1032978 const result = new Map ( ) ;
1033979
1034- let exhaustive = true ;
980+ let exhaustive = node . type !== 'SlotElement' ;
1035981
1036982 for ( const fragment of fragments ) {
1037983 if ( fragment == null ) {
@@ -1123,13 +1069,14 @@ function loop_child(children, adjacent_only) {
11231069
11241070/**
11251071 * @param {Compiler.SvelteNode } node
1126- * @returns {node is Compiler.AST.IfBlock | Compiler.AST.EachBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock }
1072+ * @returns {node is Compiler.AST.IfBlock | Compiler.AST.EachBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock | Compiler.AST.SlotElement }
11271073 */
11281074function is_block ( node ) {
11291075 return (
11301076 node . type === 'IfBlock' ||
11311077 node . type === 'EachBlock' ||
11321078 node . type === 'AwaitBlock' ||
1133- node . type === 'KeyBlock'
1079+ node . type === 'KeyBlock' ||
1080+ node . type === 'SlotElement'
11341081 ) ;
11351082}
0 commit comments