Skip to content

Commit 1ee8e68

Browse files
authored
fix(Object): use pure _dirty to prevent unnecessary saves with circular references (#515)
1 parent 3230b10 commit 1ee8e68

File tree

2 files changed

+59
-22
lines changed

2 files changed

+59
-22
lines changed

src/object.js

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ module.exports = function(AV) {
283283
dirty: function(attr) {
284284
this._refreshCache();
285285

286+
return this._dirty();
287+
},
288+
289+
_dirty: function(attr) {
286290
var currentChanges = _.last(this._opSetQueue);
287291

288292
if (attr) {
@@ -943,18 +947,13 @@ module.exports = function(AV) {
943947

944948
var model = this;
945949

946-
// If there is any unsaved child, save it first.
947-
model._refreshCache();
948-
949950
var unsavedChildren = [];
950951
var unsavedFiles = [];
951-
AV.Object._findUnsavedChildren(model.attributes,
952+
AV.Object._findUnsavedChildren(model,
952953
unsavedChildren,
953954
unsavedFiles);
954-
if (unsavedChildren.length + unsavedFiles.length > 0) {
955-
return AV.Object._deepSaveAsync(this.attributes, model, options).then(function() {
956-
return model.save(null, options);
957-
});
955+
if (unsavedChildren.length + unsavedFiles.length > 1) {
956+
return AV.Object._deepSaveAsync(this, model, options);
958957
}
959958

960959
this._startSave();
@@ -1501,11 +1500,10 @@ module.exports = function(AV) {
15011500
},
15021501
});
15031502

1504-
AV.Object._findUnsavedChildren = function(object, children, files) {
1505-
AV._traverse(object, function(object) {
1503+
AV.Object._findUnsavedChildren = function(objects, children, files) {
1504+
AV._traverse(objects, function(object) {
15061505
if (object instanceof AV.Object) {
1507-
object._refreshCache();
1508-
if (object.dirty()) {
1506+
if (object._dirty()) {
15091507
children.push(object);
15101508
}
15111509
return;
@@ -1548,11 +1546,6 @@ module.exports = function(AV) {
15481546
var unsavedChildren = [];
15491547
var unsavedFiles = [];
15501548
AV.Object._findUnsavedChildren(object, unsavedChildren, unsavedFiles);
1551-
if(model) {
1552-
unsavedChildren = _.filter(unsavedChildren, function(object) {
1553-
return object != model;
1554-
});
1555-
}
15561549

15571550
var promise = AV.Promise.resolve();
15581551
_.each(unsavedFiles, function(file) {
@@ -1603,14 +1596,25 @@ module.exports = function(AV) {
16031596
const bathSavePromise = readyToStart.then(() =>
16041597
_request("batch", null, null, "POST", {
16051598
requests: _.map(batch, function(object) {
1599+
1600+
var method = object.id ? 'PUT' : 'POST';
1601+
16061602
var json = object._getSaveJSON();
1603+
var query = {};
1604+
16071605
_.extend(json, object._flags);
1608-
var method = "POST";
1609-
1610-
var path = "/1.1/classes/" + object.className;
1606+
1607+
var route = "classes";
1608+
var className = object.className;
1609+
var path = `/${route}/${className}`;
1610+
if (object.className === "_User" && !object.id) {
1611+
// Special-case user sign-up.
1612+
path = '/users';
1613+
}
1614+
1615+
var path = `/1.1${path}`;
16111616
if (object.id) {
16121617
path = path + "/" + object.id;
1613-
method = "PUT";
16141618
}
16151619

16161620
object._startSave();

test/object.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ describe('Objects', function(){
297297
});
298298

299299
describe('set', () => {
300-
it('should not mute value', () => {
300+
it('should not mutate value', () => {
301301
const originalValue = {
302302
name: 'LC',
303303
objectId: '11111111111',
@@ -643,4 +643,37 @@ describe('Objects', function(){
643643
});
644644
});
645645

646+
describe('circular referrences', () => {
647+
it('dirty check', () => {
648+
const id = 'fake';
649+
const a = AV.parseJSON({
650+
__type: 'Object',
651+
className: 'A',
652+
objectId: id,
653+
b: [
654+
{
655+
__type: 'Pointer',
656+
className: 'B',
657+
objectId: id,
658+
},
659+
],
660+
c: {
661+
__type: 'Pointer',
662+
className: 'C',
663+
objectId: id,
664+
}
665+
});
666+
const b = a.get('b')[0];
667+
const c = a.get('c');
668+
b.set({a});
669+
a._dirty().should.eql(false);
670+
b._dirty().should.eql(true);
671+
c._dirty().should.eql(false);
672+
c.set({a});
673+
a._dirty().should.eql(false);
674+
b._dirty().should.eql(true);
675+
c._dirty().should.eql(true);
676+
});
677+
})
678+
646679
});//END RETRIEVING

0 commit comments

Comments
 (0)