diff --git a/.changeset/itchy-games-guess.md b/.changeset/itchy-games-guess.md new file mode 100644 index 0000000000..44516cfc21 --- /dev/null +++ b/.changeset/itchy-games-guess.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: don't clone non-proxies in `$inspect` diff --git a/packages/svelte/src/internal/shared/clone.js b/packages/svelte/src/internal/shared/clone.js index 4632fc3d68..b8f99ee198 100644 --- a/packages/svelte/src/internal/shared/clone.js +++ b/packages/svelte/src/internal/shared/clone.js @@ -15,14 +15,15 @@ const empty = []; * @template T * @param {T} value * @param {boolean} [skip_warning] + * @param {boolean} [no_tojson] * @returns {Snapshot} */ -export function snapshot(value, skip_warning = false) { +export function snapshot(value, skip_warning = false, no_tojson = false) { if (DEV && !skip_warning) { /** @type {string[]} */ const paths = []; - const copy = clone(value, new Map(), '', paths); + const copy = clone(value, new Map(), '', paths, null, no_tojson); if (paths.length === 1 && paths[0] === '') { // value could not be cloned w.state_snapshot_uncloneable(); @@ -40,7 +41,7 @@ export function snapshot(value, skip_warning = false) { return copy; } - return clone(value, new Map(), '', empty); + return clone(value, new Map(), '', empty, null, no_tojson); } /** @@ -49,10 +50,11 @@ export function snapshot(value, skip_warning = false) { * @param {Map>} cloned * @param {string} path * @param {string[]} paths - * @param {null | T} original The original value, if `value` was produced from a `toJSON` call + * @param {null | T} [original] The original value, if `value` was produced from a `toJSON` call + * @param {boolean} [no_tojson] * @returns {Snapshot} */ -function clone(value, cloned, path, paths, original = null) { +function clone(value, cloned, path, paths, original = null, no_tojson = false) { if (typeof value === 'object' && value !== null) { var unwrapped = cloned.get(value); if (unwrapped !== undefined) return unwrapped; @@ -71,7 +73,7 @@ function clone(value, cloned, path, paths, original = null) { for (var i = 0; i < value.length; i += 1) { var element = value[i]; if (i in value) { - copy[i] = clone(element, cloned, DEV ? `${path}[${i}]` : path, paths); + copy[i] = clone(element, cloned, DEV ? `${path}[${i}]` : path, paths, null, no_tojson); } } @@ -88,8 +90,15 @@ function clone(value, cloned, path, paths, original = null) { } for (var key in value) { - // @ts-expect-error - copy[key] = clone(value[key], cloned, DEV ? `${path}.${key}` : path, paths); + copy[key] = clone( + // @ts-expect-error + value[key], + cloned, + DEV ? `${path}.${key}` : path, + paths, + null, + no_tojson + ); } return copy; @@ -99,7 +108,7 @@ function clone(value, cloned, path, paths, original = null) { return /** @type {Snapshot} */ (structuredClone(value)); } - if (typeof (/** @type {T & { toJSON?: any } } */ (value).toJSON) === 'function') { + if (typeof (/** @type {T & { toJSON?: any } } */ (value).toJSON) === 'function' && !no_tojson) { return clone( /** @type {T & { toJSON(): any } } */ (value).toJSON(), cloned,