UNPKG

@n3okill/utils

Version:
152 lines 7.07 kB
"use strict"; /* global NodeJS */ Object.defineProperty(exports, "__esModule", { value: true }); exports.clone = clone; const _internal_1 = require("../_internal"); const cloneBuffer_1 = require("../other/cloneBuffer"); const cloneDate_1 = require("../other/cloneDate"); const cloneError_1 = require("../other/cloneError"); const clonePrimitive_1 = require("../other/clonePrimitive"); const cloneRegExp_1 = require("../other/cloneRegExp"); const cloneSymbol_1 = require("../other/cloneSymbol"); const cloneTypedArray_1 = require("../other/cloneTypedArray"); const _types_1 = require("../type/_types"); const getEnumType_1 = require("../type/getEnumType"); const isArray_1 = require("../type/isArray"); const isMap_1 = require("../type/isMap"); const isObject_1 = require("../type/isObject"); const isPlainObject_1 = require("../type/isPlainObject"); const isSet_1 = require("../type/isSet"); /** * Clone any argument type * @param arg The argument to clone * @param deep If true will deep clone values in multiple argument types * @returns New cloned object */ function clone(source, deep = false, transform) { const parentStack = []; const parentCloned = []; const _clone = (_source) => { let target; const parentIndex = parentStack.indexOf(_source); if (parentIndex !== -1) { // eslint-disable-next-line security/detect-object-injection return parentCloned[parentIndex]; } switch ((0, getEnumType_1.getEnumType)(_source)) { case _types_1.EnumTypes.Array: target = new (_source.constructor || Array)(_source.length); break; case _types_1.EnumTypes.Map: target = new (_source.constructor || Map)(); break; case _types_1.EnumTypes.Set: target = new (_source.constructor || Set)(); break; case _types_1.EnumTypes.Promise: target = new _source.constructor( // eslint-disable-next-line @typescript-eslint/no-explicit-any (resolve, reject) => { _source.then((value) => resolve((0, _internal_1._checkTransform)(_clone(value), transform)), (err) => reject((0, _internal_1._checkTransform)(_clone(err), transform))); }); break; case _types_1.EnumTypes.Object: case _types_1.EnumTypes.PlainObject: if ((0, isPlainObject_1.isPlainObject)(_source) || !("constructor" in _source)) { target = {}; } else { target = new _source.constructor(); } break; case _types_1.EnumTypes.Buffer: return (0, cloneBuffer_1.cloneBuffer)(_source, transform); case _types_1.EnumTypes.Date: return (0, cloneDate_1.cloneDate)(_source, transform); case _types_1.EnumTypes.Error: target = (0, cloneError_1.cloneError)(_source, transform); break; case _types_1.EnumTypes.RegExp: return (0, cloneRegExp_1.cloneRegExp)(_source, transform); case _types_1.EnumTypes.TypedArray: return (0, cloneTypedArray_1.cloneTypedArray)(_source, transform); case _types_1.EnumTypes.Function: case _types_1.EnumTypes.AsyncFunction: return _source.bind(null); case _types_1.EnumTypes.Symbol: return (0, cloneSymbol_1.cloneSymbol)(_source, transform); case _types_1.EnumTypes.Boolean: case _types_1.EnumTypes.Number: case _types_1.EnumTypes.String: return (0, clonePrimitive_1.clonePrimitive)(_source, transform); case _types_1.EnumTypes.Null: case _types_1.EnumTypes.Undefined: return _source; } parentStack.push(_source); parentCloned.push(target); if ((0, isArray_1.isArray)(_source)) { let length = _source.length; while (length--) { // eslint-disable-next-line security/detect-object-injection target[length] = (0, _internal_1._checkTransform)( // eslint-disable-next-line security/detect-object-injection deep ? _clone(_source[length]) : _source[length], transform, length); } } else if ((0, isMap_1.isMap)(_source)) { for (const [key, value] of _source.entries()) { target.set(key, (0, _internal_1._checkTransform)(deep ? _clone(value) : value, transform, key)); } } else if ((0, isSet_1.isSet)(_source)) { for (const val of _source.values()) { target.add((0, _internal_1._checkTransform)(deep ? _clone(val) : val, transform)); } } const cloneDescriptor = (original, name, cloneObj) => { if (!(name in cloneObj) || cloneObj[name] !== original[name]) { const descriptor = Object.getOwnPropertyDescriptor(original, name); const desc = {}; desc.writable = descriptor.writable === true; desc.configurable = descriptor.configurable === true; desc.enumerable = descriptor.enumerable === true; if (descriptor.set) { // eslint-disable-next-line @typescript-eslint/unbound-method desc.set = (deep ? _clone(descriptor.set) : descriptor.set); delete desc.writable; } if (descriptor.get) { // eslint-disable-next-line @typescript-eslint/unbound-method desc.get = (deep ? _clone(descriptor.get) : descriptor.get); delete desc.writable; } else { desc.value = (deep ? (0, _internal_1._checkTransform)(_clone(descriptor.value), transform, name) : descriptor.value); } try { Object.defineProperty(cloneObj, name, desc); // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (err) { throw new Error(`Error defining descriptor for '${name}'`); } } }; const ownPropertyNames = Object.getOwnPropertyNames(_source); for (const name of ownPropertyNames) { cloneDescriptor(_source, name, target); } const ownPropertySymbols = Object.getOwnPropertySymbols(_source); for (const symbol of ownPropertySymbols) { cloneDescriptor(_source, symbol, target); } if ((0, isObject_1.isObject)(_source) || (0, isPlainObject_1.isPlainObject)(_source)) { target = (0, _internal_1._checkTransform)(target, transform); } return target; }; return _clone(source); } //# sourceMappingURL=clone.js.map