fix: take private and public into account for `constant_assignment` of derived state (#15276)

Fixes #15273
pull/15271/head
Paolo Ricciuti 7 months ago committed by GitHub
parent 18481386f3
commit 5e52825d60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: take private and public into account for `constant_assignment` of derived state

@ -19,7 +19,7 @@ export interface AnalysisState {
component_slots: Set<string>;
/** Information about the current expression/directive/block value */
expression: ExpressionMetadata | null;
derived_state: string[];
derived_state: { name: string; private: boolean }[];
function_depth: number;
// legacy stuff

@ -7,7 +7,7 @@ import { get_rune } from '../../scope.js';
* @param {Context} context
*/
export function ClassBody(node, context) {
/** @type {string[]} */
/** @type {{name: string, private: boolean}[]} */
const derived_state = [];
for (const definition of node.body) {
@ -18,7 +18,10 @@ export function ClassBody(node, context) {
) {
const rune = get_rune(definition.value, context.state.scope);
if (rune === '$derived' || rune === '$derived.by') {
derived_state.push(definition.key.name);
derived_state.push({
name: definition.key.name,
private: definition.key.type === 'PrivateIdentifier'
});
}
}
}

@ -1,4 +1,4 @@
/** @import { AssignmentExpression, Expression, Literal, Node, Pattern, PrivateIdentifier, Super, UpdateExpression, VariableDeclarator } from 'estree' */
/** @import { AssignmentExpression, Expression, Identifier, Literal, Node, Pattern, PrivateIdentifier, Super, UpdateExpression, VariableDeclarator } from 'estree' */
/** @import { AST, Binding } from '#compiler' */
/** @import { AnalysisState, Context } from '../../types' */
/** @import { Scope } from '../../../scope' */
@ -38,16 +38,22 @@ export function validate_assignment(node, argument, state) {
e.snippet_parameter_assignment(node);
}
}
if (
argument.type === 'MemberExpression' &&
argument.object.type === 'ThisExpression' &&
(((argument.property.type === 'PrivateIdentifier' || argument.property.type === 'Identifier') &&
state.derived_state.includes(argument.property.name)) ||
state.derived_state.some(
(derived) =>
derived.name === /** @type {PrivateIdentifier | Identifier} */ (argument.property).name &&
derived.private === (argument.property.type === 'PrivateIdentifier')
)) ||
(argument.property.type === 'Literal' &&
argument.property.value &&
typeof argument.property.value === 'string' &&
state.derived_state.includes(argument.property.value)))
state.derived_state.some(
(derived) =>
derived.name === /** @type {Literal} */ (argument.property).value && !derived.private
)))
) {
e.constant_assignment(node, 'derived state');
}

@ -0,0 +1,13 @@
<script>
class Test {
#deps = () => [];
deps = $derived.by(() => {
return [];
});
constructor(f = () => []) {
this.#deps = f;
}
}
</script>
Loading…
Cancel
Save