From 5e0845fe3ef5c2fade444a17828ef977fee3e78d Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Mon, 29 Apr 2024 22:48:40 +0200 Subject: [PATCH] fix: disallow sequence expressions in `@const` tags (#11357) * fix: disallow sequence expressions in `@const` tags closes #11349 * allow parenthesized sequence expression --- .changeset/orange-masks-exercise.md | 5 +++++ packages/svelte/messages/compile-errors/template.md | 2 +- packages/svelte/src/compiler/errors.js | 4 ++-- packages/svelte/src/compiler/phases/1-parse/state/tag.js | 8 ++++++++ .../samples/const-tag-sequence/_config.js | 9 +++++++++ .../samples/const-tag-sequence/main.svelte | 7 +++++++ 6 files changed, 32 insertions(+), 3 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 0000000000..76fdc4aab8 --- /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 293d4845cd..3460d8800b 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 d2834d03d4..dd979170a7 100644 --- a/packages/svelte/src/compiler/errors.js +++ b/packages/svelte/src/compiler/errors.js @@ -729,12 +729,12 @@ 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} */ 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 a41c5d09a0..9e797f4c57 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -551,7 +551,15 @@ function special(parser) { parser.eat('=', true); parser.allow_whitespace(); + const expression_start = parser.index; const init = read_expression(parser); + 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(); 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 0000000000..a9e6ee1250 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'const_tag_invalid_expression', + 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 new file mode 100644 index 0000000000..7e446e6a89 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/const-tag-sequence/main.svelte @@ -0,0 +1,7 @@ +{#if true} + {@const foo = ('bar', 'baz')} +{/if} + +{#if true} + {@const foo = 'foo', bar = 'bar'} +{/if} \ No newline at end of file