Skip to content

Commit

Permalink
refactor: move utility functions to a utils file
Browse files Browse the repository at this point in the history
  • Loading branch information
Rebecca Stevens committed Nov 16, 2020
1 parent a63672a commit 4da6cc6
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 46 deletions.
54 changes: 8 additions & 46 deletions src/deepmerge.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,22 @@
import isPlainObj from 'is-plain-obj'
import {
cloneUnlessOtherwiseSpecified,
getKeys,
getMergeFunction,
propertyIsOnObject,
propertyIsUnsafe
} from './utils'

function defaultIsMergeable(value) {
return Array.isArray(value) || isPlainObj(value)
}

function emptyTarget(val) {
return Array.isArray(val) ? [] : {}
}

function cloneUnlessOtherwiseSpecified(value, options) {
return (options.clone !== false && options.isMergeable(value))
? deepmergeImpl(emptyTarget(value), value, options)
: value
}

function defaultArrayMerge(target, source, options) {
return target.concat(source).map((element) =>
cloneUnlessOtherwiseSpecified(element, options)
)
}

function getMergeFunction(key, options) {
if (!options.customMerge) {
return deepmergeImpl
}
const customMerge = options.customMerge(key)
return typeof customMerge === 'function' ? customMerge : deepmergeImpl
}

function getEnumerableOwnPropertySymbols(target) {
return Object.getOwnPropertySymbols
? Object.getOwnPropertySymbols(target).filter((symbol) =>
target.propertyIsEnumerable(symbol)
)
: []
}

function getKeys(target) {
return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))
}

function propertyIsOnObject(object, property) {
try {
return property in object
} catch(_) {
return false
}
}

// Protects from prototype poisoning and unexpected merging up the prototype chain.
function propertyIsUnsafe(target, key) {
return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.
}

function mergeObject(target, source, options) {
const destination = {}
if (options.isMergeable(target)) {
Expand All @@ -76,7 +38,7 @@ function mergeObject(target, source, options) {
return destination
}

function deepmergeImpl(target, source, options) {
export function deepmergeImpl(target, source, options) {
const sourceIsArray = Array.isArray(source)
const targetIsArray = Array.isArray(target)
const sourceAndTargetTypesMatch = sourceIsArray === targetIsArray
Expand Down
45 changes: 45 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { deepmergeImpl } from './deepmerge';

function emptyTarget(value) {
return Array.isArray(value) ? [] : {}
}

export function cloneUnlessOtherwiseSpecified(value, options) {
return (options.clone !== false && options.isMergeable(value))
? deepmergeImpl(emptyTarget(value), value, options)
: value
}

function getEnumerableOwnPropertySymbols(target) {
return Object.getOwnPropertySymbols
? Object.getOwnPropertySymbols(target).filter((symbol) => target.propertyIsEnumerable(symbol)
)
: [];
}

export function getKeys(target) {
return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target));
}

export function propertyIsOnObject(object, property) {
try {
return property in object;
} catch (_) {
return false;
}
}

export function getMergeFunction(key, options) {
if (!options.customMerge) {
return deepmergeImpl
}
const customMerge = options.customMerge(key)
return typeof customMerge === 'function' ? customMerge : deepmergeImpl
}

// Protects from prototype poisoning and unexpected merging up the prototype chain.
export function propertyIsUnsafe(target, key) {
return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,
&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,
&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.
}

0 comments on commit 4da6cc6

Please sign in to comment.