diff --git a/__tests__/patch.js b/__tests__/patch.js index 7e26cb41..d6afcbeb 100644 --- a/__tests__/patch.js +++ b/__tests__/patch.js @@ -1605,3 +1605,35 @@ test("applyPatches throws proper immer error when intermediate path value is nul applyPatches({a: null}, [{op: "add", path: ["a", "b"], value: 1}]) }).toThrow(isProd ? "18" : "Cannot apply patch, path doesn't resolve: a/b") }) + +describe("assigning a base value back over its own draft", () => { + // Reading a property drafts it; writing the base value back leaves the + // property untouched, so it must not show up in the patches at all. + const rootChild = {id: 1} + runPatchTests( + "root level", + {child: rootChild, other: 0}, + d => { + d.child + d.child = rootChild + d.other = 1 + }, + [{op: "replace", path: ["other"], value: 1}], + [{op: "replace", path: ["other"], value: 0}], + {child: {id: 1}, other: 1} + ) + + const nestedChild = {id: 1} + runPatchTests( + "nested", + {a: {child: nestedChild, other: 0}}, + d => { + d.a.child + d.a.child = nestedChild + d.a.other = 1 + }, + [{op: "replace", path: ["a", "other"], value: 1}], + [{op: "replace", path: ["a", "other"], value: 0}], + {a: {child: {id: 1}, other: 1}} + ) +}) diff --git a/src/core/proxy.ts b/src/core/proxy.ts index 70e95ad5..be46afc8 100644 --- a/src/core/proxy.ts +++ b/src/core/proxy.ts @@ -186,7 +186,9 @@ export const objectTraps: ProxyHandler = { const currentState: ProxyObjectState = current?.[DRAFT_STATE] if (currentState && currentState.base_ === value) { state.copy_![prop] = value - state.assigned_!.set(prop, false) + // The property still holds its base value, so nothing was assigned + // and nothing was deleted. `false` here reads as a deletion later. + state.assigned_!.delete(prop) return true } if (