From 7c9fe3ef57001a4a03c88997ce30ffcbe06dd87d Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Sat, 22 Jun 2024 22:45:23 +0200 Subject: [PATCH 1/3] fix: throw compilation error for malformed snippets --- .changeset/polite-ways-serve.md | 5 +++++ .../svelte/src/compiler/phases/1-parse/state/tag.js | 10 +++++++--- .../samples/malformed-snippet-2/_config.js | 9 +++++++++ .../samples/malformed-snippet-2/main.svelte | 1 + .../samples/malformed-snippet/_config.js | 9 +++++++++ .../samples/malformed-snippet/main.svelte | 1 + 6 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 .changeset/polite-ways-serve.md create mode 100644 packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/main.svelte create mode 100644 packages/svelte/tests/compiler-errors/samples/malformed-snippet/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/malformed-snippet/main.svelte diff --git a/.changeset/polite-ways-serve.md b/.changeset/polite-ways-serve.md new file mode 100644 index 000000000000..fe25761069fb --- /dev/null +++ b/.changeset/polite-ways-serve.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: throw compilation error for malformed snippets diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index 85fde1d4869c..2aa0dfd30a44 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -279,9 +279,15 @@ function open(parser) { while (!parser.match(')') || parentheses !== 1) { if (parser.match('(')) parentheses++; if (parser.match(')')) parentheses--; - params += parser.read(/^./); + + var next_char = parser.read(/^./); + if (next_char == null) break; // end of template + params += next_char; } + parser.eat(')', true); + parser.eat('}', true); + let function_expression = /** @type {import('estree').ArrowFunctionExpression} */ ( parse_expression_at( parser.template.slice(0, slice_end).replace(/\S/g, ' ') + `(${params}) => {}`, @@ -290,8 +296,6 @@ function open(parser) { ) ); - parser.index += 2; - /** @type {ReturnType>} */ const block = parser.append({ type: 'SnippetBlock', diff --git a/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/_config.js b/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/_config.js new file mode 100644 index 000000000000..73154e897185 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'expected_token', + message: 'Expected token )', + position: [31, 31] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/main.svelte b/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/main.svelte new file mode 100644 index 000000000000..2cde495cb4da --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/main.svelte @@ -0,0 +1 @@ +{#snippet children(hi{/snippet} diff --git a/packages/svelte/tests/compiler-errors/samples/malformed-snippet/_config.js b/packages/svelte/tests/compiler-errors/samples/malformed-snippet/_config.js new file mode 100644 index 000000000000..393d1542d42c --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/malformed-snippet/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'expected_token', + message: 'Expected token }', + position: [20, 20] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/malformed-snippet/main.svelte b/packages/svelte/tests/compiler-errors/samples/malformed-snippet/main.svelte new file mode 100644 index 000000000000..3ac8f31f1404 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/malformed-snippet/main.svelte @@ -0,0 +1 @@ +{#snippet children()hi{/snippet} From 096ba769e86f91343f76576f5c96e7346687e72f Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Sat, 22 Jun 2024 23:20:10 +0200 Subject: [PATCH 2/3] fix: support multiline --- packages/svelte/src/compiler/phases/1-parse/state/tag.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index 2aa0dfd30a44..f655ce94854d 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -280,7 +280,7 @@ function open(parser) { if (parser.match('(')) parentheses++; if (parser.match(')')) parentheses--; - var next_char = parser.read(/^./); + var next_char = parser.read(/^(.|[\r\n])/); if (next_char == null) break; // end of template params += next_char; } From 9fab9c6544ba2cd4e81beb061516468f035a9a3c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 23 Jun 2024 12:05:01 -0400 Subject: [PATCH 3/3] tweak --- .../src/compiler/phases/1-parse/state/tag.js | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index f655ce94854d..762dab69bbbb 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -269,33 +269,28 @@ function open(parser) { e.expected_identifier(parser.index); } - let slice_end = parser.index; + const params_start = parser.index; parser.eat('(', true); - let parentheses = 1; - let params = ''; - while (!parser.match(')') || parentheses !== 1) { + while (parser.index < parser.template.length && (!parser.match(')') || parentheses !== 1)) { if (parser.match('(')) parentheses++; if (parser.match(')')) parentheses--; - - var next_char = parser.read(/^(.|[\r\n])/); - if (next_char == null) break; // end of template - params += next_char; + parser.index += 1; } parser.eat(')', true); - parser.eat('}', true); + + const prelude = parser.template.slice(0, params_start).replace(/\S/g, ' '); + const params = parser.template.slice(params_start, parser.index); let function_expression = /** @type {import('estree').ArrowFunctionExpression} */ ( - parse_expression_at( - parser.template.slice(0, slice_end).replace(/\S/g, ' ') + `(${params}) => {}`, - parser.ts, - 0 - ) + parse_expression_at(prelude + `${params} => {}`, parser.ts, params_start) ); + parser.eat('}', true); + /** @type {ReturnType>} */ const block = parser.append({ type: 'SnippetBlock',