Skip to content

Commit d41be77

Browse files
committed
fix: applyPatches should mutate drafts
This mimics the behavior of applyPatches before v1.11.0 Fixes #301
1 parent c89d47d commit d41be77

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

__tests__/patch.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,24 @@ function runPatchTest(base, producer, patches, inversePathes) {
3939
}
4040

4141
describe("applyPatches", () => {
42+
it("mutates the base state when it is a draft", () => {
43+
produce({a: 1}, draft => {
44+
const result = applyPatches(draft, [
45+
{op: "replace", path: ["a"], value: 2}
46+
])
47+
expect(result).toBe(draft)
48+
expect(draft.a).toBe(2)
49+
})
50+
})
51+
it("produces a copy of the base state when not a draft", () => {
52+
const base = {a: 1}
53+
const result = applyPatches(base, [
54+
{op: "replace", path: ["a"], value: 2}
55+
])
56+
expect(result).not.toBe(base)
57+
expect(result.a).toBe(2)
58+
expect(base.a).toBe(1)
59+
})
4260
it('throws when `op` is not "add", "replace", nor "remove"', () => {
4361
expect(() => {
4462
const patch = {op: "copy", from: [0], path: [1]}

src/immer.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as legacyProxy from "./es5"
22
import * as modernProxy from "./proxy"
3-
import {generatePatches} from "./patches"
3+
import {applyPatches, generatePatches} from "./patches"
44
import {
55
assign,
66
each,
@@ -115,6 +115,14 @@ export class Immer {
115115
this.useProxies = value
116116
assign(this, value ? modernProxy : legacyProxy)
117117
}
118+
applyPatches(base, patches) {
119+
// Mutate the base state when a draft is passed.
120+
if (isDraft(base)) {
121+
return applyPatches(base, patches)
122+
}
123+
// Otherwise, produce a copy of the base state.
124+
return this.produce(base, draft => applyPatches(draft, patches))
125+
}
118126
/**
119127
* @internal
120128
* Finalize a draft, returning either the unmodified base state or a modified

src/index.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import {applyPatches as applyPatchesImpl} from "./patches"
21
import {Immer} from "./immer"
32

43
const immer = new Immer()
@@ -30,22 +29,22 @@ export default produce
3029
*
3130
* By default, auto-freezing is disabled in production.
3231
*/
33-
export const setAutoFreeze = value => immer.setAutoFreeze(value)
32+
export const setAutoFreeze = immer.setAutoFreeze.bind(immer)
3433

3534
/**
3635
* Pass true to use the ES2015 `Proxy` class when creating drafts, which is
3736
* always faster than using ES5 proxies.
3837
*
3938
* By default, feature detection is used, so calling this is rarely necessary.
4039
*/
41-
export const setUseProxies = value => immer.setUseProxies(value)
40+
export const setUseProxies = immer.setUseProxies.bind(immer)
4241

4342
/**
4443
* Apply an array of Immer patches to the first argument.
4544
*
4645
* This function is a producer, which means copy-on-write is in effect.
4746
*/
48-
export const applyPatches = produce(applyPatchesImpl)
47+
export const applyPatches = immer.applyPatches.bind(immer)
4948

5049
export {
5150
original,

src/patches.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export function generatePatches(state, basePath, patches, inversePatches) {
66
: generateObjectPatches(state, basePath, patches, inversePatches)
77
}
88

9-
export function generateArrayPatches(state, basePath, patches, inversePatches) {
9+
function generateArrayPatches(state, basePath, patches, inversePatches) {
1010
const {base, copy, assigned} = state
1111
const minLength = Math.min(base.length, copy.length)
1212

0 commit comments

Comments
 (0)