UNPKG

xtutils

Version:

Thuku's assorted general purpose typescript/javascript library.

177 lines 6.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports._cloneDeep = exports.clonePrototype = void 0; const Buffer_1 = require("../Buffer"); /** * Clone utils */ const _instanceof = (o, type) => 'object' === typeof type && type && o instanceof type; const _toString = (o) => Object.prototype.toString.call(o); const _isDate = (o) => 'object' === typeof o && _toString(o) === '[object Date]'; const _isArray = (o) => typeof o === 'object' && _toString(o) === '[object Array]'; const _isRegExp = (o) => typeof o === 'object' && _toString(o) === '[object RegExp]'; const _getRegExpFlags = (regex) => { let flags = ''; if (regex?.global) flags += 'g'; if (regex?.ignoreCase) flags += 'i'; if (regex?.multiline) flags += 'm'; return flags; }; /** * Clone prototype * * @param parent */ const clonePrototype = (parent) => { if (parent === null || parent === undefined) return parent; if ('object' !== typeof parent) parent = Object.getPrototypeOf(parent); const fn = function () { }; fn.prototype = parent; return new fn(); }; exports.clonePrototype = clonePrototype; ; /** * Clones (copies) an Object using deep copying. * * - This function supports circular references by default, but if you are certain * there are no circular references in your object, you can save some CPU time * by calling with option `circular` = `false`. * * - CAUTION: if option `circular` is `false` and `value` contains circular references, * your program may enter an infinite loop and crash. * * @param value Clone subject `<T>` * @param options Clone options * @returns `<T>` clone */ function _cloneDeep(value, options) { const { circular: _circular = true, depth: _depth = Infinity, prototype: _prototype = undefined, non_enumerable: _non_enumerable = false, } = Object(options); const circular = 'undefined' === typeof _circular ? true : Boolean(_circular); const depth = !isNaN(_depth) && Number.isInteger(_depth) && _depth > 0 ? _depth : Infinity; const prototype = _prototype; const non_enumerable = Boolean(_non_enumerable); const allParents = []; const allChildren = []; const useBuffer = 'undefined' !== typeof Buffer_1.Buffer; //clone const _clone = (parent, depth) => { if (depth === 0 || !('object' === typeof parent && parent)) return parent; let child, proto; if (_instanceof(parent, Map)) child = new Map(); else if (_instanceof(parent, Set)) child = new Set(); else if (_instanceof(parent, Promise)) { child = new Promise((resolve, reject) => { parent.then((res) => resolve(_clone(res, depth - 1))) .catch((err) => reject(_clone(err, depth - 1))); }); } else if (_isArray(parent)) child = []; else if (_isRegExp(parent)) { child = new RegExp(parent.source, _getRegExpFlags(parent)); if (parent.lastIndex) child.lastIndex = parent.lastIndex; } else if (_isDate(parent)) child = new Date(parent.getTime()); else if (useBuffer && Buffer_1.Buffer.isBuffer(parent)) { if (Buffer_1.Buffer.from) child = Buffer_1.Buffer.from(parent); //Node.js >= 5.10.0 else { child = new Buffer_1.Buffer(parent.length); //Older Node.js versions parent.copy(child); } return child; } else if (_instanceof(parent, Error)) child = Object.create(parent); else { if ('object' !== typeof prototype) { proto = Object.getPrototypeOf(parent); child = Object.create(proto); } else { child = Object.create(prototype); proto = prototype; } } if (circular) { const index = allParents.indexOf(parent); if (index !== -1) return allChildren[index]; allParents.push(parent); allChildren.push(child); } if (_instanceof(parent, Map)) { for (const [key, val] of parent) { const keyChild = _clone(key, depth - 1); const valChild = _clone(val, depth - 1); child.set(keyChild, valChild); } } if (_instanceof(parent, Set)) { for (const val of parent) { const valChild = _clone(val, depth - 1); child.add(valChild); } } for (let key in parent) { const attrs = Object.getOwnPropertyDescriptor(parent, key); if (attrs) child[key] = _clone(parent[key], depth - 1); try { const objProperty = Object.getOwnPropertyDescriptor(parent, key); if (objProperty?.set === undefined) continue; child[key] = _clone(parent[key], depth - 1); if (objProperty) Object.defineProperty(child, key, objProperty); } catch (e) { if (e instanceof TypeError) continue; //child[key] only has getter (strict mode) else if (e instanceof ReferenceError) continue; //same as above (non strict mode) } } if (Object.getOwnPropertySymbols) { const symbols = Object.getOwnPropertySymbols(parent); for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; //primitive const descriptor = Object.getOwnPropertyDescriptor(parent, symbol); if (descriptor && !descriptor.enumerable && !non_enumerable) continue; child[symbol] = _clone(parent[symbol], depth - 1); if (descriptor) Object.defineProperty(child, symbol, descriptor); } } if (non_enumerable) { const allPropertyNames = Object.getOwnPropertyNames(parent); for (let i = 0; i < allPropertyNames.length; i++) { const propertyName = allPropertyNames[i]; const descriptor = Object.getOwnPropertyDescriptor(parent, propertyName); if (descriptor && descriptor.enumerable) continue; child[propertyName] = _clone(parent[propertyName], depth - 1); if (descriptor) Object.defineProperty(child, propertyName, descriptor); } } return child; }; //result return _clone(value, depth); } exports._cloneDeep = _cloneDeep; ; //# sourceMappingURL=_cloneDeep.js.map