@@ -36,6 +36,7 @@ import {
3636 EACH_KEYED ,
3737 is_capture_event ,
3838 TEMPLATE_FRAGMENT ,
39+ TEMPLATE_UNSET_START ,
3940 TEMPLATE_USE_IMPORT_NODE ,
4041 TRANSITION_GLOBAL ,
4142 TRANSITION_IN ,
@@ -942,6 +943,7 @@ function serialize_inline_component(node, component_name, context) {
942943 fn = ( node_id ) => {
943944 return b . call (
944945 '$.component' ,
946+ node_id ,
945947 b . thunk ( /** @type {import('estree').Expression } */ ( context . visit ( node . expression ) ) ) ,
946948 b . arrow (
947949 [ b . id ( component_name ) ] ,
@@ -1679,14 +1681,35 @@ export const template_visitors = {
16791681
16801682 process_children ( trimmed , expression , false , { ...context , state } ) ;
16811683
1684+ var first = trimmed [ 0 ] ;
1685+
1686+ /**
1687+ * If the first item in an effect is a static slot or render tag, it will clone
1688+ * a template but without creating a child effect. In these cases, we need to keep
1689+ * the current `effect.nodes.start` undefined, so that it can be populated by
1690+ * the item in question
1691+ * TODO come up with a better name than `unset`
1692+ */
1693+ var unset = false ;
1694+
1695+ if ( first . type === 'SlotElement' ) unset = true ;
1696+ if ( first . type === 'RenderTag' && ! first . metadata . dynamic ) unset = true ;
1697+ if ( first . type === 'Component' && ! first . metadata . dynamic && ! context . state . options . hmr ) {
1698+ unset = true ;
1699+ }
1700+
16821701 const use_comment_template = state . template . length === 1 && state . template [ 0 ] === '<!>' ;
16831702
16841703 if ( use_comment_template ) {
16851704 // special case — we can use `$.comment` instead of creating a unique template
1686- body . push ( b . var ( id , b . call ( '$.comment' ) ) ) ;
1705+ body . push ( b . var ( id , b . call ( '$.comment' , unset && b . literal ( unset ) ) ) ) ;
16871706 } else {
16881707 let flags = TEMPLATE_FRAGMENT ;
16891708
1709+ if ( unset ) {
1710+ flags |= TEMPLATE_UNSET_START ;
1711+ }
1712+
16901713 if ( state . metadata . context . template_needs_import_node ) {
16911714 flags |= TEMPLATE_USE_IMPORT_NODE ;
16921715 }
@@ -1831,27 +1854,26 @@ export const template_visitors = {
18311854 context . state . template . push ( '<!>' ) ;
18321855 const callee = unwrap_optional ( node . expression ) . callee ;
18331856 const raw_args = unwrap_optional ( node . expression ) . arguments ;
1834- const is_reactive =
1835- callee . type !== 'Identifier' || context . state . scope . get ( callee . name ) ?. kind !== 'normal' ;
18361857
1837- /** @type {import('estree').Expression[] } */
1838- const args = [ context . state . node ] ;
1839- for ( const arg of raw_args ) {
1840- args . push ( b . thunk ( /** @type {import('estree').Expression } */ ( context . visit ( arg ) ) ) ) ;
1841- }
1858+ const args = raw_args . map ( ( arg ) =>
1859+ b . thunk ( /** @type {import('estree').Expression } */ ( context . visit ( arg ) ) )
1860+ ) ;
18421861
18431862 let snippet_function = /** @type {import('estree').Expression } */ ( context . visit ( callee ) ) ;
18441863 if ( context . state . options . dev ) {
18451864 snippet_function = b . call ( '$.validate_snippet' , snippet_function ) ;
18461865 }
18471866
1848- if ( is_reactive ) {
1849- context . state . init . push ( b . stmt ( b . call ( '$.snippet' , b . thunk ( snippet_function ) , ...args ) ) ) ;
1867+ if ( node . metadata . dynamic ) {
1868+ context . state . init . push (
1869+ b . stmt ( b . call ( '$.snippet' , context . state . node , b . thunk ( snippet_function ) , ...args ) )
1870+ ) ;
18501871 } else {
18511872 context . state . init . push (
18521873 b . stmt (
18531874 ( node . expression . type === 'CallExpression' ? b . call : b . maybe_call ) (
18541875 snippet_function ,
1876+ context . state . node ,
18551877 ...args
18561878 )
18571879 )
@@ -1914,7 +1936,7 @@ export const template_visitors = {
19141936 }
19151937
19161938 if ( node . name === 'noscript' ) {
1917- context . state . template . push ( '<! >' ) ;
1939+ context . state . template . push ( '<noscript></noscript >' ) ;
19181940 return ;
19191941 }
19201942 if ( node . name === 'script' ) {
@@ -3001,16 +3023,14 @@ export const template_visitors = {
30013023 }
30023024 } ,
30033025 Component ( node , context ) {
3004- const binding = context . state . scope . get (
3005- node . name . includes ( '.' ) ? node . name . slice ( 0 , node . name . indexOf ( '.' ) ) : node . name
3006- ) ;
3007- if ( binding !== null && binding . kind !== 'normal' ) {
3026+ if ( node . metadata . dynamic ) {
30083027 // Handle dynamic references to what seems like static inline components
30093028 const component = serialize_inline_component ( node , '$$component' , context ) ;
30103029 context . state . init . push (
30113030 b . stmt (
30123031 b . call (
30133032 '$.component' ,
3033+ context . state . node ,
30143034 // TODO use untrack here to not update when binding changes?
30153035 // Would align with Svelte 4 behavior, but it's arguably nicer/expected to update this
30163036 b . thunk (
@@ -3022,6 +3042,7 @@ export const template_visitors = {
30223042 ) ;
30233043 return ;
30243044 }
3045+
30253046 const component = serialize_inline_component ( node , node . name , context ) ;
30263047 context . state . init . push ( component ) ;
30273048 } ,
0 commit comments