fix: ensure class constructor values are proxied (#9888)

* fix: ensure class constructor values are proxied

* debugger
pull/9889/head
Dominic Gannaway 7 months ago committed by GitHub
parent 646c0c432b
commit bdd63c8187
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure class constructor values are proxied

@ -157,16 +157,45 @@ export function serialize_set_binding(node, context, fallback) {
let left = node.left;
// Handle class private/public state assignment cases
while (left.type === 'MemberExpression') {
if (left.object.type === 'ThisExpression' && left.property.type === 'PrivateIdentifier') {
if (context.state.private_state.has(left.property.name) && !state.in_constructor) {
const value = get_assignment_value(node, context);
if (
left.object.type === 'ThisExpression' &&
left.property.type === 'PrivateIdentifier' &&
context.state.private_state.has(left.property.name)
) {
const value = get_assignment_value(node, context);
if (state.in_constructor) {
// See if we should wrap value in $.proxy
if (context.state.analysis.runes && should_proxy(value)) {
const assignment = fallback();
if (assignment.type === 'AssignmentExpression') {
assignment.right = b.call('$.proxy', value);
return assignment;
}
}
} else {
return b.call(
'$.set',
left,
context.state.analysis.runes && should_proxy(value) ? b.call('$.proxy', value) : value
);
}
} else if (
left.object.type === 'ThisExpression' &&
left.property.type === 'Identifier' &&
context.state.public_state.has(left.property.name) &&
state.in_constructor
) {
const value = get_assignment_value(node, context);
// See if we should wrap value in $.proxy
if (context.state.analysis.runes && should_proxy(value)) {
const assignment = fallback();
if (assignment.type === 'AssignmentExpression') {
assignment.right = b.call('$.proxy', value);
return assignment;
}
}
}
// @ts-expect-error
left = left.object;

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

@ -0,0 +1,16 @@
<script>
class Counter {
#count = $state();
constructor(v) {
this.#count = v;
}
get count() {
return this.#count;
}
}
const counter = new Counter({ count: 0 });
</script>
<button on:click={() => counter.count.count++}>{counter.count.count}</button>

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

@ -0,0 +1,12 @@
<script>
class Counter {
count = $state();
constructor(v) {
this.count = v;
}
}
const counter = new Counter({ count: 0 });
</script>
<button on:click={() => counter.count.count++}>{counter.count.count}</button>
Loading…
Cancel
Save