From 3d6ac1301c38b8360405685b84863d023b66cbfe Mon Sep 17 00:00:00 2001 From: Rebecca Stevens Date: Fri, 27 Nov 2020 15:23:18 +1300 Subject: [PATCH] feat: don't clone by deafult re #212 --- changelog.md | 1 + readme.md | 6 ++---- src/options.ts | 9 +++++++-- test/merge-all.ts | 18 +++++++++--------- test/merge-plain-objects.ts | 8 ++++---- test/merge.ts | 2 +- 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/changelog.md b/changelog.md index 35da49a..5d3f10e 100644 --- a/changelog.md +++ b/changelog.md @@ -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. diff --git a/readme.md b/readme.md index 26a5f14..27ee05b 100644 --- a/readme.md +++ b/readme.md @@ -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 diff --git a/src/options.ts b/src/options.ts index 48e3f88..8a6fa46 100644 --- a/src/options.ts +++ b/src/options.ts @@ -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 }> @@ -45,6 +45,11 @@ export type IsMergeable = (value: any) => boolean */ export type ArrayMerge = (target: Array, source: Array, options: FullOptions) => any +/** + * The cloning behavior. + */ +export type Clone = boolean | ((object: T, options: FullOptions) => any) + /** * A function that merges any 2 non-arrays values. */ @@ -52,7 +57,7 @@ export type ObjectMerge = ( 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 | Array { return Array.isArray(value) || isPlainObj(value) diff --git a/test/merge-all.ts b/test/merge-all.ts index b299ea1..3c13aef 100644 --- a/test/merge-all.ts +++ b/test/merge-all.ts @@ -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() }) diff --git a/test/merge-plain-objects.ts b/test/merge-plain-objects.ts index 91e59ba..638442b 100644 --- a/test/merge-plain-objects.ts +++ b/test/merge-plain-objects.ts @@ -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) @@ -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) diff --git a/test/merge.ts b/test/merge.ts index a29a11d..ca09e94 100644 --- a/test/merge.ts +++ b/test/merge.ts @@ -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`,