167 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import Stack from './_Stack.js';
 | |
| import arrayEach from './_arrayEach.js';
 | |
| import assignValue from './_assignValue.js';
 | |
| import baseAssign from './_baseAssign.js';
 | |
| import baseAssignIn from './_baseAssignIn.js';
 | |
| import cloneBuffer from './_cloneBuffer.js';
 | |
| import copyArray from './_copyArray.js';
 | |
| import copySymbols from './_copySymbols.js';
 | |
| import copySymbolsIn from './_copySymbolsIn.js';
 | |
| import getAllKeys from './_getAllKeys.js';
 | |
| import getAllKeysIn from './_getAllKeysIn.js';
 | |
| import getTag from './_getTag.js';
 | |
| import initCloneArray from './_initCloneArray.js';
 | |
| import initCloneByTag from './_initCloneByTag.js';
 | |
| import initCloneObject from './_initCloneObject.js';
 | |
| import isArray from './isArray.js';
 | |
| import isBuffer from './isBuffer.js';
 | |
| import isMap from './isMap.js';
 | |
| import isObject from './isObject.js';
 | |
| import isSet from './isSet.js';
 | |
| import keys from './keys.js';
 | |
| import keysIn from './keysIn.js';
 | |
| 
 | |
| /** 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;
 | |
| }
 | |
| 
 | |
| export default baseClone;
 |