Skip to content

Commit 832f8de

Browse files
authored
fix: ensure frozen objects in state are correctly skipped (#11889)
Fixes #11887
1 parent 5eb8641 commit 832f8de

File tree

5 files changed

+62
-11
lines changed

5 files changed

+62
-11
lines changed

.changeset/tidy-fans-relax.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: ensure frozen objects in state are correctly skipped

packages/svelte/src/internal/client/proxy.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@ import * as e from './errors.js';
2424

2525
/**
2626
* @template T
27-
* @param {T} initial_value
27+
* @param {T} value
2828
* @param {boolean} [immutable]
2929
* @param {import('#client').ProxyMetadata | null} [parent]
3030
* @param {import('#client').Source<T>} [prev] dev mode only
3131
* @returns {import('#client').ProxyStateObject<T> | T}
3232
*/
33-
export function proxy(initial_value, immutable = true, parent = null, prev) {
34-
if (typeof initial_value === 'object' && initial_value != null) {
35-
let value = initial_value;
36-
// If the object is frozen then snapshot the value
37-
if (is_frozen(value) || STATE_FROZEN_SYMBOL in value) {
38-
value = snapshot(value);
39-
}
33+
export function proxy(value, immutable = true, parent = null, prev) {
34+
if (
35+
typeof value === 'object' &&
36+
value != null &&
37+
!is_frozen(value) &&
38+
!(STATE_FROZEN_SYMBOL in value)
39+
) {
4040
// If we have an existing proxy, return it...
4141
if (STATE_SYMBOL in value) {
4242
const metadata = /** @type {import('#client').ProxyMetadata<T>} */ (value[STATE_SYMBOL]);
@@ -99,7 +99,7 @@ export function proxy(initial_value, immutable = true, parent = null, prev) {
9999
}
100100
}
101101

102-
return initial_value;
102+
return value;
103103
}
104104

105105
/**

packages/svelte/src/internal/client/runtime.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,9 +1337,14 @@ if (DEV) {
13371337
* @returns {Readonly<T>}
13381338
*/
13391339
export function freeze(value) {
1340-
if (typeof value === 'object' && value != null && !(STATE_FROZEN_SYMBOL in value)) {
1340+
if (
1341+
typeof value === 'object' &&
1342+
value != null &&
1343+
!is_frozen(value) &&
1344+
!(STATE_FROZEN_SYMBOL in value)
1345+
) {
13411346
// If the object is already proxified, then snapshot the value
1342-
if (STATE_SYMBOL in value || is_frozen(value)) {
1347+
if (STATE_SYMBOL in value) {
13431348
value = snapshot(value);
13441349
}
13451350
define_property(value, STATE_FROZEN_SYMBOL, {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
test({ assert, target }) {
5+
assert.htmlEqual(target.innerHTML, `<input type="text"><span>hello</span>`);
6+
}
7+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script>
2+
const libFreezesObjects = true
3+
4+
function someLibFunctionCreatingFroozenObject(value) {
5+
if(libFreezesObjects) {
6+
return Object.freeze({inner: value})
7+
} else {
8+
return {inner: value}
9+
}
10+
}
11+
12+
function someLibFunctionReturningInner(wrapped) {
13+
return wrapped.inner
14+
}
15+
16+
function atom(init = null) {
17+
let el = $state({value: someLibFunctionCreatingFroozenObject(init)})
18+
19+
return {
20+
get value() {
21+
return someLibFunctionReturningInner(el.value)
22+
},
23+
set value(v) {
24+
el.value = someLibFunctionCreatingFroozenObject(v)
25+
},
26+
}
27+
}
28+
29+
let val = atom('hello')
30+
</script>
31+
32+
<input type="text" bind:value={val.value} />
33+
34+
<span>{val.value}</span>

0 commit comments

Comments
 (0)