UNPKG

froebel

Version:
37 lines (30 loc) 1.29 kB
/** * Returns a copied version of `value`. * * If `value` is primitive, returns `value`. * Otherwise, properties of `value` are copied recursively. Only `value`'s own * enumerable properties are cloned. Arrays are cloned by mapping over their * elements. * * If a path in `value` references itself or a parent path, then in the * resulting object that path will also reference the path it referenced in the * original object (but now in the resuling object instead of the original). */ const clone = globalThis.structuredClone ?? cloneFallback; export default clone; function cloneFallback(value) { const map = new Map(); const replacers = []; const cloned = _clone(value, map, replacers, undefined); for (const f of replacers) f(); return cloned; } function _clone(v, visited, replacers, replace) { if (typeof v !== "object" || v === null) return v; if (visited.has(v)) return replace(v); visited.set(v, 0); const cloneNext = (v, r) => _clone(v, visited, replacers, v => replacers.push(() => r(v))); const cloned = Array.isArray(v) ? v.map((e, i) => cloneNext(e, v => cloned[i] = visited.get(v))) : Object.fromEntries(Object.entries(v).map(([k, e]) => [k, cloneNext(e, v => cloned[k] = visited.get(v))])); visited.set(v, cloned); return cloned; }