fix: improve handling of object property deletions

pull/10456/head
Dominic Gannaway 3 years ago
parent 1366932dc0
commit 278a5226ae

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: improve handling of object property deletions

@ -157,7 +157,7 @@ const state_proxy_handler = {
}
if (s !== undefined) set(s, UNINITIALIZED);
if (prop in target) update(metadata.v);
if (boolean) update(metadata.v);
return boolean;
},

@ -0,0 +1,16 @@
import { test } from '../../test';
export default test({
compileOptions: {
dev: true
},
html: `<button>state1.value: a state2.value: a</button>`,
async test({ assert, target }) {
const btn = target.querySelector('button');
await btn?.click();
assert.htmlEqual(target.innerHTML, `<button>state1.value: b state2.value: b</button>`);
}
});

@ -0,0 +1,28 @@
<script>
let foo = { value: 'a' }
let state1 = $state(foo);
let state2 = $state(foo);
</script>
<button onclick={() => {
let new_state1 = {};
let new_state2 = {};
// This contains Symbol.$state and Symbol.$readonly and we can't do anything against it,
// because it's called on the original object, not our state proxy
Reflect.ownKeys(foo).forEach(k => {
new_state1[k] = foo[k];
new_state2[k] = foo[k];
});
new_state1.value = 'b';
new_state2.value = 'b';
// $.proxy will see that Symbol.$state exists on this object already, which shouldn't result in a stale value
state1 = new_state1;
// $.proxy can't look into Symbol.$state because of the frozen object
state2 = Object.freeze(new_state2);
}}
>
state1.value: {state1.value}
state2.value: {state2.value}
</button>

@ -1,11 +0,0 @@
<script>
import Component2 from './Component2.svelte';
const {state} = $props();
function render(state) {
return state
}
</script>
<Component2 state={render(state)} />

@ -1,5 +0,0 @@
<script>
const {state} = $props();
</script>
{state}

@ -1,13 +1,20 @@
import { test } from '../../test';
export default test({
compileOptions: {
dev: true
},
html: '<button>set</button><button>delete</button><p>a,b,c</p><p>{"a":1,"b":2,"c":3}</p>',
async test({ assert, target }) {
const btn = target.querySelector('button');
const [btn, bt2] = target.querySelectorAll('button');
await btn?.click();
assert.htmlEqual(target.innerHTML, `<button></button>\n[object Object]`);
assert.htmlEqual(
target.innerHTML,
`<button>set</button><button>delete</button><p>a,b,c</p><p>{"a":1,"b":2,"c":3}</p>`
);
await bt2?.click();
assert.htmlEqual(
target.innerHTML,
`<button>set</button><button>delete</button><p>a,c</p><p>{"a":1,"c":3}</p>`
);
}
});

@ -1,12 +1,8 @@
<script>
import Component from './Component.svelte';
let state = $state();
let numbers = $state({ a: 1, b: 2, c: 3 });
</script>
<button onclick={() => {
state = {}
}}></button>
{#if state}
<Component state={state} />
{/if}
<button onclick={() => { numbers.b = 2; }}>set</button>
<button onclick={() => { delete numbers.b; }}>delete</button>
<p>{Object.keys(numbers)}</p>
<p>{JSON.stringify(numbers)}</p>

Loading…
Cancel
Save