Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/compiler/parse/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ export default {
code: 'missing-component-definition',
message: '<svelte:component> must have a \'this\' attribute'
},
missing_attribute_value: {
code: 'missing-attribute-value',
message: 'Expected value for the attribute'
},
unclosed_script: {
code: 'unclosed-script',
message: '<script> must have a closing tag'
Expand All @@ -169,6 +173,10 @@ export default {
code: 'unclosed-comment',
message: 'comment was left open, expected -->'
},
unclosed_attribute_value: (token: string) => ({
code: 'unclosed-attribute-value',
message: `Expected to close the attribute value with ${token}`
}),
unexpected_block_close: {
code: 'unexpected-block-close',
message: 'Unexpected block closing tag'
Expand Down
20 changes: 19 additions & 1 deletion src/compiler/parse/state/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,25 @@ function read_attribute_value(parser: Parser) {
/(\/>|[\s"'=<>`])/
);

const value = read_sequence(parser, () => !!parser.match_regex(regex));
let value;
try {
value = read_sequence(parser, () => !!parser.match_regex(regex));
} catch (error) {
if (error.code === 'parse-error') {
// if the attribute value didn't close + self-closing tag
// eg: `<Component test={{a:1} />`
// acorn may throw a `Unterminated regular expression` because of `/>`
if (parser.template.slice(error.pos - 1, error.pos + 1) === '/>') {
parser.index = error.pos;
parser.error(parser_errors.unclosed_attribute_value(quote_mark || '}'));
}
}
throw error;
}

if (value.length === 0 && !quote_mark) {
parser.error(parser_errors.missing_attribute_value);
}

if (quote_mark) parser.index += 1;
return value;
Expand Down
10 changes: 10 additions & 0 deletions test/parser/samples/attribute-empty-error/error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"code": "missing-attribute-value",
"message": "Expected value for the attribute",
"pos": 12,
"start": {
"character": 12,
"column": 12,
"line": 1
}
}
1 change: 1 addition & 0 deletions test/parser/samples/attribute-empty-error/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class= ></div>
1 change: 1 addition & 0 deletions test/parser/samples/attribute-empty/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div a="" b={''} c='' d="{''}" ></div>
108 changes: 108 additions & 0 deletions test/parser/samples/attribute-empty/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{
"html": {
"start": 0,
"end": 38,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 38,
"type": "Element",
"name": "div",
"attributes": [
{
"start": 5,
"end": 9,
"type": "Attribute",
"name": "a",
"value": [
{
"start": 8,
"end": 8,
"type": "Text",
"raw": "",
"data": ""
}
]
},
{
"start": 10,
"end": 16,
"type": "Attribute",
"name": "b",
"value": [
{
"start": 12,
"end": 16,
"type": "MustacheTag",
"expression": {
"type": "Literal",
"start": 13,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 15
}
},
"value": "",
"raw": "''"
}
}
]
},
{
"start": 17,
"end": 21,
"type": "Attribute",
"name": "c",
"value": [
{
"start": 20,
"end": 20,
"type": "Text",
"raw": "",
"data": ""
}
]
},
{
"start": 22,
"end": 30,
"type": "Attribute",
"name": "d",
"value": [
{
"start": 25,
"end": 29,
"type": "MustacheTag",
"expression": {
"type": "Literal",
"start": 26,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 26
},
"end": {
"line": 1,
"column": 28
}
},
"value": "",
"raw": "''"
}
}
]
}
],
"children": []
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"code": "unclosed-attribute-value",
"message": "Expected to close the attribute value with }",
"pos": 25,
"start": {
"character": 25,
"column": 25,
"line": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<Component test={{a: 1} />