source: node_modules/deepmerge/index.js@ d24f17c

main
Last change on this file since d24f17c was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 3.2 KB
Line 
1var defaultIsMergeableObject = require('is-mergeable-object')
2
3function emptyTarget(val) {
4 return Array.isArray(val) ? [] : {}
5}
6
7function cloneUnlessOtherwiseSpecified(value, options) {
8 return (options.clone !== false && options.isMergeableObject(value))
9 ? deepmerge(emptyTarget(value), value, options)
10 : value
11}
12
13function defaultArrayMerge(target, source, options) {
14 return target.concat(source).map(function(element) {
15 return cloneUnlessOtherwiseSpecified(element, options)
16 })
17}
18
19function getMergeFunction(key, options) {
20 if (!options.customMerge) {
21 return deepmerge
22 }
23 var customMerge = options.customMerge(key)
24 return typeof customMerge === 'function' ? customMerge : deepmerge
25}
26
27function getEnumerableOwnPropertySymbols(target) {
28 return Object.getOwnPropertySymbols
29 ? Object.getOwnPropertySymbols(target).filter(function(symbol) {
30 return Object.propertyIsEnumerable.call(target, symbol)
31 })
32 : []
33}
34
35function getKeys(target) {
36 return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))
37}
38
39function propertyIsOnObject(object, property) {
40 try {
41 return property in object
42 } catch(_) {
43 return false
44 }
45}
46
47// Protects from prototype poisoning and unexpected merging up the prototype chain.
48function propertyIsUnsafe(target, key) {
49 return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
50 && !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
51 && Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.
52}
53
54function mergeObject(target, source, options) {
55 var destination = {}
56 if (options.isMergeableObject(target)) {
57 getKeys(target).forEach(function(key) {
58 destination[key] = cloneUnlessOtherwiseSpecified(target[key], options)
59 })
60 }
61 getKeys(source).forEach(function(key) {
62 if (propertyIsUnsafe(target, key)) {
63 return
64 }
65
66 if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {
67 destination[key] = getMergeFunction(key, options)(target[key], source[key], options)
68 } else {
69 destination[key] = cloneUnlessOtherwiseSpecified(source[key], options)
70 }
71 })
72 return destination
73}
74
75function deepmerge(target, source, options) {
76 options = options || {}
77 options.arrayMerge = options.arrayMerge || defaultArrayMerge
78 options.isMergeableObject = options.isMergeableObject || defaultIsMergeableObject
79 // cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
80 // implementations can use it. The caller may not replace it.
81 options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified
82
83 var sourceIsArray = Array.isArray(source)
84 var targetIsArray = Array.isArray(target)
85 var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray
86
87 if (!sourceAndTargetTypesMatch) {
88 return cloneUnlessOtherwiseSpecified(source, options)
89 } else if (sourceIsArray) {
90 return options.arrayMerge(target, source, options)
91 } else {
92 return mergeObject(target, source, options)
93 }
94}
95
96deepmerge.all = function deepmergeAll(array, options) {
97 if (!Array.isArray(array)) {
98 throw new Error('first argument should be an array')
99 }
100
101 return array.reduce(function(prev, next) {
102 return deepmerge(prev, next, options)
103 }, {})
104}
105
106module.exports = deepmerge
Note: See TracBrowser for help on using the repository browser.