diff --git a/src/accessDeep.ts b/src/accessDeep.ts index ea98613..ce36e72 100644 --- a/src/accessDeep.ts +++ b/src/accessDeep.ts @@ -106,11 +106,14 @@ export const setDeep = ( } if (isSet(parent)) { - const oldValue = getNthKey(parent, +lastKey); + const index = +lastKey; + const oldValue = getNthKey(parent, index); const newValue = mapper(oldValue); if (oldValue !== newValue) { - parent.delete(oldValue); - parent.add(newValue); + const values = [...parent]; + values[index] = newValue; + parent.clear(); + values.forEach(value => parent.add(value)); } } @@ -122,10 +125,12 @@ export const setDeep = ( switch (type) { case 'key': { const newKey = mapper(keyToRow); - parent.set(newKey, parent.get(keyToRow)); - if (newKey !== keyToRow) { - parent.delete(keyToRow); + const entries = [...parent]; + parent.clear(); + entries.forEach(([k, v]) => + parent.set(k === keyToRow ? newKey : k, v) + ); } break; } diff --git a/src/index.test.ts b/src/index.test.ts index 249bbb0..e5158e9 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1313,6 +1313,43 @@ test('regression #245: superjson referential equalities only use the top-most pa expect(parsed).toEqual(input); }); +test('restores multiple referentially equal values inside the same Set', () => { + const a = { tag: 'a' }; + const b = { tag: 'b' }; + const input = { + set: new Set([a, b]), + a, + b, + }; + + const output: any = SuperJSON.deserialize(SuperJSON.serialize(input)); + + expect([...output.set]).toEqual([a, b]); + expect(output.set.has(output.a)).toBe(true); + expect(output.set.has(output.b)).toBe(true); + expect([...output.set][0]).toBe(output.a); + expect([...output.set][1]).toBe(output.b); +}); + +test('restores multiple referentially equal keys inside the same Map', () => { + const a = { tag: 'a' }; + const b = { tag: 'b' }; + const input = { + map: new Map([ + [a, 1], + [b, 2], + ]), + a, + b, + }; + + const output: any = SuperJSON.deserialize(SuperJSON.serialize(input)); + + expect([...output.map.keys()]).toEqual([a, b]); + expect(output.map.get(output.a)).toBe(1); + expect(output.map.get(output.b)).toBe(2); +}); + test('dedupe=true', () => { const instance = new SuperJSON({ dedupe: true,