Skip to content

Commit 3fd02f1

Browse files
authored
breaking: preserve slots inside templates with a shadowrootmode attribute (#10721)
closes #10641
1 parent cc22492 commit 3fd02f1

File tree

4 files changed

+191
-1
lines changed

4 files changed

+191
-1
lines changed

.changeset/eleven-cycles-applaud.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
breaking: preserve slots inside templates with a shadowrootmode attribute

packages/svelte/src/compiler/phases/1-parse/state/element.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ function parent_is_head(stack) {
5151
return false;
5252
}
5353

54+
/** @param {import('#compiler').TemplateNode[]} stack */
55+
function parent_is_shadowroot_template(stack) {
56+
// https://developer.chrome.com/docs/css-ui/declarative-shadow-dom#building_a_declarative_shadow_root
57+
let i = stack.length;
58+
while (i--) {
59+
if (
60+
stack[i].type === 'RegularElement' &&
61+
/** @type {import('#compiler').RegularElement} */ (stack[i]).attributes.some(
62+
(a) => a.type === 'Attribute' && a.name === 'shadowrootmode'
63+
)
64+
) {
65+
return true;
66+
}
67+
}
68+
return false;
69+
}
70+
5471
const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i;
5572
const regex_closing_comment = /-->/;
5673
const regex_capital_letter = /[A-Z]/;
@@ -112,7 +129,8 @@ export default function tag(parser) {
112129
? 'Component'
113130
: name === 'title' && parent_is_head(parser.stack)
114131
? 'TitleElement'
115-
: name === 'slot'
132+
: // TODO Svelte 6/7: once slots are removed in favor of snippets, always keep slot as a regular element
133+
name === 'slot' && !parent_is_shadowroot_template(parser.stack)
116134
? 'SlotElement'
117135
: 'RegularElement';
118136

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<template shadowrootmode="open">
2+
<p><slot></slot></p>
3+
</template>
4+
<template>
5+
<p><slot></slot></p>
6+
</template>
7+
<slot></slot>
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
{
2+
"css": null,
3+
"js": [],
4+
"start": 0,
5+
"end": 125,
6+
"type": "Root",
7+
"fragment": {
8+
"type": "Fragment",
9+
"nodes": [
10+
{
11+
"type": "RegularElement",
12+
"start": 0,
13+
"end": 66,
14+
"name": "template",
15+
"attributes": [
16+
{
17+
"type": "Attribute",
18+
"start": 10,
19+
"end": 31,
20+
"name": "shadowrootmode",
21+
"value": [
22+
{
23+
"start": 26,
24+
"end": 30,
25+
"type": "Text",
26+
"raw": "open",
27+
"data": "open"
28+
}
29+
]
30+
}
31+
],
32+
"fragment": {
33+
"type": "Fragment",
34+
"nodes": [
35+
{
36+
"type": "Text",
37+
"start": 32,
38+
"end": 34,
39+
"raw": "\n\t",
40+
"data": "\n\t"
41+
},
42+
{
43+
"type": "RegularElement",
44+
"start": 34,
45+
"end": 54,
46+
"name": "p",
47+
"attributes": [],
48+
"fragment": {
49+
"type": "Fragment",
50+
"nodes": [
51+
{
52+
"type": "RegularElement",
53+
"start": 37,
54+
"end": 50,
55+
"name": "slot",
56+
"attributes": [],
57+
"fragment": {
58+
"type": "Fragment",
59+
"nodes": [],
60+
"transparent": true
61+
}
62+
}
63+
],
64+
"transparent": true
65+
}
66+
},
67+
{
68+
"type": "Text",
69+
"start": 54,
70+
"end": 55,
71+
"raw": "\n",
72+
"data": "\n"
73+
}
74+
],
75+
"transparent": true
76+
}
77+
},
78+
{
79+
"type": "Text",
80+
"start": 66,
81+
"end": 67,
82+
"raw": "\n",
83+
"data": "\n"
84+
},
85+
{
86+
"type": "RegularElement",
87+
"start": 67,
88+
"end": 111,
89+
"name": "template",
90+
"attributes": [],
91+
"fragment": {
92+
"type": "Fragment",
93+
"nodes": [
94+
{
95+
"type": "Text",
96+
"start": 77,
97+
"end": 79,
98+
"raw": "\n\t",
99+
"data": "\n\t"
100+
},
101+
{
102+
"type": "RegularElement",
103+
"start": 79,
104+
"end": 99,
105+
"name": "p",
106+
"attributes": [],
107+
"fragment": {
108+
"type": "Fragment",
109+
"nodes": [
110+
{
111+
"type": "SlotElement",
112+
"start": 82,
113+
"end": 95,
114+
"name": "slot",
115+
"attributes": [],
116+
"fragment": {
117+
"type": "Fragment",
118+
"nodes": [],
119+
"transparent": true
120+
}
121+
}
122+
],
123+
"transparent": true
124+
}
125+
},
126+
{
127+
"type": "Text",
128+
"start": 99,
129+
"end": 100,
130+
"raw": "\n",
131+
"data": "\n"
132+
}
133+
],
134+
"transparent": true
135+
}
136+
},
137+
{
138+
"type": "Text",
139+
"start": 111,
140+
"end": 112,
141+
"raw": "\n",
142+
"data": "\n"
143+
},
144+
{
145+
"type": "SlotElement",
146+
"start": 112,
147+
"end": 125,
148+
"name": "slot",
149+
"attributes": [],
150+
"fragment": {
151+
"type": "Fragment",
152+
"nodes": [],
153+
"transparent": true
154+
}
155+
}
156+
],
157+
"transparent": false
158+
},
159+
"options": null
160+
}

0 commit comments

Comments
 (0)