@jsbits/deep-clone
Version:
Performs a deep cloning of an object own properties and symbols, with loosy or exact behavior.
1 lines • 15.4 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["index.ts"],"sourcesContent":["/// <reference lib=\"es2015\" />\n\ntype CloneFn = <T> (obj: T) => T\ntype GetKeysFn = (obj: any, type: string) => Array<string | symbol>\n\nconst _nodejs = (function () {\n const g = typeof global === 'object' && global\n const m = g && g.process &&\n typeof g.Buffer === 'function' && /^v?(\\d+)/.exec(g.process.version)\n return (m && m[1] as any) | 0\n})()\n\nconst _OP = Object.prototype\nconst _toString = _OP.toString\nconst _ownKeys = typeof Reflect === 'object' &&\n typeof Reflect.ownKeys === 'function' && Reflect.ownKeys\n\n/**\n * Cloning method of various types.\n */\nconst enum ObjType {\n Simple = 1,\n Array,\n ArrayBuffer,\n DataView,\n MapOrSet,\n Error,\n Arguments,\n AsIs,\n}\n\n/**\n * Clonable types with special handlers\n */\nconst clonable: { [k: string]: ObjType } = {\n Date: ObjType.Simple,\n RegExp: ObjType.Simple,\n String: ObjType.Simple,\n Number: ObjType.Simple,\n Boolean: ObjType.Simple,\n Float32Array: ObjType.Simple,\n Float64Array: ObjType.Simple,\n Int8Array: ObjType.Simple,\n Int16Array: ObjType.Simple,\n Int32Array: ObjType.Simple,\n Uint8Array: ObjType.Simple,\n Uint8ClampedArray: ObjType.Simple,\n Uint16Array: ObjType.Simple,\n Uint32Array: ObjType.Simple,\n Array: ObjType.Array,\n ArrayBuffer: ObjType.ArrayBuffer,\n SharedArrayBuffer: ObjType.ArrayBuffer,\n DataView: ObjType.DataView,\n Error: ObjType.Error,\n Map: ObjType.MapOrSet,\n Set: ObjType.MapOrSet,\n Arguments: ObjType.Arguments,\n Atomics: ObjType.AsIs,\n JSON: ObjType.AsIs,\n Math: ObjType.AsIs,\n Promise: ObjType.AsIs,\n WeakMap: ObjType.AsIs,\n WeakSet: ObjType.AsIs,\n XMLHttpRequest: ObjType.AsIs,\n}\n\nconst arrayLike = [\n 'Array',\n 'String',\n 'Float32Array',\n 'Float64Array',\n 'Int8Array',\n 'Int16Array',\n 'Int32Array',\n 'Uint8Array',\n 'Uint8ClampedArray',\n 'Uint16Array',\n 'Uint32Array',\n]\n\n/**\n * Creates a function to get enumerable symbol names of an object.\n *\n * The array is returned as string[] because the lack of full typings\n * for Symbol keys in TS v3\n *\n * @param {boolean} exact All keys?\n * @returns {Function} Extractor\n * @private\n */\nconst getKeyGetter = function (exact: boolean) {\n\n // istanbul ignore next\n const _keys = exact ? Object.getOwnPropertyNames : Object.keys\n const _getSymbols = Object.getOwnPropertySymbols\n\n // istanbul ignore next: until we can test IE11\n if (!_getSymbols) {\n return _keys\n }\n\n // All the keys, including the non-enumerable ones\n // istanbul ignore if: until we can test IE11\n if (exact) {\n return (obj: any) => _keys(obj).concat(_getSymbols(obj) as any)\n }\n\n // Only enumerable keys and symbols\n const _isEnum = _OP.propertyIsEnumerable\n return (obj: any) => {\n const objkeys = _keys(obj) as any[]\n const symbols = _getSymbols(obj)\n\n for (let i = 0; i < symbols.length; i++) {\n if (_isEnum.call(obj, symbols[i])) {\n objkeys.push(symbols[i])\n }\n }\n\n return objkeys as string[]\n }\n}\n\n/**\n * Creates a function to get the properties and symbol names of an object.\n *\n * @param {boolean} exact Include non-enum keys?\n * @returns {Function} Extractor\n * @private\n */\nconst getKeysFac = function (exact: boolean) {\n\n // Avoid creating multiple anonymous functions\n const _filtIdx = (prop: any) => prop !== '0' && (prop | 0) <= 0 && prop !== 'length'\n const _getKeys = exact && _ownKeys || getKeyGetter(exact)\n\n return (obj: {}, type: string) => {\n const objkeys = _getKeys(obj) as Array<string | symbol>\n return ~arrayLike.indexOf(type) ? objkeys.filter(_filtIdx) : objkeys\n }\n}\n\n/**\n * Clone the Map or Set and copy its elements.\n *\n * @param {Map|Set} src Object to copy\n * @param {Function} fn Cloner\n * @param {string} type Type of object\n * @returns {Map|Set} The clone\n * @private\n */\nconst cloneMapOrSet = <T=any> (src: Map<T, T> | Set<T>, fn: CloneFn, type?: string) => {\n const dest = new (src as any).constructor()\n\n // IE11 will not copy items, anyway, we need clone keys and values\n const cb = type === 'Set'\n ? function (this: Set<T>, v: T) { this.add(fn(v)) }\n : function (this: Map<T, T>, v: T, k: T) { this.set(fn(k), fn(v)) }\n\n ;(src as Set<T>).forEach(cb, dest)\n return dest\n}\n\n/**\n * Clone the given DataView object.\n *\n * @param {DataView} src Object to clone\n * @returns {DataView} Clone\n * @private\n */\nconst cloneDataView = (src: DataView) => {\n const buffer = src.buffer.slice(0)\n return new (src as any).constructor(buffer, src.byteOffset, src.byteLength)\n}\n\nconst cloneError = (src: Error) => {\n const err = new (src as any).constructor(src.message)\n return Object.defineProperty(err, 'stack', {\n value: src.stack, configurable: true, writable: true,\n })\n}\n\n/**\n * Copies arguments to an object without prototype - Adds the length property.\n *\n * @param {Arguments} src arguments pseudo-array\n * @returns {object} -\n * @private\n */\nconst cloneArguments = (src: any[]) => {\n const args = Object.create(null)\n return Object.defineProperty(args, 'length', {\n value: src.length, configurable: true, writable: true,\n })\n}\n\n// Faster array cloning\nconst cloneArray = (src: any, fn: CloneFn) => src.map(fn)\n\nconst cloneFn: { [k: number]: (obj: any, fn: CloneFn, _?: string) => any } = {\n [ObjType.AsIs]: (obj: any) => obj,\n [ObjType.Arguments]: cloneArguments,\n [ObjType.Array]: cloneArray,\n [ObjType.ArrayBuffer]: (obj: any) => obj.slice(0),\n [ObjType.DataView]: cloneDataView,\n [ObjType.Error]: cloneError,\n [ObjType.MapOrSet]: cloneMapOrSet,\n}\n\n/**\n * Creates a new object intance of the given type.\n *\n * @param {object} obj Non-null object\n * @param {string} type Object type\n * @param {Function} fn Cloner\n * @returns {object} The new instance\n * @private\n */\nconst createObject = (obj: any, type: string, fn: CloneFn) => {\n const cloneType = clonable[type]\n\n if (cloneType === ObjType.Simple) {\n return obj.slice && _nodejs && Buffer.isBuffer(obj)\n ? obj.slice(0)\n : new obj.constructor(obj.valueOf())\n }\n\n if (cloneFn[cloneType]) {\n return cloneFn[cloneType](obj, fn, type)\n }\n\n return type.lastIndexOf(' Iterator', type.length - 9) > -1\n ? obj : Object.create(Object.getPrototypeOf(obj))\n}\n\n/**\n * Get the object type, taking care about node <6 returning 'Object' for\n * Promise.\n */\nconst getObjectType = (function () {\n\n const _getTag = (obj: object) => _toString.call(obj).slice(8, -1)\n\n // istanbul ignore else\n if (!_nodejs || _nodejs >= 5) {\n return _getTag\n }\n\n // istanbul ignore next\n return (obj: object) => {\n const tag = _getTag(obj)\n return tag === 'Object' && obj.constructor && obj.constructor.name === 'Promise'\n ? 'Promise' : tag\n }\n})()\n\n/**\n * Factory to create a \"clone\" function for loosy or exact mode.\n *\n * @param {Function} getKeys Keys & symbols extractor\n * @returns {Function} Cloner\n * @private\n */\n// codebeat:disable[ABC,BLOCK_NESTING]\nconst cloneFac = function (getKeys: GetKeysFn) {\n\n const _clone = function _clone<T> (obj: any): T { // -eslint-disable-line max-statements\n\n // Filter out null, undefined, NaN, primitive values, and functions\n if (!obj || typeof obj !== 'object') {\n return obj\n }\n\n // The type also allows optimize the getKeys function.\n const type = getObjectType(obj)\n\n // Get a new object of the same type and the properties of the source\n const clone = createObject(obj, type, _clone)\n const props = getKeys(obj, type)\n\n for (let i = 0; i < props.length; i++) {\n const prop = props[i]\n const desc = Object.getOwnPropertyDescriptor(obj, prop)!\n\n // NOTE: `value` must be excluded for setter/getter\n if (desc.value !== undefined) {\n desc.value = _clone((obj as any)[prop])\n }\n\n Object.defineProperty(clone, prop, desc)\n }\n\n return clone\n }\n\n return _clone\n}\n// codebeat:enable[ABC,BLOCK_NESTING]\n\n\n/**\n * Deep clone of enumerable properties.\n *\n * @param {object} obj Any object\n * @returns {object} The clone.\n * @private\n */\nconst looseClone = cloneFac(getKeysFac(false))\n\n/**\n * Deep clone of all the properties, including the non-enumerable ones.\n *\n * @param {object} obj Any object or value\n * @returns {object} The clone.\n * @private\n */\nconst exactClone = cloneFac(getKeysFac(true))\n\n/**\n * Performs a deep cloning of an object own properties and symbols, preserving\n * its prototype.\n *\n * By default `cloneObject` works in \"loosy mode\", where it clones only\n * the object _enumerable_ properties and symbols.\n *\n * To enable the \"exact mode\" and clone all, pass `true` in the second parameter.\n *\n * Both modes retain all the attributes of the copied properties (enumerable,\n * configurable, writable) and correctly transfer the `get` and/or `set`\n * methods, although these, like the other function-type values,\n * _are copied by reference_.\n *\n * Try to limit the usage of this function to POJOs, as this function does not\n * work for objects with constructor that requires parameters (other than\n * the most JS built-in Objects), nor objects with recursive references.\n *\n * @template T\n * @param {T} value Value to clone, mostly an object or array.\n * @param {boolean} [exact=false] If `true`, also clone the non-enumerable properties\n * @returns {T} The cloned object or value.\n * @since 1.0.0\n */\nconst deepClone = function _deepClone<T> (value: T, exact?: boolean): T {\n return exact ? exactClone(value) : looseClone(value)\n}\n\n// Export here so that TS places the JSDdoc in the correct position.\nexport = deepClone\n"],"names":[],"mappings":"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"}