fix: preserve logical assignments to private state fields

pull/18594/head
subotac 6 days ago
parent 44a7813730
commit 60c724945a
No known key found for this signature in database

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: preserve short-circuiting for logical assignments to private state fields

@ -1,4 +1,4 @@
/** @import { AssignmentExpression, AssignmentOperator, Expression, Identifier, Pattern } from 'estree' */
/** @import { AssignmentExpression, AssignmentOperator, Expression, Identifier, LogicalOperator, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { Context } from '../types.js' */
import * as b from '#compiler/builders';
@ -79,8 +79,13 @@ function build_assignment(operator, left, right, context) {
// special case — assignment to private state field
if (left.property.type === 'PrivateIdentifier') {
const logical_operator = ['||=', '&&=', '??='].includes(operator)
? /** @type {LogicalOperator} */ (operator.slice(0, -1))
: null;
let value = /** @type {Expression} */ (
context.visit(build_assignment_value(operator, left, right))
context.visit(
logical_operator === null ? build_assignment_value(operator, left, right) : right
)
);
const needs_proxy =
@ -88,7 +93,15 @@ function build_assignment(operator, left, right, context) {
is_non_coercive_operator(operator) &&
should_proxy(value, context.state.scope);
return b.call('$.set', left, value, needs_proxy && b.true);
const assignment = b.call('$.set', left, value, needs_proxy && b.true);
return logical_operator === null
? assignment
: b.logical(
logical_operator,
/** @type {Expression} */ (context.visit(left)),
assignment
);
}
}
}

@ -0,0 +1,5 @@
import { test } from '../../test';
export default test({
html: `<p>truthy||value</p>`
});

@ -0,0 +1,24 @@
<script>
class Values {
#or = $state.raw('truthy');
#and = $state.raw('');
#nullish = $state.raw('value');
get or() {
return (this.#or ||= 'assigned');
}
get and() {
return (this.#and &&= 'assigned');
}
get nullish() {
return (this.#nullish ??= 'assigned');
}
}
const values = new Values();
const result = $derived([values.or, values.and, values.nullish]);
</script>
<p>{result.join('|')}</p>
Loading…
Cancel
Save