All files / packages/core/src/utilities deepMerge.ts

83.33% Statements 30/36
61.11% Branches 22/36
88.88% Functions 8/9
83.33% Lines 30/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 871x 1005x   1005x             1x           1x 1403x   1403x         1x 2x   2x 2x 2x                         2x     1x 323x   323x 323x 875x     323x 682x 526x   156x       323x                   1x 325x 325x 325x   325x 2x         323x        
const isMergeableObject = (val) => {
  const nonNullObject = val && typeof val === 'object';
 
  return (
    nonNullObject &&
    Object.prototype.toString.call(val) !== '[object RegExp]' &&
    Object.prototype.toString.call(val) !== '[object Date]'
  );
};
 
const emptyTarget = (val) => {
  const isEmpty = Array.isArray(val) ? [] : {};
 
  return isEmpty;
};
 
const cloneIfNecessary = (value, optionsArgument) => {
  const clone = optionsArgument && optionsArgument.clone === true;
 
  return clone && isMergeableObject(value)
    ? deepMerge(emptyTarget(value), value, optionsArgument)
    : value;
};
 
const defaultArrayMerge = (target, source, optionsArgument) => {
  const destination = target.slice();
 
  source.forEach(function (e, i) {
    if (typeof destination[i] === 'undefined') {
      destination[i] = cloneIfNecessary(e, optionsArgument);
    } else Eif (isMergeableObject(e)) {
      destination[i] = deepMerge(target[i], e, optionsArgument);
    } else if (target.indexOf(e) === -1) {
      // IMPORTANT: WE SHOULD NOT PUSH NEW ELEMENTS TO THE ARRAY
      // INSTEAD WE SHOULD REPLACE THE ELEMENT, this will result
      // in unexpected behaviors if the initial tool parameters
      // are desired to override the default tool parameters that are
      // arrays
      destination[i] = cloneIfNecessary(e, optionsArgument);
    }
  });
 
  return destination;
};
 
const mergeObject = (target, source, optionsArgument) => {
  const destination = {};
 
  Eif (isMergeableObject(target)) {
    Object.keys(target).forEach(function (key) {
      destination[key] = cloneIfNecessary(target[key], optionsArgument);
    });
  }
  Object.keys(source).forEach(function (key) {
    if (!isMergeableObject(source[key]) || !target[key]) {
      destination[key] = cloneIfNecessary(source[key], optionsArgument);
    } else {
      destination[key] = deepMerge(target[key], source[key], optionsArgument);
    }
  });
 
  return destination;
};
 
/**
 * Merge two objects, recursively merging any objects that are arrays
 * @param target - The target object.
 * @param source - The source object to merge into the target object.
 * @param optionsArgument - The options object.
 * @returns The merged object.
 */
const deepMerge = (target = {}, source = {}, optionsArgument = undefined) => {
  const array = Array.isArray(source);
  const options = optionsArgument || { arrayMerge: defaultArrayMerge };
  const arrayMerge = options.arrayMerge || defaultArrayMerge;
 
  if (array) {
    return Array.isArray(target)
      ? arrayMerge(target, source, optionsArgument)
      : cloneIfNecessary(source, optionsArgument);
  }
 
  return mergeObject(target, source, optionsArgument);
};
 
export default deepMerge;