proxify values assigned to private state fields

pull/14273/head
Rich Harris 2 years ago
parent b07fc795d0
commit 7ace774dcc

@ -39,18 +39,21 @@ function build_assignment(operator, left, right, context) {
if (private_state !== undefined) {
let transformed = false;
let value = /** @type {Expression} */ (
context.visit(build_assignment_value(operator, left, right))
);
if (should_proxy(value, context.state.scope)) {
if (
private_state.kind === 'state' &&
// other operators result in coercion
['=', '||=', '&&=', '??='].includes(operator) &&
should_proxy(right, context.state.scope)
) {
transformed = true;
value =
private_state.kind === 'raw_state'
? value
: build_proxy_reassignment(value, b.member(b.this, private_state.id));
right = build_proxy_reassignment(right, b.member(b.this, private_state.id));
}
let value = /** @type {Expression} */ (
context.visit(build_assignment_value(operator, left, right))
);
if (!context.state.in_constructor) {
return b.call('$.set', left, value);
} else if (transformed) {

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

@ -1,7 +1,25 @@
<script>
let items = $state(null);
class Foo {
#items = $state(null);
get items() {
return this.#items;
}
add() {
(this.#items ??= []).push(this.#items.length);
}
}
const foo = new Foo();
</script>
<button onclick={() => (items ??= []).push(items.length)}>
items: {JSON.stringify(items)}
</button>
<button onclick={() => foo.add()}>
items: {JSON.stringify(foo.items)}
</button>

Loading…
Cancel
Save