From 35e1e0baed4f3b2f6604fa9f8d4fdd384a863dd3 Mon Sep 17 00:00:00 2001 From: Nic <162764842+Nic-Polumeyv@users.noreply.github.com> Date: Sat, 12 Sep 2026 20:33:18 -0400 Subject: [PATCH] a render tag needs a call, a duplicate clause and an elseif keep their own errors --- packages/svelte/src/compiler/phases/1-parse/index.js | 11 +++++++++-- .../samples/block-duplicate-clause/_config.js | 9 +++++++++ .../samples/block-duplicate-clause/main.svelte | 1 + .../samples/block-invalid-elseif/_config.js | 9 +++++++++ .../samples/block-invalid-elseif/main.svelte | 1 + .../samples/render-tag-invalid-expression/_config.js | 9 +++++++++ .../samples/render-tag-invalid-expression/main.svelte | 1 + 7 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 packages/svelte/tests/compiler-errors/samples/block-duplicate-clause/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/block-duplicate-clause/main.svelte create mode 100644 packages/svelte/tests/compiler-errors/samples/block-invalid-elseif/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/block-invalid-elseif/main.svelte create mode 100644 packages/svelte/tests/compiler-errors/samples/render-tag-invalid-expression/_config.js create mode 100644 packages/svelte/tests/compiler-errors/samples/render-tag-invalid-expression/main.svelte diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js index 08c6d90e87..de959ba755 100644 --- a/packages/svelte/src/compiler/phases/1-parse/index.js +++ b/packages/svelte/src/compiler/phases/1-parse/index.js @@ -322,7 +322,9 @@ class Finish { case 'HtmlTag': this.expression(node, node.expression); return; - case 'RenderTag': + case 'RenderTag': { + const call = node.expression.type === 'ChainExpression' ? node.expression.expression : node.expression; + if (call.type !== 'CallExpression') e.render_tag_invalid_expression(node.expression); this.expression(node, node.expression); node.metadata = { ...node.metadata, @@ -332,6 +334,7 @@ class Finish { snippets: new Set() }; return; + } case 'ConstTag': case 'DeclarationTag': this.expression(node, node.declaration); @@ -591,7 +594,10 @@ function throw_error(error, template) { } // a branch that fits no open block, reported at its sigil if (what === 'else') e.expected_token(pos + 1, '{:else}'); - if (what === 'else if or else') e.expected_token(pos + 1, '{:else} or {:else if}'); + if (what === 'else if or else') { + if (template.startsWith('{:elseif', pos)) e.block_invalid_elseif(pos + 1); + e.expected_token(pos + 1, '{:else} or {:else if}'); + } if (what === 'then or catch') e.expected_token(pos + 1, '{:then ...} or {:catch ...}'); if (what === 'a block name') e.expected_block_type(pos); if (what === 'an attribute value') e.expected_attribute_value(pos); @@ -638,6 +644,7 @@ function throw_error(error, template) { if (name === 'script') e.script_duplicate(pos); if (name === 'style') e.style_duplicate(pos); if (name.startsWith('svelte:')) e.svelte_meta_duplicate(pos, name); + if (name.startsWith('{:')) e.block_duplicate_clause(pos + 1, name); e.attribute_duplicate(range); } // eslint-disable-next-line no-fallthrough diff --git a/packages/svelte/tests/compiler-errors/samples/block-duplicate-clause/_config.js b/packages/svelte/tests/compiler-errors/samples/block-duplicate-clause/_config.js new file mode 100644 index 0000000000..d205dd9756 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/block-duplicate-clause/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'block_duplicate_clause', + message: '{:then} cannot appear more than once within a block', + position: [43, 43] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/block-duplicate-clause/main.svelte b/packages/svelte/tests/compiler-errors/samples/block-duplicate-clause/main.svelte new file mode 100644 index 0000000000..c70d8c396a --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/block-duplicate-clause/main.svelte @@ -0,0 +1 @@ +{#await p}{:then x}{:then y}{/await} diff --git a/packages/svelte/tests/compiler-errors/samples/block-invalid-elseif/_config.js b/packages/svelte/tests/compiler-errors/samples/block-invalid-elseif/_config.js new file mode 100644 index 0000000000..cc331c2e28 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/block-invalid-elseif/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'block_invalid_elseif', + message: "'elseif' should be 'else if'", + position: [34, 34] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/block-invalid-elseif/main.svelte b/packages/svelte/tests/compiler-errors/samples/block-invalid-elseif/main.svelte new file mode 100644 index 0000000000..c50f7ae130 --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/block-invalid-elseif/main.svelte @@ -0,0 +1 @@ +{#if x}{:elseif y}{/if} diff --git a/packages/svelte/tests/compiler-errors/samples/render-tag-invalid-expression/_config.js b/packages/svelte/tests/compiler-errors/samples/render-tag-invalid-expression/_config.js new file mode 100644 index 0000000000..0d49bfdcbd --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/render-tag-invalid-expression/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + error: { + code: 'render_tag_invalid_expression', + message: '`{@render ...}` tags can only contain call expressions', + position: [34, 37] + } +}); diff --git a/packages/svelte/tests/compiler-errors/samples/render-tag-invalid-expression/main.svelte b/packages/svelte/tests/compiler-errors/samples/render-tag-invalid-expression/main.svelte new file mode 100644 index 0000000000..16383aa6be --- /dev/null +++ b/packages/svelte/tests/compiler-errors/samples/render-tag-invalid-expression/main.svelte @@ -0,0 +1 @@ +{@render foo}