fix: don't transform reassigned state in labeled statement in `$derived` (#15725)

* fix: don't transform reassigned state in labeled statement in `$derived`

* fix type so optional chaining is unnecessary

* drive-by tidy up

* drive-by tidy up

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/15729/head
Paolo Ricciuti 5 months ago committed by GitHub
parent 73acf6e7f4
commit 0d233e58cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: don't transform reassigned state in labeled statement in `$derived`

@ -944,21 +944,19 @@ const instance_script = {
node.body.type === 'ExpressionStatement' &&
node.body.expression.type === 'AssignmentExpression'
) {
const ids = extract_identifiers(node.body.expression.left);
const [, expression_ids] = extract_all_identifiers_from_expression(
node.body.expression.right
);
const bindings = ids.map((id) => state.scope.get(id.name));
const reassigned_bindings = bindings.filter((b) => b?.reassigned);
const { left, right } = node.body.expression;
const ids = extract_identifiers(left);
const [, expression_ids] = extract_all_identifiers_from_expression(right);
const bindings = ids.map((id) => /** @type {Binding} */ (state.scope.get(id.name)));
if (bindings.every((b) => b.kind === 'legacy_reactive')) {
if (
node.body.expression.right.type !== 'Literal' &&
!bindings.some((b) => b?.kind === 'store_sub') &&
node.body.expression.left.type !== 'MemberExpression'
right.type !== 'Literal' &&
bindings.every((b) => b.kind !== 'store_sub') &&
left.type !== 'MemberExpression'
) {
let { start, end } = /** @type {{ start: number, end: number }} */ (
node.body.expression.right
);
let { start, end } = /** @type {{ start: number, end: number }} */ (right);
check_rune_binding('derived');
@ -969,7 +967,7 @@ const instance_script = {
'let '
);
if (node.body.expression.right.type === 'SequenceExpression') {
if (right.type === 'SequenceExpression') {
while (state.str.original[start] !== '(') start -= 1;
while (state.str.original[end - 1] !== ')') end += 1;
}
@ -983,15 +981,16 @@ const instance_script = {
}
return;
} else {
for (const binding of reassigned_bindings) {
if (binding && (ids.includes(binding.node) || expression_ids.length === 0)) {
}
for (const binding of bindings) {
if (binding.reassigned && (ids.includes(binding.node) || expression_ids.length === 0)) {
check_rune_binding('state');
const init =
binding.kind === 'state'
? ' = $state()'
: expression_ids.length === 0
? ` = $state(${state.str.original.substring(/** @type {number} */ (node.body.expression.right.start), node.body.expression.right.end)})`
? ` = $state(${state.str.original.substring(/** @type {number} */ (right.start), right.end)})`
: '';
// implicitly-declared variable which we need to make explicit
state.str.prependLeft(
@ -1000,7 +999,8 @@ const instance_script = {
);
}
}
if (expression_ids.length === 0 && !bindings.some((b) => b?.kind === 'store_sub')) {
if (expression_ids.length === 0 && bindings.every((b) => b.kind !== 'store_sub')) {
state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end));
return;
}

@ -0,0 +1,6 @@
<script>
let something = '123';
let foo = false;
$: foo = !!something;
</script>

@ -0,0 +1,10 @@
<script>
import { run } from 'svelte/legacy';
let something = '123';
let foo = $state(false);
run(() => {
foo = !!something;
});
</script>
Loading…
Cancel
Save