Skip to content

Commit fa4341a

Browse files
authored
fix: Multiple object updates of nested keys overwrite each other (#1451)
1 parent 8f30edf commit fa4341a

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

src/ObjectStateMutations.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,14 @@ export function estimateAttributes(
120120
if (attr.includes('.')) {
121121
// convert a.b.c into { a: { b: { c: value } } }
122122
const fields = attr.split('.');
123-
const first = fields[0];
124123
const last = fields[fields.length - 1];
125-
data[first] = { ...serverData[first] };
126-
let object = { ...data };
124+
let object = data;
127125
for (let i = 0; i < fields.length - 1; i++) {
128126
const key = fields[i];
129127
if (!(key in object)) {
130128
object[key] = {};
129+
} else {
130+
object[key] = { ...object[key] };
131131
}
132132
object = object[key];
133133
}

src/__tests__/ParseObject-test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,69 @@ describe('ParseObject', () => {
669669
});
670670
});
671671

672+
it('can set multiple nested fields (regression test for #1450)', () => {
673+
const o = new ParseObject('Person');
674+
o._finishFetch({
675+
objectId: 'setNested2_1450',
676+
objectField: {
677+
number: 5,
678+
letter: 'a',
679+
nested: {
680+
number: 0,
681+
letter: 'b',
682+
},
683+
},
684+
});
685+
686+
expect(o.attributes).toEqual({
687+
objectField: { number: 5, letter: 'a', nested: { number: 0, letter: 'b' } },
688+
});
689+
o.set('objectField.number', 20);
690+
o.set('objectField.letter', 'b');
691+
o.set('objectField.nested.number', 1);
692+
o.set('objectField.nested.letter', 'c');
693+
694+
expect(o.attributes).toEqual({
695+
objectField: { number: 20, letter: 'b', nested: { number: 1, letter: 'c' } },
696+
});
697+
expect(o.op('objectField.number') instanceof SetOp).toBe(true);
698+
expect(o.dirtyKeys()).toEqual([
699+
'objectField.number',
700+
'objectField.letter',
701+
'objectField.nested.number',
702+
'objectField.nested.letter',
703+
'objectField',
704+
]);
705+
expect(o._getSaveJSON()).toEqual({
706+
'objectField.number': 20,
707+
'objectField.letter': 'b',
708+
'objectField.nested.number': 1,
709+
'objectField.nested.letter': 'c',
710+
});
711+
712+
o.revert('objectField.nested.number');
713+
o.revert('objectField.nested.letter');
714+
expect(o._getSaveJSON()).toEqual({
715+
'objectField.number': 20,
716+
'objectField.letter': 'b',
717+
});
718+
expect(o.attributes).toEqual({
719+
objectField: { number: 20, letter: 'b', nested: { number: 0, letter: 'b' } },
720+
});
721+
722+
// Also test setting new root fields using the dot notation
723+
o.set('objectField2.number', 0);
724+
expect(o._getSaveJSON()).toEqual({
725+
'objectField.number': 20,
726+
'objectField.letter': 'b',
727+
'objectField2.number': 0,
728+
});
729+
expect(o.attributes).toEqual({
730+
objectField: { number: 20, letter: 'b', nested: { number: 0, letter: 'b' } },
731+
objectField2: { number: 0 },
732+
});
733+
});
734+
672735
it('can increment a nested field', () => {
673736
const o = new ParseObject('Person');
674737
o._finishFetch({

0 commit comments

Comments
 (0)