| 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'); |
| |
| /** 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; |