* chore: use closures for state proxies
* use variables
* early return
* tidy up
* move ownership stuff into separate object
* put original value directly on STATE_SYMBOL
* rename
* tidy up
* tidy
* tweak
* fix
* remove is_frozen check
* remove `$state.is`
* avoid mutations
* tweak
* changesets
* changeset
* changeset
* regenerate
* add comment
* add note
* add test
@ -101,28 +101,6 @@ To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snaps
This is handy when you want to pass some state to an external library or API that doesn't expect a proxy, such as `structuredClone`.
## `$state.is`
Sometimes you might need to compare two values, one of which is a reactive `$state(...)` proxy but the other is not. For this you can use `$state.is(a, b)`:
```svelte
<script>
let foo = $state({});
let bar = {};
foo.bar = bar;
console.log(foo.bar === bar); // false — `foo.bar` is a reactive proxy
console.log($state.is(foo.bar, bar)); // true
</script>
```
This is handy when you might want to check if the object exists within a deeply reactive object/array.
Under the hood, `$state.is` uses [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) for comparing the values.
> Use this as an escape hatch - most of the time you don't need this. Svelte will warn you at dev time if you happen to run into this problem
## `$derived`
Derived state is declared with the `$derived` rune:
> Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results. Consider using `$state.is(a, b)` instead%details%
> Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results
`$state(...)` creates a [proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) of the value it is passed. The proxy and the value have different identities, meaning equality checks will always return `false`:
@ -57,15 +57,4 @@
</script>
```
In the rare case that you need to compare them, you can use `$state.is`, which unwraps proxies:
```svelte
<script>
let value = { foo: 'bar' };
let proxy = $state(value);
$state.is(value, proxy); // true
</script>
```
During development, Svelte will warn you when comparing values with proxies.
To resolve this, ensure you're comparing values where both values were created with `$state(...)`, or neither were. Note that `$state.raw(...)` will _not_ create a state proxy.
consterror=newError(`state_descriptors_fixed\nProperty descriptors defined on \`$state\` objects must contain \`value\` and always be \`enumerable\`, \`configurable\` and \`writable\`.`);
console.warn(`%c[svelte] state_proxy_equality_mismatch\n%cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results. Consider using \`$state.is(a, b)\` instead${details}`,bold,normal);
console.warn(`%c[svelte] state_proxy_equality_mismatch\n%cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${operator}\` will produce unexpected results`,bold,normal);