pull/14599/head
ComputerGuy 2 years ago
parent 4b802dbed3
commit 240997244f

@ -1,7 +1,14 @@
/** @import { Snapshot } from './types' */
import { DEV } from 'esm-env';
import { STATE_SYMBOL } from '../client/constants.js';
import * as w from './warnings.js';
import { get_prototype_of, is_array, object_prototype } from './utils.js';
import {
get_prototype_of,
is_array,
object_prototype,
structured_clone,
is_object
} from './utils.js';
/**
* In dev, we keep track of which properties could not be cloned. In prod
@ -93,7 +100,7 @@ function clone(value, cloned, path, paths, original = null) {
}
if (value instanceof Date) {
return /** @type {Snapshot<T>} */ (structuredClone(value));
return /** @type {Snapshot<T>} */ (structured_clone(value));
}
if (typeof (/** @type {T & { toJSON?: any } } */ (value).toJSON) === 'function') {
@ -114,7 +121,7 @@ function clone(value, cloned, path, paths, original = null) {
}
try {
return /** @type {Snapshot<T>} */ (structuredClone(value));
return /** @type {Snapshot<T>} */ (structured_clone(value));
} catch (e) {
if (DEV) {
paths.push(path);
@ -123,3 +130,40 @@ function clone(value, cloned, path, paths, original = null) {
return /** @type {Snapshot<T>} */ (value);
}
}
// Patches `structuredClone` to work with `$state` proxies
if (DEV) {
/**
* Creates a deep clone of an object.
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/structuredClone)
* @template T
* @param {T} value
* @param {StructuredSerializeOptions} options
* @returns {T}
*/
//@ts-expect-error
globalThis.structuredClone = function structuredClone(value, options) {
/**
* @param {any[]} keys
* @param {object} object
* @returns {boolean}
*/
function in_object(keys, object) {
let result = true;
for (let key of keys) {
result &&= key in object;
}
return result;
}
// the `transfer` property in options can't really be patched easily, so the original structuredClone is used
if (is_object(options) && 'transfer' in options && is_object(value)) {
//@ts-expect-error
if (in_object(['f', 'v', 'equals', 'reactions', 'version'], value) || STATE_SYMBOL in value) // not quite sure if the first condition is necessary
//@ts-expect-error
value = snapshot(value);
return structured_clone(value, options);
}
//@ts-expect-error
return snapshot(value);
};
}

@ -9,6 +9,7 @@ export var get_descriptors = Object.getOwnPropertyDescriptors;
export var object_prototype = Object.prototype;
export var array_prototype = Array.prototype;
export var get_prototype_of = Object.getPrototypeOf;
export var structured_clone = structuredClone;
/**
* @param {any} thing
@ -58,3 +59,12 @@ export function fallback(value, fallback, lazy = false) {
: /** @type {V} */ (fallback)
: value;
}
/**
* Returns true if the value is an object that is not null
* @param {any} value
* @returns {boolean}
*/
export function is_object(value) {
return typeof value === "object" && value !== null;
}
Loading…
Cancel
Save