@n3okill/utils
Version:
Many javascript helpers
152 lines • 7.07 kB
JavaScript
;
/* 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