unskip and fix test

pull/15820/head
Rich Harris 4 months ago
parent c82ede5cf6
commit d6c985960b

@ -872,6 +872,12 @@ class Counter {
...but it can only happen once.
### state_field_invalid_assignment
```
Cannot assign to a state field before its declaration
```
### state_invalid_export
```

@ -236,6 +236,10 @@ class Counter {
...but it can only happen once.
## state_field_invalid_assignment
> Cannot assign to a state field before its declaration
## state_invalid_export
> Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties

@ -104,16 +104,6 @@ export function constant_binding(node, thing) {
e(node, 'constant_binding', `Cannot bind to ${thing}\nhttps://svelte.dev/e/constant_binding`);
}
/**
* `%name%` has already been declared on this class
* @param {null | number | NodeLike} node
* @param {string} name
* @returns {never}
*/
export function state_field_duplicate(node, name) {
e(node, 'state_field_duplicate', `\`${name}\` has already been declared on this class\nhttps://svelte.dev/e/state_field_duplicate`);
}
/**
* `%name%` has already been declared
* @param {null | number | NodeLike} node
@ -471,6 +461,25 @@ export function snippet_parameter_assignment(node) {
e(node, 'snippet_parameter_assignment', `Cannot reassign or bind to snippet parameter\nhttps://svelte.dev/e/snippet_parameter_assignment`);
}
/**
* `%name%` has already been declared on this class
* @param {null | number | NodeLike} node
* @param {string} name
* @returns {never}
*/
export function state_field_duplicate(node, name) {
e(node, 'state_field_duplicate', `\`${name}\` has already been declared on this class\nhttps://svelte.dev/e/state_field_duplicate`);
}
/**
* Cannot assign to a state field before its declaration
* @param {null | number | NodeLike} node
* @returns {never}
*/
export function state_field_invalid_assignment(node) {
e(node, 'state_field_invalid_assignment', `Cannot assign to a state field before its declaration\nhttps://svelte.dev/e/state_field_invalid_assignment`);
}
/**
* Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties
* @param {null | number | NodeLike} node

@ -8,7 +8,7 @@ import { validate_assignment } from './shared/utils.js';
* @param {Context} context
*/
export function AssignmentExpression(node, context) {
validate_assignment(node, node.left, context.state);
validate_assignment(node, node.left, context);
if (context.state.reactive_statement) {
const id = node.left.type === 'MemberExpression' ? object(node.left) : node.left;

@ -158,7 +158,7 @@ export function BindDirective(node, context) {
return;
}
validate_assignment(node, node.expression, context.state);
validate_assignment(node, node.expression, context);
const assignee = node.expression;
const left = object(assignee);

@ -8,7 +8,7 @@ import { validate_assignment } from './shared/utils.js';
* @param {Context} context
*/
export function UpdateExpression(node, context) {
validate_assignment(node, node.argument, context.state);
validate_assignment(node, node.argument, context);
if (context.state.reactive_statement) {
const id = node.argument.type === 'MemberExpression' ? object(node.argument) : node.argument;

@ -4,24 +4,25 @@
/** @import { Scope } from '../../../scope' */
/** @import { NodeLike } from '../../../../errors.js' */
import * as e from '../../../../errors.js';
import { extract_identifiers } from '../../../../utils/ast.js';
import { extract_identifiers, get_parent } from '../../../../utils/ast.js';
import * as w from '../../../../warnings.js';
import * as b from '#compiler/builders';
import { get_rune } from '../../../scope.js';
import { get_name } from '../../../nodes.js';
/**
* @param {AssignmentExpression | UpdateExpression | AST.BindDirective} node
* @param {Pattern | Expression} argument
* @param {AnalysisState} state
* @param {Context} context
*/
export function validate_assignment(node, argument, state) {
validate_no_const_assignment(node, argument, state.scope, node.type === 'BindDirective');
export function validate_assignment(node, argument, context) {
validate_no_const_assignment(node, argument, context.state.scope, node.type === 'BindDirective');
if (argument.type === 'Identifier') {
const binding = state.scope.get(argument.name);
const binding = context.state.scope.get(argument.name);
if (state.analysis.runes) {
if (binding?.node === state.analysis.props_id) {
if (context.state.analysis.runes) {
if (binding?.node === context.state.analysis.props_id) {
e.constant_assignment(node, '$props.id()');
}
@ -34,6 +35,41 @@ export function validate_assignment(node, argument, state) {
e.snippet_parameter_assignment(node);
}
}
if (argument.type === 'MemberExpression' && argument.object.type === 'ThisExpression') {
const name =
argument.computed && argument.property.type !== 'Literal'
? null
: get_name(argument.property);
const field =
name !== null &&
context.state.state_fields &&
Object.hasOwn(context.state.state_fields, name) &&
context.state.state_fields[name];
// check we're not assigning to a state field before its declaration in the constructor
if (field && field.node.type === 'AssignmentExpression' && node !== field.node) {
let i = context.path.length;
while (i--) {
const parent = context.path[i];
if (
parent.type === 'FunctionDeclaration' ||
parent.type === 'FunctionExpression' ||
parent.type === 'ArrowFunctionExpression'
) {
const grandparent = get_parent(context.path, i - 1);
if (grandparent.type === 'MethodDefinition' && grandparent.kind === 'constructor') {
e.state_field_invalid_assignment(node);
}
break;
}
}
}
}
}
/**

@ -1,5 +0,0 @@
import { test } from '../../test';
export default test({
skip: true // TODO delete this file so the test runs
});

@ -1,14 +1,14 @@
[
{
"code": "state_field_duplicate",
"message": "`count` has already been declared on this class",
"code": "state_field_invalid_assignment",
"message": "Cannot assign to a state field before its declaration",
"start": {
"line": 7,
"column": 2
"line": 4,
"column": 3
},
"end": {
"line": 7,
"column": 24
"line": 4,
"column": 18
}
}
]

Loading…
Cancel
Save