You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.2 KiB

4 years ago
  1. 'use strict';
  2. var isMergeableObject = function isMergeableObject(value) {
  3. return isNonNullObject(value)
  4. && !isSpecial(value)
  5. };
  6. function isNonNullObject(value) {
  7. return !!value && typeof value === 'object'
  8. }
  9. function isSpecial(value) {
  10. var stringValue = Object.prototype.toString.call(value);
  11. return stringValue === '[object RegExp]'
  12. || stringValue === '[object Date]'
  13. || isReactElement(value)
  14. }
  15. // see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25
  16. var canUseSymbol = typeof Symbol === 'function' && Symbol.for;
  17. var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;
  18. function isReactElement(value) {
  19. return value.$$typeof === REACT_ELEMENT_TYPE
  20. }
  21. function emptyTarget(val) {
  22. return Array.isArray(val) ? [] : {}
  23. }
  24. function cloneUnlessOtherwiseSpecified(value, optionsArgument) {
  25. var cloneOptionWasSpecified = optionsArgument && typeof optionsArgument.clone === 'boolean';
  26. var clone = !cloneOptionWasSpecified || optionsArgument.clone === true;
  27. return (clone && isMergeableObject(value))
  28. ? deepmerge(emptyTarget(value), value, optionsArgument)
  29. : value
  30. }
  31. function defaultArrayMerge(target, source, optionsArgument) {
  32. var destination = target.slice();
  33. source.forEach(function(e, i) {
  34. if (typeof destination[i] === 'undefined') {
  35. destination[i] = cloneUnlessOtherwiseSpecified(e, optionsArgument);
  36. } else if (isMergeableObject(e)) {
  37. destination[i] = deepmerge(target[i], e, optionsArgument);
  38. } else if (target.indexOf(e) === -1) {
  39. destination.push(cloneUnlessOtherwiseSpecified(e, optionsArgument));
  40. }
  41. });
  42. return destination
  43. }
  44. function mergeObject(target, source, optionsArgument) {
  45. var destination = {};
  46. if (isMergeableObject(target)) {
  47. Object.keys(target).forEach(function(key) {
  48. destination[key] = cloneUnlessOtherwiseSpecified(target[key], optionsArgument);
  49. });
  50. }
  51. Object.keys(source).forEach(function(key) {
  52. if (!isMergeableObject(source[key]) || !target[key]) {
  53. destination[key] = cloneUnlessOtherwiseSpecified(source[key], optionsArgument);
  54. } else {
  55. destination[key] = deepmerge(target[key], source[key], optionsArgument);
  56. }
  57. });
  58. return destination
  59. }
  60. function deepmerge(target, source, optionsArgument) {
  61. var sourceIsArray = Array.isArray(source);
  62. var targetIsArray = Array.isArray(target);
  63. var options = optionsArgument || { arrayMerge: defaultArrayMerge };
  64. var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
  65. if (!sourceAndTargetTypesMatch) {
  66. return cloneUnlessOtherwiseSpecified(source, optionsArgument)
  67. } else if (sourceIsArray) {
  68. var arrayMerge = options.arrayMerge || defaultArrayMerge;
  69. return arrayMerge(target, source, optionsArgument)
  70. } else {
  71. return mergeObject(target, source, optionsArgument)
  72. }
  73. }
  74. deepmerge.all = function deepmergeAll(array, optionsArgument) {
  75. if (!Array.isArray(array) || array.length < 2) {
  76. throw new Error('first argument should be an array with at least two elements')
  77. }
  78. // we are sure there are at least 2 values, so it is safe to have no initial value
  79. return array.reduce(function(prev, next) {
  80. return deepmerge(prev, next, optionsArgument)
  81. })
  82. };
  83. var deepmerge_1 = deepmerge;
  84. module.exports = deepmerge_1;