Skip to content

Commit

Permalink
feat: don't clone by deafult
Browse files Browse the repository at this point in the history
  • Loading branch information
RebeccaStevens committed Nov 27, 2020
1 parent ec58b65 commit 20a8080
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 22 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# [5.0.0](https://github.com/TehShrike/deepmerge/releases/tag/v5.0.0)

- Breaking: Cloning is not turned off by default
- Breaking: Endpoint are now exported in esm style [#215](https://github.com/TehShrike/deepmerge/pull/215)
- The main merge function is now a default export
- The all merge function is now exported as "deepmergeAll" and is no longer a property on the main merge function.
Expand Down
6 changes: 2 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,9 @@ result.pets // => ['Cat', 'Parrot', 'Dog']

#### `clone`

*Deprecated.*
Defaults to `false`.

Defaults to `true`.

If `clone` is `false` then child objects will be copied directly instead of being cloned. This was the default behavior before version 2.x.
If `clone` is `true` then child objects will be cloned into the destination object instead of being directly copied. This was the default behavior before version 5.x.

## Testing

Expand Down
9 changes: 7 additions & 2 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { FlattenAlias, Property } from "./types"
*/
export type Options = Partial<{
readonly arrayMerge?: ArrayMerge
readonly clone?: boolean
readonly clone?: Clone
readonly customMerge?: ObjectMerge
readonly isMergeable?: IsMergeable
}>
Expand Down Expand Up @@ -45,14 +45,19 @@ export type IsMergeable = (value: any) => boolean
*/
export type ArrayMerge<T1 = any, T2 = any> = (target: Array<T1>, source: Array<T2>, options: FullOptions) => any

/**
* The cloning behavior.
*/
export type Clone<T = any> = boolean | ((object: T, options: FullOptions) => any)

/**
* A function that merges any 2 non-arrays values.
*/
export type ObjectMerge<K = any> = (
key: K
) => ((target: any, source: any, options: FullOptions) => any) | undefined

const defaultClone = true as const
const defaultClone = false as const

function defaultIsMergeable(value: unknown): value is Record<Property, unknown> | Array<unknown> {
return Array.isArray(value) || isPlainObj(value)
Expand Down
18 changes: 9 additions & 9 deletions test/merge-all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,31 @@ test(`invoke merge on every item in array with clone should clone all elements`,
t.end()
})

test(`invoke merge on every item in array clone=false should not clone all elements`, (t) => {
test(`invoke merge on every item in array clone=true should clone all elements`, (t) => {
const firstObject = { a: { d: 123 } }
const secondObject = { b: { e: true } }
const thirdObject = { c: { f: `string` } }

const mergedWithoutClone = deepmergeAll([ firstObject, secondObject, thirdObject ], { clone: false })
const mergedWithoutClone = deepmergeAll([ firstObject, secondObject, thirdObject ], { clone: true })

t.equal(mergedWithoutClone.a, firstObject.a)
t.equal(mergedWithoutClone.b, secondObject.b)
t.equal(mergedWithoutClone.c, thirdObject.c)
t.notEqual(mergedWithoutClone.a, firstObject.a)
t.notEqual(mergedWithoutClone.b, secondObject.b)
t.notEqual(mergedWithoutClone.c, thirdObject.c)

t.end()
})


test(`invoke merge on every item in array without clone should clone all elements`, (t) => {
test(`invoke merge on every item in array without clone should not clone all elements`, (t) => {
const firstObject = { a: { d: 123 } }
const secondObject = { b: { e: true } }
const thirdObject = { c: { f: `string` } }

const mergedWithoutClone = deepmergeAll([ firstObject, secondObject, thirdObject ])

t.notEqual(mergedWithoutClone.a, firstObject.a)
t.notEqual(mergedWithoutClone.b, secondObject.b)
t.notEqual(mergedWithoutClone.c, thirdObject.c)
t.equal(mergedWithoutClone.a, firstObject.a)
t.equal(mergedWithoutClone.b, secondObject.b)
t.equal(mergedWithoutClone.c, thirdObject.c)

t.end()
})
8 changes: 4 additions & 4 deletions test/merge-plain-objects.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import deepmerge from "deepmerge"
import test from "tape"

test(`plain objects are merged by default`, (t) => {
test(`plain objects are merged by default and can be cloned`, (t) => {
const input = {
newObject: new Object(),
objectLiteral: { a: 123 },
}
const output = deepmerge({}, input)
const output = deepmerge({}, input, { clone: true })

t.deepEqual(output.newObject, input.newObject)
t.notEqual(output.newObject, input.newObject)
Expand All @@ -16,13 +16,13 @@ test(`plain objects are merged by default`, (t) => {
t.end()
})

test(`instantiated objects are copied by reference`, (t) => {
test(`instantiated objects are copied by reference with clone=true`, (t) => {
const input = {
date: new Date(),
error: new Error(),
regex: /regex/,
}
const output = deepmerge({}, input)
const output = deepmerge({}, input, { clone: true })

t.equal(output.date, input.date)
t.equal(output.error, input.error)
Expand Down
6 changes: 3 additions & 3 deletions test/merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ test(`should clone source and target`, (t) => {
t.end()
})

test(`should clone source and target`, (t) => {
test(`should not clone source and target if not told to`, (t) => {
const src = {
b: {
c: `foo`,
Expand All @@ -153,8 +153,8 @@ test(`should clone source and target`, (t) => {
}

const merged = deepmerge(target, src)
t.notEqual(merged.a, target.a)
t.notEqual(merged.b, src.b)
t.equal(merged.a, target.a)
t.equal(merged.b, src.b)

t.end()
})
Expand Down

0 comments on commit 20a8080

Please sign in to comment.