| Leo Repp | 58b9f11 | 2021-11-22 11:57:47 +0100 | [diff] [blame^] | 1 | var assignMergeValue = require('./_assignMergeValue'), |
| 2 | cloneBuffer = require('./_cloneBuffer'), |
| 3 | cloneTypedArray = require('./_cloneTypedArray'), |
| 4 | copyArray = require('./_copyArray'), |
| 5 | initCloneObject = require('./_initCloneObject'), |
| 6 | isArguments = require('./isArguments'), |
| 7 | isArray = require('./isArray'), |
| 8 | isArrayLikeObject = require('./isArrayLikeObject'), |
| 9 | isBuffer = require('./isBuffer'), |
| 10 | isFunction = require('./isFunction'), |
| 11 | isObject = require('./isObject'), |
| 12 | isPlainObject = require('./isPlainObject'), |
| 13 | isTypedArray = require('./isTypedArray'), |
| 14 | safeGet = require('./_safeGet'), |
| 15 | toPlainObject = require('./toPlainObject'); |
| 16 | |
| 17 | /** |
| 18 | * A specialized version of `baseMerge` for arrays and objects which performs |
| 19 | * deep merges and tracks traversed objects enabling objects with circular |
| 20 | * references to be merged. |
| 21 | * |
| 22 | * @private |
| 23 | * @param {Object} object The destination object. |
| 24 | * @param {Object} source The source object. |
| 25 | * @param {string} key The key of the value to merge. |
| 26 | * @param {number} srcIndex The index of `source`. |
| 27 | * @param {Function} mergeFunc The function to merge values. |
| 28 | * @param {Function} [customizer] The function to customize assigned values. |
| 29 | * @param {Object} [stack] Tracks traversed source values and their merged |
| 30 | * counterparts. |
| 31 | */ |
| 32 | function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { |
| 33 | var objValue = safeGet(object, key), |
| 34 | srcValue = safeGet(source, key), |
| 35 | stacked = stack.get(srcValue); |
| 36 | |
| 37 | if (stacked) { |
| 38 | assignMergeValue(object, key, stacked); |
| 39 | return; |
| 40 | } |
| 41 | var newValue = customizer |
| 42 | ? customizer(objValue, srcValue, (key + ''), object, source, stack) |
| 43 | : undefined; |
| 44 | |
| 45 | var isCommon = newValue === undefined; |
| 46 | |
| 47 | if (isCommon) { |
| 48 | var isArr = isArray(srcValue), |
| 49 | isBuff = !isArr && isBuffer(srcValue), |
| 50 | isTyped = !isArr && !isBuff && isTypedArray(srcValue); |
| 51 | |
| 52 | newValue = srcValue; |
| 53 | if (isArr || isBuff || isTyped) { |
| 54 | if (isArray(objValue)) { |
| 55 | newValue = objValue; |
| 56 | } |
| 57 | else if (isArrayLikeObject(objValue)) { |
| 58 | newValue = copyArray(objValue); |
| 59 | } |
| 60 | else if (isBuff) { |
| 61 | isCommon = false; |
| 62 | newValue = cloneBuffer(srcValue, true); |
| 63 | } |
| 64 | else if (isTyped) { |
| 65 | isCommon = false; |
| 66 | newValue = cloneTypedArray(srcValue, true); |
| 67 | } |
| 68 | else { |
| 69 | newValue = []; |
| 70 | } |
| 71 | } |
| 72 | else if (isPlainObject(srcValue) || isArguments(srcValue)) { |
| 73 | newValue = objValue; |
| 74 | if (isArguments(objValue)) { |
| 75 | newValue = toPlainObject(objValue); |
| 76 | } |
| 77 | else if (!isObject(objValue) || isFunction(objValue)) { |
| 78 | newValue = initCloneObject(srcValue); |
| 79 | } |
| 80 | } |
| 81 | else { |
| 82 | isCommon = false; |
| 83 | } |
| 84 | } |
| 85 | if (isCommon) { |
| 86 | // Recursively merge objects and arrays (susceptible to call stack limits). |
| 87 | stack.set(srcValue, newValue); |
| 88 | mergeFunc(newValue, srcValue, srcIndex, customizer, stack); |
| 89 | stack['delete'](srcValue); |
| 90 | } |
| 91 | assignMergeValue(object, key, newValue); |
| 92 | } |
| 93 | |
| 94 | module.exports = baseMergeDeep; |