From bbde0799959a44a836615ae793c97bf7c48bd98e Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Sun, 28 Apr 2024 14:54:47 +0200 Subject: [PATCH 1/2] fix: disallow sequence expressions in `@const` tags closes #11349 --- .changeset/orange-masks-exercise.md | 5 +++++ packages/svelte/messages/compile-errors/template.md | 2 +- packages/svelte/src/compiler/errors.js | 2 +- packages/svelte/src/compiler/phases/1-parse/state/tag.js | 3 +++ .../compiler-errors/samples/const-tag-sequence/_config.js | 8 ++++++++ .../samples/const-tag-sequence/main.svelte | 3 +++ 6 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 .changeset/orange-masks-exercise.md create mode 100644 packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte diff --git a/.changeset/orange-masks-exercise.md b/.changeset/orange-masks-exercise.md new file mode 100644 index 000000000000..76fdc4aab815 --- /dev/null +++ b/.changeset/orange-masks-exercise.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: disallow sequence expressions in `@const` tags diff --git a/packages/svelte/messages/compile-errors/template.md b/packages/svelte/messages/compile-errors/template.md index c1b8c5f3c3be..d9365a51fbac 100644 --- a/packages/svelte/messages/compile-errors/template.md +++ b/packages/svelte/messages/compile-errors/template.md @@ -94,7 +94,7 @@ ## const_tag_invalid_expression -> {@const ...} must be an assignment +> {@const ...} must consist of a single variable declaration ## const_tag_invalid_placement diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index a00a2cd593b6..f071cbe6fd05 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -734,7 +734,7 @@ export function component_invalid_directive(node) { * @returns {never} */ export function const_tag_invalid_expression(node) { - e(node, "const_tag_invalid_expression", "{@const ...} must be an assignment"); + e(node, "const_tag_invalid_expression", "{@const ...} must consist of a single variable declaration"); } /** 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 bf6adccccfcf..86e713b522a0 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -552,6 +552,9 @@ function special(parser) { parser.allow_whitespace(); const init = read_expression(parser); + if (init.type === 'SequenceExpression') { + e.const_tag_invalid_expression(init); + } parser.allow_whitespace(); parser.eat('}', true); diff --git a/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js new file mode 100644 index 000000000000..eac1302fdc2f --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js @@ -0,0 +1,8 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'const_tag_invalid_expression', + message: '{@const ...} must consist of a single variable declaration' + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte new file mode 100644 index 000000000000..5d66ea33eb92 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte @@ -0,0 +1,3 @@ +{#if true} + {@const foo = 'foo', bar = 'bar'} +{/if} \ No newline at end of file From 4eb3e94460d806975f684415a0ebb80b5a13e926 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Sun, 28 Apr 2024 20:40:04 +0200 Subject: [PATCH 2/2] allow parenthesized sequence expression --- packages/svelte/src/compiler/errors.js | 2 +- packages/svelte/src/compiler/phases/1-parse/state/tag.js | 7 ++++++- .../compiler-errors/samples/const-tag-sequence/_config.js | 3 ++- .../compiler-errors/samples/const-tag-sequence/main.svelte | 4 ++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/svelte/src/compiler/errors.js b/packages/svelte/src/compiler/errors.js index f071cbe6fd05..5596d9dfd4c9 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -729,7 +729,7 @@ export function component_invalid_directive(node) { } /** - * {@const ...} must be an assignment + * {@const ...} must consist of a single variable declaration * @param {null | number | NodeLike} node * @returns {never} */ 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 86e713b522a0..c7308a7bce6a 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -551,8 +551,13 @@ function special(parser) { parser.eat('=', true); parser.allow_whitespace(); + const expression_start = parser.index; const init = read_expression(parser); - if (init.type === 'SequenceExpression') { + if ( + init.type === 'SequenceExpression' && + !parser.template.substring(expression_start, init.start).includes('(') + ) { + // const a = (b, c) is allowed but a = b, c = d is not; e.const_tag_invalid_expression(init); } parser.allow_whitespace(); diff --git a/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js index eac1302fdc2f..a9e6ee125061 100644 --- a/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js +++ b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js @@ -3,6 +3,7 @@ import { test } from '../../test'; export default test({ error: { code: 'const_tag_invalid_expression', - message: '{@const ...} must consist of a single variable declaration' + message: '{@const ...} must consist of a single variable declaration', + position: [75, 93] } }); diff --git a/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte index 5d66ea33eb92..7e446e6a8941 100644 --- a/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte +++ b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte @@ -1,3 +1,7 @@ +{#if true} + {@const foo = ('bar', 'baz')} +{/if} + {#if true} {@const foo = 'foo', bar = 'bar'} {/if} \ No newline at end of file