feat: allow modifiying derived props (#10080)

It's an unnecessary restruction because it can be worked around (hide it behind a getter/setter), already works for bind:x and prevents valid use cases
pull/10127/head
Simon H 11 months ago committed by GitHub
parent b623890439
commit 3624a4c2a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
feat: allow modifiying derived props

@ -854,6 +854,13 @@ function validate_assignment(node, argument, state) {
let left = /** @type {import('estree').Expression | import('estree').Super} */ (argument); let left = /** @type {import('estree').Expression | import('estree').Super} */ (argument);
if (left.type === 'Identifier') {
const binding = state.scope.get(left.name);
if (binding?.kind === 'derived') {
error(node, 'invalid-derived-assignment');
}
}
/** @type {import('estree').Expression | import('estree').PrivateIdentifier | null} */ /** @type {import('estree').Expression | import('estree').PrivateIdentifier | null} */
let property = null; let property = null;
@ -862,13 +869,6 @@ function validate_assignment(node, argument, state) {
left = left.object; left = left.object;
} }
if (left.type === 'Identifier') {
const binding = state.scope.get(left.name);
if (binding?.kind === 'derived') {
error(node, 'invalid-derived-assignment');
}
}
if (left.type === 'ThisExpression' && property?.type === 'PrivateIdentifier') { if (left.type === 'ThisExpression' && property?.type === 'PrivateIdentifier') {
if (state.private_derived_state.includes(property.name)) { if (state.private_derived_state.includes(property.name)) {
error(node, 'invalid-derived-assignment'); error(node, 'invalid-derived-assignment');

@ -1,5 +1,5 @@
<script> <script>
const a = $state(0); const a = $state(0);
const b = $derived({ a }); let b = $derived(a);
b.a += 1; b = 1;
</script> </script>

@ -1,5 +1,5 @@
<script> <script>
const a = $state(0); const a = $state(0);
const b = $derived({ a }); let b = $derived(a);
b.a++; b++;
</script> </script>

@ -0,0 +1,15 @@
import { test } from '../../test';
export default test({
html: `<button>0 / 0</button><button>0 / 0</button>`,
async test({ assert, target }) {
const [btn1, btn2] = target.querySelectorAll('button');
await btn1?.click();
assert.htmlEqual(target.innerHTML, `<button>1 / 2</button><button>1 / 2</button>`);
await btn2?.click();
assert.htmlEqual(target.innerHTML, `<button>2 / 4</button><button>2 / 4</button>`);
}
});

@ -0,0 +1,7 @@
<script>
let count = $state(0);
let double = $derived({ get value() { return count * 2}, set value(c) { count = c / 2 } });
</script>
<button on:click={() => count++}>{count} / {double.value}</button>
<button on:click={() => double.value += 2}>{count} / {double.value}</button>
Loading…
Cancel
Save