@@ -282,7 +282,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
282282 * @type {import('zimmerframe').Visitor<import('#compiler').ElementLike, State, import('#compiler').SvelteNode> }
283283 */
284284 const SvelteFragment = ( node , { state, next } ) => {
285- const scope = analyze_let_directives ( node , state . scope ) ;
285+ const [ scope ] = analyze_let_directives ( node , state . scope ) ;
286286 scopes . set ( node , scope ) ;
287287 next ( { scope } ) ;
288288 } ;
@@ -293,36 +293,40 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
293293 */
294294 function analyze_let_directives ( node , parent ) {
295295 const scope = parent . child ( ) ;
296+ let is_default_slot = true ;
296297
297298 for ( const attribute of node . attributes ) {
298- if ( attribute . type !== 'LetDirective' ) continue ;
299-
300- /** @type {import('#compiler').Binding[] } */
301- const bindings = [ ] ;
302- scope . declarators . set ( attribute , bindings ) ;
299+ if ( attribute . type === 'LetDirective' ) {
300+ /** @type {import('#compiler').Binding[] } */
301+ const bindings = [ ] ;
302+ scope . declarators . set ( attribute , bindings ) ;
303303
304- // attach the scope to the directive itself, as well as the
305- // contents to which it applies
306- scopes . set ( attribute , scope ) ;
304+ // attach the scope to the directive itself, as well as the
305+ // contents to which it applies
306+ scopes . set ( attribute , scope ) ;
307307
308- if ( attribute . expression ) {
309- for ( const id of extract_identifiers_from_destructuring ( attribute . expression ) ) {
308+ if ( attribute . expression ) {
309+ for ( const id of extract_identifiers_from_destructuring ( attribute . expression ) ) {
310+ const binding = scope . declare ( id , 'derived' , 'const' ) ;
311+ bindings . push ( binding ) ;
312+ }
313+ } else {
314+ /** @type {import('estree').Identifier } */
315+ const id = {
316+ name : attribute . name ,
317+ type : 'Identifier' ,
318+ start : attribute . start ,
319+ end : attribute . end
320+ } ;
310321 const binding = scope . declare ( id , 'derived' , 'const' ) ;
311322 bindings . push ( binding ) ;
312323 }
313- } else {
314- /** @type {import('estree').Identifier } */
315- const id = {
316- name : attribute . name ,
317- type : 'Identifier' ,
318- start : attribute . start ,
319- end : attribute . end
320- } ;
321- const binding = scope . declare ( id , 'derived' , 'const' ) ;
322- bindings . push ( binding ) ;
324+ } else if ( attribute . type === 'Attribute' && attribute . name === 'slot' ) {
325+ is_default_slot = false ;
323326 }
324327 }
325- return scope ;
328+
329+ return /** @type {const } */ ( [ scope , is_default_slot ] ) ;
326330 }
327331
328332 walk ( ast , state , {
@@ -364,13 +368,17 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
364368 Component ( node , { state, visit, path } ) {
365369 state . scope . reference ( b . id ( node . name ) , path ) ;
366370
367- // let:x from the default slot is a weird one:
368- // Its scope only applies to children that are not slots themselves.
369371 for ( const attribute of node . attributes ) {
370372 visit ( attribute ) ;
371373 }
372374
373- const scope = analyze_let_directives ( node , state . scope ) ;
375+ // let:x is super weird:
376+ // - for the default slot, its scope only applies to children that are not slots themselves
377+ // - for named slots, its scope applies to the component itself, too
378+ const [ scope , is_default_slot ] = analyze_let_directives ( node , state . scope ) ;
379+ if ( ! is_default_slot ) {
380+ scopes . set ( node , scope ) ;
381+ }
374382
375383 for ( const child of node . fragment . nodes ) {
376384 if (
0 commit comments