fix: show correct errors for invalid runes in `.svelte.js` files (#12432)

* fix: show correct error for renamed runes in `.svelte.js` files

* better

* changeset

* comment

* cleanup

* types & lint

* lint

* revert src changes

* move existing validation logic

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/12433/head
Ahmad S 6 months ago committed by GitHub
parent 8d3c0266ce
commit 879d88f612
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: show correct errors for invalid runes in `.svelte.js` files

@ -1043,6 +1043,41 @@ export const validation_runes_js = {
if (node.callee.type === 'ClassExpression' && context.state.scope.function_depth > 0) {
w.perf_avoid_inline_class(node);
}
},
Identifier(node, { path, state }) {
let i = path.length;
let parent = /** @type {import('estree').Expression} */ (path[--i]);
if (
Runes.includes(/** @type {Runes[number]} */ (node.name)) &&
is_reference(node, parent) &&
state.scope.get(node.name) === null &&
state.scope.get(node.name.slice(1)) === null
) {
/** @type {import('estree').Expression} */
let current = node;
let name = node.name;
while (parent.type === 'MemberExpression') {
if (parent.computed) e.rune_invalid_computed_property(parent);
name += `.${/** @type {import('estree').Identifier} */ (parent.property).name}`;
current = parent;
parent = /** @type {import('estree').Expression} */ (path[--i]);
if (!Runes.includes(/** @type {Runes[number]} */ (name))) {
if (name === '$effect.active') {
e.rune_renamed(parent, '$effect.active', '$effect.tracking');
}
e.rune_invalid_name(parent, name);
}
}
if (parent.type !== 'CallExpression') {
e.rune_missing_parentheses(current);
}
}
}
};
@ -1153,41 +1188,6 @@ export const validation_runes = merge(validation, a11y_validators, {
e.import_svelte_internal_forbidden(node);
}
},
Identifier(node, { path, state }) {
let i = path.length;
let parent = /** @type {import('estree').Expression} */ (path[--i]);
if (
Runes.includes(/** @type {Runes[number]} */ (node.name)) &&
is_reference(node, parent) &&
state.scope.get(node.name) === null &&
state.scope.get(node.name.slice(1)) === null
) {
/** @type {import('estree').Expression} */
let current = node;
let name = node.name;
while (parent.type === 'MemberExpression') {
if (parent.computed) e.rune_invalid_computed_property(parent);
name += `.${/** @type {import('estree').Identifier} */ (parent.property).name}`;
current = parent;
parent = /** @type {import('estree').Expression} */ (path[--i]);
if (!Runes.includes(/** @type {Runes[number]} */ (name))) {
if (name === '$effect.active') {
e.rune_renamed(parent, '$effect.active', '$effect.tracking');
}
e.rune_invalid_name(parent, name);
}
}
if (parent.type !== 'CallExpression') {
e.rune_missing_parentheses(current);
}
}
},
LabeledStatement(node, { path }) {
if (node.label.name !== '$' || path.at(-1)?.type !== 'Program') return;
e.legacy_reactive_statement_invalid(node);
@ -1368,5 +1368,6 @@ export const validation_runes = merge(validation, a11y_validators, {
// TODO this is a code smell. need to refactor this stuff
ClassBody: validation_runes_js.ClassBody,
ClassDeclaration: validation_runes_js.ClassDeclaration,
Identifier: validation_runes_js.Identifier,
NewExpression: validation_runes_js.NewExpression
});

@ -0,0 +1,8 @@
import { test } from '../../test';
export default test({
error: {
code: 'rune_renamed',
message: '`$effect.active` is now `$effect.tracking`'
}
});

@ -0,0 +1,8 @@
import { test } from '../../test';
export default test({
error: {
code: 'rune_invalid_name',
message: '`$effect.imnotarune` is not a valid rune'
}
});
Loading…
Cancel
Save