From b6cf85019724d89b4da1723fa5b3ef825901a236 Mon Sep 17 00:00:00 2001 From: Nic <162764842+Nic-Polumeyv@users.noreply.github.com> Date: Fri, 18 Sep 2026 18:51:42 -0400 Subject: [PATCH] svelte:element's this is promoted here, as upstream does it: a mixed value warns and takes its first chunk --- .../src/compiler/phases/1-parse/grammar.js | 2 +- .../src/compiler/phases/1-parse/index.js | 53 +++++++++++-------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/svelte/src/compiler/phases/1-parse/grammar.js b/packages/svelte/src/compiler/phases/1-parse/grammar.js index a3bd3359ef..5097d90e55 100644 --- a/packages/svelte/src/compiler/phases/1-parse/grammar.js +++ b/packages/svelte/src/compiler/phases/1-parse/grammar.js @@ -14,7 +14,7 @@ elements name=name attributes=attributes children=fragment text Text data=data raw=raw comment Comment data=data -element svelte:element SvelteElement this=tag:text +element svelte:element SvelteElement element svelte:component SvelteComponent this=expression element svelte:self SvelteSelf element svelte:window SvelteWindow root once diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js index 71bd2c086b..5d0ba5ba85 100644 --- a/packages/svelte/src/compiler/phases/1-parse/index.js +++ b/packages/svelte/src/compiler/phases/1-parse/index.js @@ -7,7 +7,12 @@ import * as e from '../../errors.js'; import * as w from '../../warnings.js'; import * as state from '../../state.js'; import { ExpressionMetadata, disallow_children } from '../nodes.js'; -import { keep_tables, tables_of } from '../../utils/ast.js'; +import { + get_attribute_expression, + is_expression_attribute, + keep_tables, + tables_of +} from '../../utils/ast.js'; import { grammar } from './grammar.js'; // the grammar is read by the engine once, whatever it parses @@ -306,15 +311,28 @@ class Finish { } : /** @type {any} */ ({}); if (node.type === 'SvelteElement') { - // a tag named in text is the literal Svelte writes by hand, quoted its way - if (node.tag.type === 'Literal' && node.tag.raw === node.tag.value) { - const { start, end } = /** @type {{ start: number; end: number }} */ (node.tag); - const quoted = this.template[start - 1] === '"' || this.template[start - 1] === "'"; - w.svelte_element_invalid_this({ - start: this.template.lastIndexOf('this', start), - end: quoted ? end + 1 : end - }); - node.tag.raw = `'${node.tag.value}'`; + const index = node.attributes.findIndex( + (attribute) => attribute.type === 'Attribute' && attribute.name === 'this' + ); + if (index === -1) e.svelte_element_missing_this(node.start); + const definition = /** @type {AST.Attribute} */ (node.attributes.splice(index, 1)[0]); + if (definition.value === true) e.svelte_element_missing_this(definition); + if (is_expression_attribute(definition)) { + node.tag = get_attribute_expression(definition); + } else { + w.svelte_element_invalid_this(definition); + // wrong for `this="h{n}"`, which gives ``: the Svelte 4 behaviour, kept until 6.0 makes it an error + const chunk = /** @type {Array} */ (definition.value)[0]; + node.tag = + chunk.type === 'Text' + ? { + type: 'Literal', + value: chunk.data, + raw: `'${chunk.raw}'`, + start: chunk.start, + end: chunk.end + } + : chunk.expression; } node.metadata.expression = new ExpressionMetadata(); } @@ -610,19 +628,8 @@ function throw_error(error, template) { if (what === 'a block name') e.expected_block_type(pos); if (what === 'an attribute value') e.expected_attribute_value(pos); if (what === 'a tag name') e.expected_tag(pos); - if (what === 'a this attribute') { - if (template.startsWith(' - template.lastIndexOf('