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;
|
---|