Skip to content

Commit 5bb5ba4

Browse files
authored
complain if named slots other than direct descendant of component (#4509)
1 parent 82dce0c commit 5bb5ba4

18 files changed

Lines changed: 98 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* Allow `<svelte:self>` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798))
66
* Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930))
7+
* Prevent passing named slots other than from the top level within a component ([#3385](https://github.com/sveltejs/svelte/issues/3385))
78
* Allow transitions and animations to work within iframes ([#3624](https://github.com/sveltejs/svelte/issues/3624))
89
* Fix initialising slot fallbacks when unnecessary ([#3763](https://github.com/sveltejs/svelte/issues/3763))
910
* Disallow binding directly to `const` variables ([#4479](https://github.com/sveltejs/svelte/issues/4479))

src/compiler/compile/nodes/Element.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ export default class Element extends Node {
278278
}
279279

280280
validate_attributes() {
281-
const { component } = this;
281+
const { component, parent } = this;
282282

283283
const attribute_map = new Map();
284284

@@ -395,26 +395,10 @@ export default class Element extends Node {
395395
component.slot_outlets.add(name);
396396
}
397397

398-
let ancestor = this.parent;
399-
do {
400-
if (ancestor.type === 'InlineComponent') break;
401-
if (ancestor.type === 'Element' && /-/.test(ancestor.name)) break;
402-
403-
if (ancestor.type === 'IfBlock' || ancestor.type === 'EachBlock') {
404-
const type = ancestor.type === 'IfBlock' ? 'if' : 'each';
405-
const message = `Cannot place slotted elements inside an ${type}-block`;
406-
407-
component.error(attribute, {
408-
code: `invalid-slotted-content`,
409-
message
410-
});
411-
}
412-
} while (ancestor = ancestor.parent);
413-
414-
if (!ancestor) {
398+
if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
415399
component.error(attribute, {
416400
code: `invalid-slotted-content`,
417-
message: `Element with a slot='...' attribute must be a descendant of a component or custom element`
401+
message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`,
418402
});
419403
}
420404
}
@@ -776,3 +760,12 @@ function should_have_attribute(
776760
message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
777761
});
778762
}
763+
764+
function within_custom_element(parent: INode) {
765+
while (parent) {
766+
if (parent.type === 'InlineComponent') return false;
767+
if (parent.type === 'Element' && /-/.test(parent.name)) return true;
768+
parent = parent.parent;
769+
}
770+
return false;
771+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<slot name="slot2"></slot>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`]
3+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
import Nested from "./Nested.svelte";
3+
</script>
4+
5+
<Nested>
6+
<div slot="slot1">
7+
<div>
8+
<div slot="slot2" />
9+
</div>
10+
</div>
11+
</Nested>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<slot name="slot2"></slot>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`]
3+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
import Nested from "./Nested.svelte";
3+
</script>
4+
5+
<Nested>
6+
<div>
7+
<div>
8+
<div slot="slot2" />
9+
</div>
10+
</div>
11+
</Nested>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<slot name="slot2"></slot>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`]
3+
};

0 commit comments

Comments
 (0)