Skip to content

Commit 4e727ed

Browse files
committed
handle invalid blocks
1 parent 72850e5 commit 4e727ed

File tree

5 files changed

+326
-13
lines changed

5 files changed

+326
-13
lines changed

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

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -279,34 +279,43 @@ function open(parser) {
279279
parser.require_whitespace();
280280

281281
const name_start = parser.index;
282-
const name = parser.read_identifier();
282+
let name = parser.read_identifier();
283283
const name_end = parser.index;
284284

285285
if (name === null) {
286-
e.expected_identifier(parser.index);
286+
if (parser.loose) {
287+
name = '';
288+
} else {
289+
e.expected_identifier(parser.index);
290+
}
287291
}
288292

289293
parser.allow_whitespace();
290294

291295
const params_start = parser.index;
292296

293-
parser.eat('(', true);
294-
let parentheses = 1;
297+
const matched = parser.eat('(', true, false);
295298

296-
while (parser.index < parser.template.length && (!parser.match(')') || parentheses !== 1)) {
297-
if (parser.match('(')) parentheses++;
298-
if (parser.match(')')) parentheses--;
299-
parser.index += 1;
300-
}
299+
if (matched) {
300+
let parentheses = 1;
301301

302-
parser.eat(')', true);
302+
while (parser.index < parser.template.length && (!parser.match(')') || parentheses !== 1)) {
303+
if (parser.match('(')) parentheses++;
304+
if (parser.match(')')) parentheses--;
305+
parser.index += 1;
306+
}
307+
308+
parser.eat(')', true);
309+
}
303310

304311
const prelude = parser.template.slice(0, params_start).replace(/\S/g, ' ');
305312
const params = parser.template.slice(params_start, parser.index);
306313

307-
let function_expression = /** @type {ArrowFunctionExpression} */ (
308-
parse_expression_at(prelude + `${params} => {}`, parser.ts, params_start)
309-
);
314+
let function_expression = matched
315+
? /** @type {ArrowFunctionExpression} */ (
316+
parse_expression_at(prelude + `${params} => {}`, parser.ts, params_start)
317+
)
318+
: { params: [] };
310319

311320
parser.allow_whitespace();
312321
parser.eat('}', true);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{#if }
2+
{:else if }
3+
{:else }
4+
{/if}
5+
6+
{#each }
7+
{/each}
8+
9+
{#snippet }
10+
{/snippet}
11+
12+
{#snippet foo}
13+
{/snippet}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{
2+
"html": {
3+
"type": "Fragment",
4+
"start": 0,
5+
"end": 102,
6+
"children": [
7+
{
8+
"type": "IfBlock",
9+
"start": 0,
10+
"end": 33,
11+
"expression": {
12+
"type": "Identifier",
13+
"start": 5,
14+
"end": 5,
15+
"name": ""
16+
},
17+
"children": [],
18+
"else": {
19+
"type": "ElseBlock",
20+
"start": 18,
21+
"end": 28,
22+
"children": [
23+
{
24+
"type": "IfBlock",
25+
"start": 18,
26+
"end": 33,
27+
"expression": {
28+
"type": "Identifier",
29+
"start": 17,
30+
"end": 17,
31+
"name": ""
32+
},
33+
"children": [],
34+
"else": {
35+
"type": "ElseBlock",
36+
"start": 27,
37+
"end": 28,
38+
"children": []
39+
},
40+
"elseif": true
41+
}
42+
]
43+
}
44+
},
45+
{
46+
"type": "Text",
47+
"start": 33,
48+
"end": 35,
49+
"raw": "\n\n",
50+
"data": "\n\n"
51+
},
52+
{
53+
"type": "EachBlock",
54+
"start": 35,
55+
"end": 51,
56+
"children": [],
57+
"context": null,
58+
"expression": {
59+
"type": "Identifier",
60+
"start": 42,
61+
"end": 42,
62+
"name": ""
63+
}
64+
},
65+
{
66+
"type": "Text",
67+
"start": 51,
68+
"end": 53,
69+
"raw": "\n\n",
70+
"data": "\n\n"
71+
},
72+
{
73+
"type": "SnippetBlock",
74+
"start": 53,
75+
"end": 75,
76+
"expression": {
77+
"type": "Identifier",
78+
"start": 63,
79+
"end": 63,
80+
"name": ""
81+
},
82+
"parameters": [],
83+
"children": []
84+
},
85+
{
86+
"type": "Text",
87+
"start": 75,
88+
"end": 77,
89+
"raw": "\n\n",
90+
"data": "\n\n"
91+
},
92+
{
93+
"type": "SnippetBlock",
94+
"start": 77,
95+
"end": 102,
96+
"expression": {
97+
"type": "Identifier",
98+
"start": 87,
99+
"end": 90,
100+
"name": "foo"
101+
},
102+
"parameters": [],
103+
"children": []
104+
}
105+
]
106+
}
107+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{#if }
2+
{:else if }
3+
{:else }
4+
{/if}
5+
6+
{#each }
7+
{/each}
8+
9+
{#snippet }
10+
{/snippet}
11+
12+
{#snippet foo}
13+
{/snippet}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
{
2+
"css": null,
3+
"js": [],
4+
"start": 0,
5+
"end": 102,
6+
"type": "Root",
7+
"fragment": {
8+
"type": "Fragment",
9+
"nodes": [
10+
{
11+
"type": "IfBlock",
12+
"elseif": false,
13+
"start": 0,
14+
"end": 33,
15+
"test": {
16+
"type": "Identifier",
17+
"start": 5,
18+
"end": 5,
19+
"name": ""
20+
},
21+
"consequent": {
22+
"type": "Fragment",
23+
"nodes": [
24+
{
25+
"type": "Text",
26+
"start": 6,
27+
"end": 7,
28+
"raw": "\n",
29+
"data": "\n"
30+
}
31+
]
32+
},
33+
"alternate": {
34+
"type": "Fragment",
35+
"nodes": [
36+
{
37+
"start": 7,
38+
"end": 33,
39+
"type": "IfBlock",
40+
"elseif": true,
41+
"test": {
42+
"type": "Identifier",
43+
"start": 17,
44+
"end": 17,
45+
"name": ""
46+
},
47+
"consequent": {
48+
"type": "Fragment",
49+
"nodes": [
50+
{
51+
"type": "Text",
52+
"start": 18,
53+
"end": 19,
54+
"raw": "\n",
55+
"data": "\n"
56+
}
57+
]
58+
},
59+
"alternate": {
60+
"type": "Fragment",
61+
"nodes": [
62+
{
63+
"type": "Text",
64+
"start": 27,
65+
"end": 28,
66+
"raw": "\n",
67+
"data": "\n"
68+
}
69+
]
70+
}
71+
}
72+
]
73+
}
74+
},
75+
{
76+
"type": "Text",
77+
"start": 33,
78+
"end": 35,
79+
"raw": "\n\n",
80+
"data": "\n\n"
81+
},
82+
{
83+
"type": "EachBlock",
84+
"start": 35,
85+
"end": 51,
86+
"expression": {
87+
"type": "Identifier",
88+
"start": 42,
89+
"end": 42,
90+
"name": ""
91+
},
92+
"body": {
93+
"type": "Fragment",
94+
"nodes": [
95+
{
96+
"type": "Text",
97+
"start": 43,
98+
"end": 44,
99+
"raw": "\n",
100+
"data": "\n"
101+
}
102+
]
103+
},
104+
"context": null
105+
},
106+
{
107+
"type": "Text",
108+
"start": 51,
109+
"end": 53,
110+
"raw": "\n\n",
111+
"data": "\n\n"
112+
},
113+
{
114+
"type": "SnippetBlock",
115+
"start": 53,
116+
"end": 75,
117+
"expression": {
118+
"type": "Identifier",
119+
"start": 63,
120+
"end": 63,
121+
"name": ""
122+
},
123+
"parameters": [],
124+
"body": {
125+
"type": "Fragment",
126+
"nodes": [
127+
{
128+
"type": "Text",
129+
"start": 64,
130+
"end": 65,
131+
"raw": "\n",
132+
"data": "\n"
133+
}
134+
]
135+
}
136+
},
137+
{
138+
"type": "Text",
139+
"start": 75,
140+
"end": 77,
141+
"raw": "\n\n",
142+
"data": "\n\n"
143+
},
144+
{
145+
"type": "SnippetBlock",
146+
"start": 77,
147+
"end": 102,
148+
"expression": {
149+
"type": "Identifier",
150+
"start": 87,
151+
"end": 90,
152+
"name": "foo"
153+
},
154+
"parameters": [],
155+
"body": {
156+
"type": "Fragment",
157+
"nodes": [
158+
{
159+
"type": "Text",
160+
"start": 91,
161+
"end": 92,
162+
"raw": "\n",
163+
"data": "\n"
164+
}
165+
]
166+
}
167+
}
168+
]
169+
},
170+
"options": null
171+
}

0 commit comments

Comments
 (0)