es-toolkit
es-toolkit copied to clipboard
`mergeWith` (non-`compat`) dangerously shallow-copies default-mergeable source members
PR #556 addressed an issue regarding how merge handles inconsistent source and target types by default.
Looks like this should be applied to mergeWith as well, which still has identical logic to merge before that PR: https://github.com/toss/es-toolkit/blob/f1c7f923b1315bb05cb3a5e4070e6fa50d3127c5/src/object/mergeWith.ts#L74-L78
Note that as a consequence of this, by default mergeWith currently results with shallow copies of internal members, making typical usage unsafe. For example:
import assert from 'assert';
import { mergeWith, noop } from 'es-toolkit';
const a = { x: { name: 'a.x' } };
const b = { y: { name: 'b.y' } };
const c = { y: { name: 'c.y' } };
// Appears safe, should be equivalent to default merge!
const m = [a, b, c].reduce((t, s) => mergeWith(t, s, noop), {});
assert.strictEqual(a.x.name, 'a.x');
assert.strictEqual(b.y.name, 'b.y'); // FAIL: source object b.y was mutated!
assert.strictEqual(c.y.name, 'c.y');
@raon0211 This issue appears to have been resolved by PR #1495.
Thanks @Seol-JY !