00001 var Stack = require('./_Stack'),
00002 arrayEach = require('./_arrayEach'),
00003 assignValue = require('./_assignValue'),
00004 baseAssign = require('./_baseAssign'),
00005 baseAssignIn = require('./_baseAssignIn'),
00006 cloneBuffer = require('./_cloneBuffer'),
00007 copyArray = require('./_copyArray'),
00008 copySymbols = require('./_copySymbols'),
00009 copySymbolsIn = require('./_copySymbolsIn'),
00010 getAllKeys = require('./_getAllKeys'),
00011 getAllKeysIn = require('./_getAllKeysIn'),
00012 getTag = require('./_getTag'),
00013 initCloneArray = require('./_initCloneArray'),
00014 initCloneByTag = require('./_initCloneByTag'),
00015 initCloneObject = require('./_initCloneObject'),
00016 isArray = require('./isArray'),
00017 isBuffer = require('./isBuffer'),
00018 isObject = require('./isObject'),
00019 keys = require('./keys');
00020
00022 var CLONE_DEEP_FLAG = 1,
00023 CLONE_FLAT_FLAG = 2,
00024 CLONE_SYMBOLS_FLAG = 4;
00025
00027 var argsTag = '[object Arguments]',
00028 arrayTag = '[object Array]',
00029 boolTag = '[object Boolean]',
00030 dateTag = '[object Date]',
00031 errorTag = '[object Error]',
00032 funcTag = '[object Function]',
00033 genTag = '[object GeneratorFunction]',
00034 mapTag = '[object Map]',
00035 numberTag = '[object Number]',
00036 objectTag = '[object Object]',
00037 regexpTag = '[object RegExp]',
00038 setTag = '[object Set]',
00039 stringTag = '[object String]',
00040 symbolTag = '[object Symbol]',
00041 weakMapTag = '[object WeakMap]';
00042
00043 var arrayBufferTag = '[object ArrayBuffer]',
00044 dataViewTag = '[object DataView]',
00045 float32Tag = '[object Float32Array]',
00046 float64Tag = '[object Float64Array]',
00047 int8Tag = '[object Int8Array]',
00048 int16Tag = '[object Int16Array]',
00049 int32Tag = '[object Int32Array]',
00050 uint8Tag = '[object Uint8Array]',
00051 uint8ClampedTag = '[object Uint8ClampedArray]',
00052 uint16Tag = '[object Uint16Array]',
00053 uint32Tag = '[object Uint32Array]';
00054
00056 var cloneableTags = {};
00057 cloneableTags[argsTag] = cloneableTags[arrayTag] =
00058 cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
00059 cloneableTags[boolTag] = cloneableTags[dateTag] =
00060 cloneableTags[float32Tag] = cloneableTags[float64Tag] =
00061 cloneableTags[int8Tag] = cloneableTags[int16Tag] =
00062 cloneableTags[int32Tag] = cloneableTags[mapTag] =
00063 cloneableTags[numberTag] = cloneableTags[objectTag] =
00064 cloneableTags[regexpTag] = cloneableTags[setTag] =
00065 cloneableTags[stringTag] = cloneableTags[symbolTag] =
00066 cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
00067 cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
00068 cloneableTags[errorTag] = cloneableTags[funcTag] =
00069 cloneableTags[weakMapTag] = false;
00070
00087 function baseClone(value, bitmask, customizer, key, object, stack) {
00088 var result,
00089 isDeep = bitmask & CLONE_DEEP_FLAG,
00090 isFlat = bitmask & CLONE_FLAT_FLAG,
00091 isFull = bitmask & CLONE_SYMBOLS_FLAG;
00092
00093 if (customizer) {
00094 result = object ? customizer(value, key, object, stack) : customizer(value);
00095 }
00096 if (result !== undefined) {
00097 return result;
00098 }
00099 if (!isObject(value)) {
00100 return value;
00101 }
00102 var isArr = isArray(value);
00103 if (isArr) {
00104 result = initCloneArray(value);
00105 if (!isDeep) {
00106 return copyArray(value, result);
00107 }
00108 } else {
00109 var tag = getTag(value),
00110 isFunc = tag == funcTag || tag == genTag;
00111
00112 if (isBuffer(value)) {
00113 return cloneBuffer(value, isDeep);
00114 }
00115 if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
00116 result = (isFlat || isFunc) ? {} : initCloneObject(value);
00117 if (!isDeep) {
00118 return isFlat
00119 ? copySymbolsIn(value, baseAssignIn(result, value))
00120 : copySymbols(value, baseAssign(result, value));
00121 }
00122 } else {
00123 if (!cloneableTags[tag]) {
00124 return object ? value : {};
00125 }
00126 result = initCloneByTag(value, tag, baseClone, isDeep);
00127 }
00128 }
00129
00130 stack || (stack = new Stack);
00131 var stacked = stack.get(value);
00132 if (stacked) {
00133 return stacked;
00134 }
00135 stack.set(value, result);
00136
00137 var keysFunc = isFull
00138 ? (isFlat ? getAllKeysIn : getAllKeys)
00139 : (isFlat ? keysIn : keys);
00140
00141 var props = isArr ? undefined : keysFunc(value);
00142 arrayEach(props || value, function(subValue, key) {
00143 if (props) {
00144 key = subValue;
00145 subValue = value[key];
00146 }
00147
00148 assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
00149 });
00150 return result;
00151 }
00152
00153 module.exports = baseClone;