| | |
| | | /* eslint-disable */
|
| | | var clone = (function() {
|
| | | 'use strict';
|
| | |
|
| | | function _instanceof(obj, type) {
|
| | | return type != null && obj instanceof type;
|
| | | }
|
| | |
|
| | | var nativeMap;
|
| | | try {
|
| | | nativeMap = Map;
|
| | | } catch(_) {
|
| | | // maybe a reference error because no `Map`. Give it a dummy value that no
|
| | | // value will ever be an instanceof.
|
| | | nativeMap = function() {};
|
| | | }
|
| | |
|
| | | var nativeSet;
|
| | | try {
|
| | | nativeSet = Set;
|
| | | } catch(_) {
|
| | | nativeSet = function() {};
|
| | | }
|
| | |
|
| | | var nativePromise;
|
| | | try {
|
| | | nativePromise = Promise;
|
| | | } catch(_) {
|
| | | nativePromise = function() {};
|
| | | }
|
| | |
|
| | | /**
|
| | | * 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 clone(obj, false).
|
| | | *
|
| | | * Caution: if `circular` is false and `parent` contains circular references,
|
| | | * your program may enter an infinite loop and crash.
|
| | | *
|
| | | * @param `parent` - the object to be cloned
|
| | | * @param `circular` - set to true if the object to be cloned may contain
|
| | | * circular references. (optional - true by default)
|
| | | * @param `depth` - set to a number if the object is only to be cloned to
|
| | | * a particular depth. (optional - defaults to Infinity)
|
| | | * @param `prototype` - sets the prototype to be used when cloning an object.
|
| | | * (optional - defaults to parent prototype).
|
| | | * @param `includeNonEnumerable` - set to true if the non-enumerable properties
|
| | | * should be cloned as well. Non-enumerable properties on the prototype
|
| | | * chain will be ignored. (optional - false by default)
|
| | | */
|
| | | function clone(parent, circular, depth, prototype, includeNonEnumerable) {
|
| | | if (typeof circular === 'object') {
|
| | | depth = circular.depth;
|
| | | prototype = circular.prototype;
|
| | | includeNonEnumerable = circular.includeNonEnumerable;
|
| | | circular = circular.circular;
|
| | | }
|
| | | // maintain two arrays for circular references, where corresponding parents
|
| | | // and children have the same index
|
| | | var allParents = [];
|
| | | var allChildren = [];
|
| | |
|
| | | var useBuffer = typeof Buffer != 'undefined';
|
| | |
|
| | | if (typeof circular == 'undefined')
|
| | | circular = true;
|
| | |
|
| | | if (typeof depth == 'undefined')
|
| | | depth = Infinity;
|
| | |
|
| | | // recurse this function so we don't reset allParents and allChildren
|
| | | function _clone(parent, depth) {
|
| | | // cloning null always returns null
|
| | | if (parent === null)
|
| | | return null;
|
| | |
|
| | | if (depth === 0)
|
| | | return parent;
|
| | |
|
| | | var child;
|
| | | var proto;
|
| | | if (typeof parent != 'object') {
|
| | | return parent;
|
| | | }
|
| | |
|
| | | if (_instanceof(parent, nativeMap)) {
|
| | | child = new nativeMap();
|
| | | } else if (_instanceof(parent, nativeSet)) {
|
| | | child = new nativeSet();
|
| | | } else if (_instanceof(parent, nativePromise)) {
|
| | | child = new nativePromise(function (resolve, reject) {
|
| | | parent.then(function(value) {
|
| | | resolve(_clone(value, depth - 1));
|
| | | }, function(err) {
|
| | | reject(_clone(err, depth - 1));
|
| | | });
|
| | | });
|
| | | } else if (clone.__isArray(parent)) {
|
| | | child = [];
|
| | | } else if (clone.__isRegExp(parent)) {
|
| | | child = new RegExp(parent.source, __getRegExpFlags(parent));
|
| | | if (parent.lastIndex) child.lastIndex = parent.lastIndex;
|
| | | } else if (clone.__isDate(parent)) {
|
| | | child = new Date(parent.getTime());
|
| | | } else if (useBuffer && Buffer.isBuffer(parent)) {
|
| | | if (Buffer.from) {
|
| | | // Node.js >= 5.10.0
|
| | | child = Buffer.from(parent);
|
| | | } else {
|
| | | // Older Node.js versions
|
| | | child = new Buffer(parent.length);
|
| | | parent.copy(child);
|
| | | }
|
| | | return child;
|
| | | } else if (_instanceof(parent, Error)) {
|
| | | child = Object.create(parent);
|
| | | } else {
|
| | | if (typeof prototype == 'undefined') {
|
| | | proto = Object.getPrototypeOf(parent);
|
| | | child = Object.create(proto);
|
| | | }
|
| | | else {
|
| | | child = Object.create(prototype);
|
| | | proto = prototype;
|
| | | }
|
| | | }
|
| | |
|
| | | if (circular) {
|
| | | var index = allParents.indexOf(parent);
|
| | |
|
| | | if (index != -1) {
|
| | | return allChildren[index];
|
| | | }
|
| | | allParents.push(parent);
|
| | | allChildren.push(child);
|
| | | }
|
| | |
|
| | | if (_instanceof(parent, nativeMap)) {
|
| | | parent.forEach(function(value, key) {
|
| | | var keyChild = _clone(key, depth - 1);
|
| | | var valueChild = _clone(value, depth - 1);
|
| | | child.set(keyChild, valueChild);
|
| | | });
|
| | | }
|
| | | if (_instanceof(parent, nativeSet)) {
|
| | | parent.forEach(function(value) {
|
| | | var entryChild = _clone(value, depth - 1);
|
| | | child.add(entryChild);
|
| | | });
|
| | | }
|
| | |
|
| | | for (var i in parent) {
|
| | | var attrs = Object.getOwnPropertyDescriptor(parent, i);
|
| | | if (attrs) {
|
| | | child[i] = _clone(parent[i], depth - 1);
|
| | | }
|
| | |
|
| | | try {
|
| | | var objProperty = Object.getOwnPropertyDescriptor(parent, i);
|
| | | if (objProperty.set === 'undefined') {
|
| | | // no setter defined. Skip cloning this property
|
| | | continue;
|
| | | }
|
| | | child[i] = _clone(parent[i], depth - 1);
|
| | | } catch(e){
|
| | | if (e instanceof TypeError) {
|
| | | // when in strict mode, TypeError will be thrown if child[i] property only has a getter
|
| | | // we can't do anything about this, other than inform the user that this property cannot be set.
|
| | | continue
|
| | | } else if (e instanceof ReferenceError) {
|
| | | //this may happen in non strict mode
|
| | | continue
|
| | | }
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | if (Object.getOwnPropertySymbols) {
|
| | | var symbols = Object.getOwnPropertySymbols(parent);
|
| | | for (var i = 0; i < symbols.length; i++) {
|
| | | // Don't need to worry about cloning a symbol because it is a primitive,
|
| | | // like a number or string.
|
| | | var symbol = symbols[i];
|
| | | var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
|
| | | if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
|
| | | continue;
|
| | | }
|
| | | child[symbol] = _clone(parent[symbol], depth - 1);
|
| | | Object.defineProperty(child, symbol, descriptor);
|
| | | }
|
| | | }
|
| | |
|
| | | if (includeNonEnumerable) {
|
| | | var allPropertyNames = Object.getOwnPropertyNames(parent);
|
| | | for (var i = 0; i < allPropertyNames.length; i++) {
|
| | | var propertyName = allPropertyNames[i];
|
| | | var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
|
| | | if (descriptor && descriptor.enumerable) {
|
| | | continue;
|
| | | }
|
| | | child[propertyName] = _clone(parent[propertyName], depth - 1);
|
| | | Object.defineProperty(child, propertyName, descriptor);
|
| | | }
|
| | | }
|
| | |
|
| | | return child;
|
| | | }
|
| | |
|
| | | return _clone(parent, depth);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Simple flat clone using prototype, accepts only objects, usefull for property
|
| | | * override on FLAT configuration object (no nested props).
|
| | | *
|
| | | * USE WITH CAUTION! This may not behave as you wish if you do not know how this
|
| | | * works.
|
| | | */
|
| | | clone.clonePrototype = function clonePrototype(parent) {
|
| | | if (parent === null)
|
| | | return null;
|
| | |
|
| | | var c = function () {};
|
| | | c.prototype = parent;
|
| | | return new c();
|
| | | };
|
| | |
|
| | | // private utility functions
|
| | |
|
| | | function __objToStr(o) {
|
| | | return Object.prototype.toString.call(o);
|
| | | }
|
| | | clone.__objToStr = __objToStr;
|
| | |
|
| | | function __isDate(o) {
|
| | | return typeof o === 'object' && __objToStr(o) === '[object Date]';
|
| | | }
|
| | | clone.__isDate = __isDate;
|
| | |
|
| | | function __isArray(o) {
|
| | | return typeof o === 'object' && __objToStr(o) === '[object Array]';
|
| | | }
|
| | | clone.__isArray = __isArray;
|
| | |
|
| | | function __isRegExp(o) {
|
| | | return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
|
| | | }
|
| | | clone.__isRegExp = __isRegExp;
|
| | |
|
| | | function __getRegExpFlags(re) {
|
| | | var flags = '';
|
| | | if (re.global) flags += 'g';
|
| | | if (re.ignoreCase) flags += 'i';
|
| | | if (re.multiline) flags += 'm';
|
| | | return flags;
|
| | | }
|
| | | clone.__getRegExpFlags = __getRegExpFlags;
|
| | |
|
| | | return clone;
|
| | | })();
|
| | |
|
| | | export default clone
|