fix: ensure frozen objects in state are correctly skipped (#11889)

Fixes #11887
pull/11874/head
Dominic Gannaway 1 year ago committed by GitHub
parent 5eb8641ac7
commit 832f8deeec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: ensure frozen objects in state are correctly skipped

@ -24,19 +24,19 @@ import * as e from './errors.js';
/**
* @template T
* @param {T} initial_value
* @param {T} value
* @param {boolean} [immutable]
* @param {import('#client').ProxyMetadata | null} [parent]
* @param {import('#client').Source<T>} [prev] dev mode only
* @returns {import('#client').ProxyStateObject<T> | T}
*/
export function proxy(initial_value, immutable = true, parent = null, prev) {
if (typeof initial_value === 'object' && initial_value != null) {
let value = initial_value;
// If the object is frozen then snapshot the value
if (is_frozen(value) || STATE_FROZEN_SYMBOL in value) {
value = snapshot(value);
}
export function proxy(value, immutable = true, parent = null, prev) {
if (
typeof value === 'object' &&
value != null &&
!is_frozen(value) &&
!(STATE_FROZEN_SYMBOL in value)
) {
// If we have an existing proxy, return it...
if (STATE_SYMBOL in value) {
const metadata = /** @type {import('#client').ProxyMetadata<T>} */ (value[STATE_SYMBOL]);
@ -99,7 +99,7 @@ export function proxy(initial_value, immutable = true, parent = null, prev) {
}
}
return initial_value;
return value;
}
/**

@ -1337,9 +1337,14 @@ if (DEV) {
* @returns {Readonly<T>}
*/
export function freeze(value) {
if (typeof value === 'object' && value != null && !(STATE_FROZEN_SYMBOL in value)) {
if (
typeof value === 'object' &&
value != null &&
!is_frozen(value) &&
!(STATE_FROZEN_SYMBOL in value)
) {
// If the object is already proxified, then snapshot the value
if (STATE_SYMBOL in value || is_frozen(value)) {
if (STATE_SYMBOL in value) {
value = snapshot(value);
}
define_property(value, STATE_FROZEN_SYMBOL, {

@ -0,0 +1,7 @@
import { test } from '../../test';
export default test({
test({ assert, target }) {
assert.htmlEqual(target.innerHTML, `<input type="text"><span>hello</span>`);
}
});

@ -0,0 +1,34 @@
<script>
const libFreezesObjects = true
function someLibFunctionCreatingFroozenObject(value) {
if(libFreezesObjects) {
return Object.freeze({inner: value})
} else {
return {inner: value}
}
}
function someLibFunctionReturningInner(wrapped) {
return wrapped.inner
}
function atom(init = null) {
let el = $state({value: someLibFunctionCreatingFroozenObject(init)})
return {
get value() {
return someLibFunctionReturningInner(el.value)
},
set value(v) {
el.value = someLibFunctionCreatingFroozenObject(v)
},
}
}
let val = atom('hello')
</script>
<input type="text" bind:value={val.value} />
<span>{val.value}</span>
Loading…
Cancel
Save