You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					167 lines
				
				5.5 KiB
			
		
		
			
		
	
	
					167 lines
				
				5.5 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								var Stack = require('./_Stack'),
							 | 
						||
| 
								 | 
							
								    arrayEach = require('./_arrayEach'),
							 | 
						||
| 
								 | 
							
								    assignValue = require('./_assignValue'),
							 | 
						||
| 
								 | 
							
								    baseAssign = require('./_baseAssign'),
							 | 
						||
| 
								 | 
							
								    baseAssignIn = require('./_baseAssignIn'),
							 | 
						||
| 
								 | 
							
								    cloneBuffer = require('./_cloneBuffer'),
							 | 
						||
| 
								 | 
							
								    copyArray = require('./_copyArray'),
							 | 
						||
| 
								 | 
							
								    copySymbols = require('./_copySymbols'),
							 | 
						||
| 
								 | 
							
								    copySymbolsIn = require('./_copySymbolsIn'),
							 | 
						||
| 
								 | 
							
								    getAllKeys = require('./_getAllKeys'),
							 | 
						||
| 
								 | 
							
								    getAllKeysIn = require('./_getAllKeysIn'),
							 | 
						||
| 
								 | 
							
								    getTag = require('./_getTag'),
							 | 
						||
| 
								 | 
							
								    initCloneArray = require('./_initCloneArray'),
							 | 
						||
| 
								 | 
							
								    initCloneByTag = require('./_initCloneByTag'),
							 | 
						||
| 
								 | 
							
								    initCloneObject = require('./_initCloneObject'),
							 | 
						||
| 
								 | 
							
								    isArray = require('./isArray'),
							 | 
						||
| 
								 | 
							
								    isBuffer = require('./isBuffer'),
							 | 
						||
| 
								 | 
							
								    isMap = require('./isMap'),
							 | 
						||
| 
								 | 
							
								    isObject = require('./isObject'),
							 | 
						||
| 
								 | 
							
								    isSet = require('./isSet'),
							 | 
						||
| 
								 | 
							
								    keys = require('./keys'),
							 | 
						||
| 
								 | 
							
								    keysIn = require('./keysIn');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Used to compose bitmasks for cloning. */
							 | 
						||
| 
								 | 
							
								var CLONE_DEEP_FLAG = 1,
							 | 
						||
| 
								 | 
							
								    CLONE_FLAT_FLAG = 2,
							 | 
						||
| 
								 | 
							
								    CLONE_SYMBOLS_FLAG = 4;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** `Object#toString` result references. */
							 | 
						||
| 
								 | 
							
								var argsTag = '[object Arguments]',
							 | 
						||
| 
								 | 
							
								    arrayTag = '[object Array]',
							 | 
						||
| 
								 | 
							
								    boolTag = '[object Boolean]',
							 | 
						||
| 
								 | 
							
								    dateTag = '[object Date]',
							 | 
						||
| 
								 | 
							
								    errorTag = '[object Error]',
							 | 
						||
| 
								 | 
							
								    funcTag = '[object Function]',
							 | 
						||
| 
								 | 
							
								    genTag = '[object GeneratorFunction]',
							 | 
						||
| 
								 | 
							
								    mapTag = '[object Map]',
							 | 
						||
| 
								 | 
							
								    numberTag = '[object Number]',
							 | 
						||
| 
								 | 
							
								    objectTag = '[object Object]',
							 | 
						||
| 
								 | 
							
								    regexpTag = '[object RegExp]',
							 | 
						||
| 
								 | 
							
								    setTag = '[object Set]',
							 | 
						||
| 
								 | 
							
								    stringTag = '[object String]',
							 | 
						||
| 
								 | 
							
								    symbolTag = '[object Symbol]',
							 | 
						||
| 
								 | 
							
								    weakMapTag = '[object WeakMap]';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var arrayBufferTag = '[object ArrayBuffer]',
							 | 
						||
| 
								 | 
							
								    dataViewTag = '[object DataView]',
							 | 
						||
| 
								 | 
							
								    float32Tag = '[object Float32Array]',
							 | 
						||
| 
								 | 
							
								    float64Tag = '[object Float64Array]',
							 | 
						||
| 
								 | 
							
								    int8Tag = '[object Int8Array]',
							 | 
						||
| 
								 | 
							
								    int16Tag = '[object Int16Array]',
							 | 
						||
| 
								 | 
							
								    int32Tag = '[object Int32Array]',
							 | 
						||
| 
								 | 
							
								    uint8Tag = '[object Uint8Array]',
							 | 
						||
| 
								 | 
							
								    uint8ClampedTag = '[object Uint8ClampedArray]',
							 | 
						||
| 
								 | 
							
								    uint16Tag = '[object Uint16Array]',
							 | 
						||
| 
								 | 
							
								    uint32Tag = '[object Uint32Array]';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Used to identify `toStringTag` values supported by `_.clone`. */
							 | 
						||
| 
								 | 
							
								var cloneableTags = {};
							 | 
						||
