svelte:element's this is promoted here, as upstream does it: a mixed value warns and takes its first chunk

goodbye-acorn
Nic 2 weeks ago
parent 4a143a3011
commit b6cf850197

@ -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

@ -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 `<h>`: the Svelte 4 behaviour, kept until 6.0 makes it an error
const chunk = /** @type {Array<AST.ExpressionTag | AST.Text>} */ (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('<svelte:element', pos)) e.svelte_element_missing_this(pos);
e.svelte_component_missing_this(pos);
}
if (what === 'an expression as this') {
if (
template.lastIndexOf('<svelte:element', pos) >
template.lastIndexOf('<svelte:component', pos)
) {
e.svelte_element_missing_this(range);
}
e.svelte_component_invalid_this(range);
}
if (what === 'a this attribute') e.svelte_component_missing_this(pos);
if (what === 'an expression as this') e.svelte_component_invalid_this(range);
if (what === 'an expression, not text' || what === 'a value') e.directive_invalid_value(pos);
if (what.startsWith('context to be')) e.script_invalid_context(range);
if (what === 'module without a value') e.script_invalid_attribute_value(range, 'module');

Loading…
Cancel
Save