Skip to content

Commit

Permalink
complain if named slots other than direct descendant of component (sv…
Browse files Browse the repository at this point in the history
  • Loading branch information
tanhauhau authored and taylorzane committed Dec 17, 2020
1 parent e50b5d8 commit 4dacf22
Show file tree
Hide file tree
Showing 18 changed files with 98 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* Allow `<svelte:self>` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798))
* Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930))
* Prevent passing named slots other than from the top level within a component ([#3385](https://github.com/sveltejs/svelte/issues/3385))
* Allow transitions and animations to work within iframes ([#3624](https://github.com/sveltejs/svelte/issues/3624))
* Fix initialising slot fallbacks when unnecessary ([#3763](https://github.com/sveltejs/svelte/issues/3763))
* Disallow binding directly to `const` variables ([#4479](https://github.com/sveltejs/svelte/issues/4479))
Expand Down
31 changes: 12 additions & 19 deletions src/compiler/compile/nodes/Element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export default class Element extends Node {
}

validate_attributes() {
const { component } = this;
const { component, parent } = this;

const attribute_map = new Map();

Expand Down Expand Up @@ -395,26 +395,10 @@ export default class Element extends Node {
component.slot_outlets.add(name);
}

let ancestor = this.parent;
do {
if (ancestor.type === 'InlineComponent') break;
if (ancestor.type === 'Element' && /-/.test(ancestor.name)) break;

if (ancestor.type === 'IfBlock' || ancestor.type === 'EachBlock') {
const type = ancestor.type === 'IfBlock' ? 'if' : 'each';
const message = `Cannot place slotted elements inside an ${type}-block`;

component.error(attribute, {
code: `invalid-slotted-content`,
message
});
}
} while (ancestor = ancestor.parent);

if (!ancestor) {
if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) {
component.error(attribute, {
code: `invalid-slotted-content`,
message: `Element with a slot='...' attribute must be a descendant of a component or custom element`
message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`,
});
}
}
Expand Down Expand Up @@ -776,3 +760,12 @@ function should_have_attribute(
message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
});
}

function within_custom_element(parent: INode) {
while (parent) {
if (parent.type === 'InlineComponent') return false;
if (parent.type === 'Element' && /-/.test(parent.name)) return true;
parent = parent.parent;
}
return false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<slot name="slot2"></slot>
3 changes: 3 additions & 0 deletions test/runtime/samples/component-slot-nested-error-2/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`]
};
11 changes: 11 additions & 0 deletions test/runtime/samples/component-slot-nested-error-2/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script>
import Nested from "./Nested.svelte";
</script>

<Nested>
<div slot="slot1">
<div>
<div slot="slot2" />
</div>
</div>
</Nested>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<slot name="slot2"></slot>
3 changes: 3 additions & 0 deletions test/runtime/samples/component-slot-nested-error-3/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`]
};
11 changes: 11 additions & 0 deletions test/runtime/samples/component-slot-nested-error-3/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script>
import Nested from "./Nested.svelte";
</script>

<Nested>
<div>
<div>
<div slot="slot2" />
</div>
</div>
</Nested>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<slot name="slot2"></slot>
3 changes: 3 additions & 0 deletions test/runtime/samples/component-slot-nested-error/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`]
};
9 changes: 9 additions & 0 deletions test/runtime/samples/component-slot-nested-error/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script>
import Nested from "./Nested.svelte";
</script>

<Nested>
<div slot="slot1">
<div slot="slot2" />
</div>
</Nested>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"code": "invalid-slotted-content",
"message": "Element with a slot='...' attribute must be a child of a component or a descendant of a custom element",
"start": { "line": 10, "column": 9, "character": 138 },
"end": { "line": 10, "column": 19, "character": 148 },
"pos": 138
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script>
import Nested from './Nested.svelte';
let thing = false;
</script>

<custom-element>
<Nested>
{#if thing}
<div>
<div slot='bar' />
</div>
{/if}
</Nested>
</custom-element>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script>
import Nested from './Nested.svelte';
let thing = false;
</script>

<Nested>
<custom-element>
<div>
<div slot='foo' />
</div>
{#if thing}
<div slot='bar' />
{/if}
</custom-element>
</Nested>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[{
"code": "invalid-slotted-content",
"message": "Cannot place slotted elements inside an each-block",
"message": "Element with a slot='...' attribute must be a child of a component or a descendant of a custom element",
"start": {
"line": 7,
"column": 7,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[{
"code": "invalid-slotted-content",
"message": "Cannot place slotted elements inside an if-block",
"message": "Element with a slot='...' attribute must be a child of a component or a descendant of a custom element",
"start": {
"line": 7,
"column": 7,
Expand Down
2 changes: 1 addition & 1 deletion test/validator/samples/slot-attribute-invalid/errors.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[{
"code": "invalid-slotted-content",
"message": "Element with a slot='...' attribute must be a descendant of a component or custom element",
"message": "Element with a slot='...' attribute must be a child of a component or a descendant of a custom element",
"start": {
"line": 1,
"column": 5,
Expand Down

0 comments on commit 4dacf22

Please sign in to comment.