Skip to content

Commit

Permalink
[fix] script style end parsing (#6511)
Browse files Browse the repository at this point in the history
* update script end tag parsing to allow whitespace after tagname

* update style end tag parsing to allow for whitespace after tag name

* handle no closing match for script and style for eof and non-eof failures

* cleaning up script and style end tag parsing

Co-authored-by: pngwn <[email protected]>
  • Loading branch information
tanhauhau and pngwn authored Jul 12, 2021
1 parent 9990328 commit 6a582af
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/compiler/parse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ export class Parser {
return identifier;
}

read_until(pattern: RegExp) {
read_until(pattern: RegExp, error_message?: Parameters<Parser['error']>[0]) {
if (this.index >= this.template.length) {
this.error({
this.error(error_message || {
code: 'unexpected-eof',
message: 'Unexpected end of input'
});
Expand Down
21 changes: 9 additions & 12 deletions src/compiler/parse/read/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { Parser } from '../index';
import { Script } from '../../interfaces';
import { Node, Program } from 'estree';

const script_closing_tag = '</script>';

function get_context(parser: Parser, attributes: any[], start: number): string {
const context = attributes.find(attribute => attribute.name === 'context');
if (!context) return 'default';
Expand All @@ -30,18 +28,17 @@ function get_context(parser: Parser, attributes: any[], start: number): string {

export default function read_script(parser: Parser, start: number, attributes: Node[]): Script {
const script_start = parser.index;
const script_end = parser.template.indexOf(script_closing_tag, script_start);

if (script_end === -1) {
parser.error({
code: 'unclosed-script',
message: '<script> must have a closing tag'
});
const error_message = {
code: 'unclosed-script',
message: '<script> must have a closing tag'
};
const data = parser.read_until(/<\/script\s*>/, error_message);
if (parser.index >= parser.template.length) {
parser.error(error_message);
}

const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') +
parser.template.slice(script_start, script_end);
parser.index = script_end + script_closing_tag.length;
const source = parser.template.slice(0, script_start).replace(/[^\n]/g, ' ') + data;
parser.read(/<\/script\s*>/);

let ast: Program;

Expand Down
14 changes: 12 additions & 2 deletions src/compiler/parse/read/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ import { Style } from '../../interfaces';

export default function read_style(parser: Parser, start: number, attributes: Node[]): Style {
const content_start = parser.index;
const styles = parser.read_until(/<\/style>/);
const error_message = {
code: 'unclosed-style',
message: '<style> must have a closing tag'
};

const styles = parser.read_until(/<\/style\s*>/, error_message);

if (parser.index >= parser.template.length) {
parser.error(error_message);
}

const content_end = parser.index;

let ast;
Expand Down Expand Up @@ -72,7 +82,7 @@ export default function read_style(parser: Parser, start: number, attributes: No
}
});

parser.eat('</style>', true);
parser.read(/<\/style\s*>/);
const end = parser.index;

return {
Expand Down
10 changes: 10 additions & 0 deletions test/parser/samples/error-script-unclosed-eof/error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"code": "unclosed-script",
"message": "<script> must have a closing tag",
"start": {
"line": 3,
"column": 22,
"character": 32
},
"pos": 32
}
3 changes: 3 additions & 0 deletions test/parser/samples/error-script-unclosed-eof/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<script>
<h1>Hello {name}!</h1>
10 changes: 10 additions & 0 deletions test/parser/samples/error-style-unclosed-eof/error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"code": "unclosed-style",
"message": "<style> must have a closing tag",
"start": {
"line": 3,
"column": 22,
"character": 31
},
"pos": 31
}
3 changes: 3 additions & 0 deletions test/parser/samples/error-style-unclosed-eof/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<style>
<h1>Hello {name}!</h1>
10 changes: 10 additions & 0 deletions test/parser/samples/error-style-unclosed/error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"code": "unclosed-style",
"message": "<style> must have a closing tag",
"start": {
"line": 3,
"column": 7,
"character": 31
},
"pos": 31
}
3 changes: 3 additions & 0 deletions test/parser/samples/error-style-unclosed/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1>Hello {name}!</h1>

<style>
10 changes: 10 additions & 0 deletions test/parser/samples/whitespace-after-script-tag/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script>
let name = 'world';
</script
>
<h1>Hello {name}!</h1>
150 changes: 150 additions & 0 deletions test/parser/samples/whitespace-after-script-tag/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"html": {
"start": 51,
"end": 73,
"type": "Fragment",
"children": [
{
"start": 49,
"end": 51,
"type": "Text",
"raw": "\n\n",
"data": "\n\n"
},
{
"start": 51,
"end": 73,
"type": "Element",
"name": "h1",
"attributes": [],
"children": [
{
"start": 55,
"end": 61,
"type": "Text",
"raw": "Hello ",
"data": "Hello "
},
{
"start": 61,
"end": 67,
"type": "MustacheTag",
"expression": {
"type": "Identifier",
"start": 62,
"end": 66,
"loc": {
"start": {
"line": 10,
"column": 11
},
"end": {
"line": 10,
"column": 15
}
},
"name": "name"
}
},
{
"start": 67,
"end": 68,
"type": "Text",
"raw": "!",
"data": "!"
}
]
}
]
},
"instance": {
"type": "Script",
"start": 0,
"end": 49,
"context": "default",
"content": {
"type": "Program",
"start": 8,
"end": 30,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 0
}
},
"body": [
{
"type": "VariableDeclaration",
"start": 10,
"end": 29,
"loc": {
"start": {
"line": 2,
"column": 1
},
"end": {
"line": 2,
"column": 20
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 14,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 19
}
},
"id": {
"type": "Identifier",
"start": 14,
"end": 18,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 9
}
},
"name": "name"
},
"init": {
"type": "Literal",
"start": 21,
"end": 28,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 19
}
},
"value": "world",
"raw": "'world'"
}
}
],
"kind": "let"
}
],
"sourceType": "module"
}
}
}
12 changes: 12 additions & 0 deletions test/parser/samples/whitespace-after-style-tag/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<div>foo</div>

<style>
div {
color: red;
}
</style
>
Loading

0 comments on commit 6a582af

Please sign in to comment.