diff --git a/.changeset/tidy-fans-relax.md b/.changeset/tidy-fans-relax.md new file mode 100644 index 0000000000..4fefa924a6 --- /dev/null +++ b/.changeset/tidy-fans-relax.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: ensure frozen objects in state are correctly skipped diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index 53ce093dc3..6ff4d72a49 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -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} [prev] dev mode only * @returns {import('#client').ProxyStateObject | 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} */ (value[STATE_SYMBOL]); @@ -99,7 +99,7 @@ export function proxy(initial_value, immutable = true, parent = null, prev) { } } - return initial_value; + return value; } /** diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 92a13dc6d4..36d0602275 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -1337,9 +1337,14 @@ if (DEV) { * @returns {Readonly} */ 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, { diff --git a/packages/svelte/tests/runtime-runes/samples/class-state-frozen/_config.js b/packages/svelte/tests/runtime-runes/samples/class-state-frozen/_config.js new file mode 100644 index 0000000000..48a2c13e06 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/class-state-frozen/_config.js @@ -0,0 +1,7 @@ +import { test } from '../../test'; + +export default test({ + test({ assert, target }) { + assert.htmlEqual(target.innerHTML, `hello`); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/class-state-frozen/main.svelte b/packages/svelte/tests/runtime-runes/samples/class-state-frozen/main.svelte new file mode 100644 index 0000000000..4e0cdef476 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/class-state-frozen/main.svelte @@ -0,0 +1,34 @@ + + + + +{val.value}