UNPKG

@feugene/mu

Version:

Helpful TS utilities without dependencies

79 lines 2.78 kB
import isDate from '../is/isDate.mjs'; // Helpers function isPlainObject(val) { if (val === null || typeof val !== 'object') return false; const proto = Object.getPrototypeOf(val); return proto === Object.prototype || proto === null; } function ownEnumerableKeys(obj) { const keys = Object.keys(obj); const symbols = Object.getOwnPropertySymbols(obj).filter(sym => { const desc = Object.getOwnPropertyDescriptor(obj, sym); return !!desc?.enumerable; }); return keys.concat(symbols); } /** * Deep clone with Node 22 strategy. * - Plain objects and arrays: recursively clone over own enumerable string and symbol keys only. * - Date: cloned by value via new Date(time). * - DOM nodes (when cloneDom=true): uses node.cloneNode(true). * - Other objects (Map, Set, RegExp, TypedArrays, ArrayBuffer, URL, etc.): * attempted via structuredClone; on failure, return original reference. * - Functions/classes/instances with custom prototypes: returned as-is (by reference). * * Limitations: * - Accessors/descriptors are not preserved; enumerable data properties only for plain objects. * - Prototypes for plain objects are normalized to Object.prototype (or null if origin had null-proto). */ export default function clone(item, cloneDom = true) { // Nullish or primitive if (item == null || (typeof item !== 'object' && typeof item !== 'function')) { return item; } // DOM Node clone (duck-typed) // @ts-ignore if (cloneDom && item.nodeType && typeof item.cloneNode === 'function') { // @ts-ignore return item.cloneNode(true); } // Date if (isDate(item)) { // @ts-ignore return new Date(item.getTime()); } // Array if (Array.isArray(item)) { const src = item; const out = new Array(src.length); for (let i = 0; i < src.length; i++) { out[i] = clone(src[i], cloneDom); } return out; } // Plain Object if (isPlainObject(item)) { const src = item; const out = Object.create(Object.getPrototypeOf(src)); for (const key of ownEnumerableKeys(src)) { out[key] = clone(src[key], cloneDom); } return out; } // For other complex objects (Map, Set, RegExp, TypedArrays, etc.) // try structuredClone if available; fall back to reference if it throws. try { // @ts-ignore Node 22 global if (typeof structuredClone === 'function') { // @ts-ignore return structuredClone(item); } } catch (_) { // fallthrough to return original item } // As-is for functions/classes and unsupported cases return item; } //# sourceMappingURL=clone.mjs.map