| 
								 | 
							
								cloneableTags[argsTag] = cloneableTags[arrayTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[boolTag] = cloneableTags[dateTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[float32Tag] = cloneableTags[float64Tag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[int8Tag] = cloneableTags[int16Tag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[int32Tag] = cloneableTags[mapTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[numberTag] = cloneableTags[objectTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[regexpTag] = cloneableTags[setTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[stringTag] = cloneableTags[symbolTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
							 | 
						||
| 
								 | 
							
								cloneableTags[errorTag] = cloneableTags[funcTag] =
							 | 
						||
| 
								 | 
							
								cloneableTags[weakMapTag] = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * The base implementation of `_.clone` and `_.cloneDeep` which tracks
							 | 
						||
| 
								 | 
							
								 * traversed objects.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @private
							 | 
						||
| 
								 | 
							
								 * @param {*} value The value to clone.
							 | 
						||
| 
								 | 
							
								 * @param {boolean} bitmask The bitmask flags.
							 | 
						||
| 
								 | 
							
								 *  1 - Deep clone
							 | 
						||
| 
								 | 
							
								 *  2 - Flatten inherited properties
							 | 
						||
| 
								 | 
							
								 *  4 - Clone symbols
							 | 
						||
| 
								 | 
							
								 * @param {Function} [customizer] The function to customize cloning.
							 | 
						||
| 
								 | 
							
								 * @param {string} [key] The key of `value`.
							 | 
						||
| 
								 | 
							
								 * @param {Object} [object] The parent object of `value`.
							 | 
						||
| 
								 | 
							
								 * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
							 | 
						||
| 
								 | 
							
								 * @returns {*} Returns the cloned value.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								function baseClone(value, bitmask, customizer, key, object, stack) {
							 | 
						||
| 
								 | 
							
								  var result,
							 | 
						||
| 
								 | 
							
								      isDeep = bitmask & CLONE_DEEP_FLAG,
							 | 
						||
| 
								 | 
							
								      isFlat = bitmask & CLONE_FLAT_FLAG,
							 | 
						||
| 
								 | 
							
								      isFull = bitmask & CLONE_SYMBOLS_FLAG;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (customizer) {
							 | 
						||
| 
								 | 
							
								    result = object ? customizer(value, key, object, stack) : customizer(value);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (result !== undefined) {
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (!isObject(value)) {
							 | 
						||
| 
								 | 
							
								    return value;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  var isArr = isArray(value);
							 | 
						||
| 
								 | 
							
								  if (isArr) {
							 | 
						||
| 
								 | 
							
								    result = initCloneArray(value);
							 | 
						||
| 
								 | 
							
								    if (!isDeep) {
							 | 
						||
| 
								 | 
							
								      return copyArray(value, result);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    var tag = getTag(value),
							 | 
						||
| 
								 | 
							
								        isFunc = tag == funcTag || tag == genTag;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (isBuffer(value)) {
							 | 
						||
| 
								 | 
							
								      return cloneBuffer(value, isDeep);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
							 | 
						||
| 
								 | 
							
								      result = (isFlat || isFunc) ? {} : initCloneObject(value);
							 | 
						||
| 
								 | 
							
								      if (!isDeep) {
							 | 
						||
| 
								 | 
							
								        return isFlat
							 | 
						||
| 
								 | 
							
								          ? copySymbolsIn(value, baseAssignIn(result, value))
							 | 
						||
| 
								 | 
							
								          : copySymbols(value, baseAssign(result, value));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      if (!cloneableTags[tag]) {
							 | 
						||
| 
								 | 
							
								        return object ? value : {};
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      result = initCloneByTag(value, tag, isDeep);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  // Check for circular references and return its corresponding clone.
							 | 
						||
| 
								 | 
							
								  stack || (stack = new Stack);
							 | 
						||
| 
								 | 
							
								  var stacked = stack.get(value);
							 | 
						||
| 
								 | 
							
								  if (stacked) {
							 | 
						||
| 
								 | 
							
								    return stacked;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  stack.set(value, result);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (isSet(value)) {
							 | 
						||
| 
								 | 
							
								    value.forEach(function(subValue) {
							 | 
						||
| 
								 | 
							
								      result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else if (isMap(value)) {
							 | 
						||
| 
								 | 
							
								    value.forEach(function(subValue, key) {
							 | 
						||
| 
								 | 
							
								      result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var keysFunc = isFull
							 | 
						||
| 
								 | 
							
								    ? (isFlat ? getAllKeysIn : getAllKeys)
							 | 
						||
| 
								 | 
							
								    : (isFlat ? keysIn : keys);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var props = isArr ? undefined : keysFunc(value);
							 | 
						||
| 
								 | 
							
								  arrayEach(props || value, function(subValue, key) {
							 | 
						||
| 
								 | 
							
								    if (props) {
							 | 
						||
| 
								 | 
							
								      key = subValue;
							 | 
						||
| 
								 | 
							
								      subValue = value[key];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    // Recursively populate clone (susceptible to call stack limits).
							 | 
						||
| 
								 | 
							
								    assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = baseClone;
							 |