Skip to content

Commit 9138dcf

Browse files
committed
fix scoping
1 parent 3f899c5 commit 9138dcf

File tree

1 file changed

+33
-25
lines changed
  • packages/svelte/src/compiler/phases

1 file changed

+33
-25
lines changed

packages/svelte/src/compiler/phases/scope.js

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)