Skip to content

Commit

Permalink
better error message for mismatched tags due to autoclosing (#5060)
Browse files Browse the repository at this point in the history
  • Loading branch information
tanhauhau committed Jul 24, 2020
1 parent 40987b7 commit 3dad14f
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Prevent duplicate invalidation with certain two-way component bindings ([#3180](https://github.com/sveltejs/svelte/issues/3180), [#5117](https://github.com/sveltejs/svelte/issues/5117), [#5144](https://github.com/sveltejs/svelte/issues/5144))
* Fix reactivity when passing `$$props` to a `<slot>` ([#3364](https://github.com/sveltejs/svelte/issues/3364))
* Fix unneeded invalidation of `$$props` and `$$restProps` ([#4993](https://github.com/sveltejs/svelte/issues/4993), [#5118](https://github.com/sveltejs/svelte/issues/5118))
* Provide better compiler error message when mismatched tags are due to autoclosing of tags ([#5049](https://github.com/sveltejs/svelte/issues/5049))

## 3.24.0

Expand Down
7 changes: 7 additions & 0 deletions src/compiler/parse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import error from '../utils/error';

type ParserState = (parser: Parser) => (ParserState | void);

interface LastAutoClosedTag {
tag: string;
reason: string;
depth: number;
}

export class Parser {
readonly template: string;
readonly filename?: string;
Expand All @@ -20,6 +26,7 @@ export class Parser {
css: Style[] = [];
js: Script[] = [];
meta_tags = {};
last_auto_closed_tag?: LastAutoClosedTag;

constructor(template: string, options: ParserOptions) {
if (typeof template !== 'string') {
Expand Down
17 changes: 15 additions & 2 deletions src/compiler/parse/state/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,15 @@ export default function tag(parser: Parser) {

// close any elements that don't have their own closing tags, e.g. <div><p></div>
while (parent.name !== name) {
if (parent.type !== 'Element')
if (parent.type !== 'Element') {
const message = parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name
? `</${name}> attempted to close <${name}> that was already automatically closed by <${parser.last_auto_closed_tag.reason}>`
: `</${name}> attempted to close an element that was not open`;
parser.error({
code: `invalid-closing-tag`,
message: `</${name}> attempted to close an element that was not open`
message
}, start);
}

parent.end = start;
parser.stack.pop();
Expand All @@ -148,10 +152,19 @@ export default function tag(parser: Parser) {
parent.end = parser.index;
parser.stack.pop();

if (parser.last_auto_closed_tag && parser.stack.length < parser.last_auto_closed_tag.depth) {
parser.last_auto_closed_tag = null;
}

return;
} else if (closing_tag_omitted(parent.name, name)) {
parent.end = start;
parser.stack.pop();
parser.last_auto_closed_tag = {
tag: parent.name,
reason: name,
depth: parser.stack.length,
};
}

const unique_names: Set<string> = new Set();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"code": "invalid-closing-tag",
"message": "</p> attempted to close an element that was not open",
"pos": 38,
"start": {
"character": 38,
"column": 0,
"line": 5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div>
<p>
<pre>pre tag</pre>
</div>
</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"code": "invalid-closing-tag",
"message": "</p> attempted to close <p> that was already automatically closed by <pre>",
"pos": 24,
"start": {
"character": 24,
"column": 0,
"line": 3
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>
<pre>pre tag</pre>
</p>

0 comments on commit 3dad14f

Please sign in to comment.