Skip to content

Commit 86bbc83

Browse files
authored
fix: ensure unstate() only deeply applies to plain objects and arrays (#10191)
* fix: ensure unstate() only deeply applies to plain objects and arrays * tweak
1 parent 5dce70e commit 86bbc83

File tree

4 files changed

+38
-19
lines changed

4 files changed

+38
-19
lines changed

.changeset/forty-peaches-unite.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 unstate() only deeply applies to plain objects and arrays

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,22 @@ import {
1111
batch_inspect
1212
} from '../runtime.js';
1313
import {
14+
array_prototype,
1415
define_property,
1516
get_descriptor,
1617
get_descriptors,
18+
get_prototype_of,
1719
is_array,
18-
object_keys
20+
is_frozen,
21+
object_keys,
22+
object_prototype
1923
} from '../utils.js';
2024

2125
/** @typedef {{ s: Map<string | symbol, import('../types.js').SourceSignal<any>>; v: import('../types.js').SourceSignal<number>; a: boolean, i: boolean, p: StateObject }} Metadata */
2226
/** @typedef {Record<string | symbol, any> & { [STATE_SYMBOL]: Metadata }} StateObject */
2327

2428
export const STATE_SYMBOL = Symbol('$state');
2529
export const READONLY_SYMBOL = Symbol('readonly');
26-
27-
const object_prototype = Object.prototype;
28-
const array_prototype = Array.prototype;
29-
const get_prototype_of = Object.getPrototypeOf;
30-
const is_frozen = Object.isFrozen;
31-
3230
/**
3331
* @template {StateObject} T
3432
* @param {T} value

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

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import { DEV } from 'esm-env';
22
import { subscribe_to_store } from '../../store/utils.js';
33
import { EMPTY_FUNC, run_all } from '../common.js';
4-
import { get_descriptor, get_descriptors, is_array, is_frozen, object_freeze } from './utils.js';
4+
import {
5+
array_prototype,
6+
get_descriptor,
7+
get_descriptors,
8+
get_prototype_of,
9+
is_array,
10+
is_frozen,
11+
object_freeze,
12+
object_prototype
13+
} from './utils.js';
514
import {
615
PROPS_IS_LAZY_INITIAL,
716
PROPS_IS_IMMUTABLE,
@@ -1975,19 +1984,23 @@ function deep_unstate(value, visited = new Map()) {
19751984
visited.set(value, unstated);
19761985
return unstated;
19771986
}
1978-
1979-
let contains_unstated = false;
1980-
/** @type {any} */
1981-
const nested_unstated = Array.isArray(value) ? [] : {};
1982-
for (let key in value) {
1983-
const result = deep_unstate(value[key], visited);
1984-
nested_unstated[key] = result;
1985-
if (result !== value[key]) {
1986-
contains_unstated = true;
1987+
const prototype = get_prototype_of(value);
1988+
// Only deeply unstate plain objects and arrays
1989+
if (prototype === object_prototype || prototype === array_prototype) {
1990+
let contains_unstated = false;
1991+
/** @type {any} */
1992+
const nested_unstated = Array.isArray(value) ? [] : {};
1993+
for (let key in value) {
1994+
const result = deep_unstate(value[key], visited);
1995+
nested_unstated[key] = result;
1996+
if (result !== value[key]) {
1997+
contains_unstated = true;
1998+
}
19871999
}
2000+
visited.set(value, contains_unstated ? nested_unstated : value);
2001+
} else {
2002+
visited.set(value, value);
19882003
}
1989-
1990-
visited.set(value, contains_unstated ? nested_unstated : value);
19912004
}
19922005

19932006
return visited.get(value) ?? value;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export var object_freeze = Object.freeze;
1010
export var define_property = Object.defineProperty;
1111
export var get_descriptor = Object.getOwnPropertyDescriptor;
1212
export var get_descriptors = Object.getOwnPropertyDescriptors;
13+
export var object_prototype = Object.prototype;
14+
export var array_prototype = Array.prototype;
15+
export var get_prototype_of = Object.getPrototypeOf;
1316

1417
/**
1518
* @param {any} thing

0 commit comments

Comments
 (0)