Skip to content

Commit

Permalink
Merge pull request #651 from share/milestone-mutation
Browse files Browse the repository at this point in the history
🐛 Avoid mutating milestone snapshots when building from ops
  • Loading branch information
alecgibson authored May 14, 2024
2 parents a5c19b9 + 1683efa commit 8ba276c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ Backend.prototype._fetchSnapshotByTimestamp = function(collection, id, timestamp
};

Backend.prototype._buildSnapshotFromOps = function(id, startingSnapshot, ops, callback) {
var snapshot = startingSnapshot || new Snapshot(id, 0, null, undefined, null);
var snapshot = util.clone(startingSnapshot) || new Snapshot(id, 0, null, undefined, null);
var error = ot.applyOps(snapshot, ops, {_normalizeLegacyJson0Ops: true});
callback(error, snapshot);
};
Expand Down
34 changes: 34 additions & 0 deletions test/client/snapshot-version-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var sinon = require('sinon');
var async = require('async');
var json0v2 = require('ot-json0-v2').type;
var types = require('../../lib/types');
var clone = require('../../lib/util').clone;

describe('SnapshotVersionRequest', function() {
var backend;
Expand Down Expand Up @@ -440,6 +441,39 @@ describe('SnapshotVersionRequest', function() {
], done);
});

it('does not mutate the milestone snapshot', function(done) {
var connection = backendWithMilestones.connect();
var doc = connection.get('books', 'mocking-bird');
var milestoneDb = backendWithMilestones.milestoneDb;
var milestone;

async.waterfall([
doc.create.bind(doc, {title: 'To Kill a Mocking Bird'}),
doc.submitOp.bind(doc, {p: ['author'], oi: 'Harper Lea'}),
doc.submitOp.bind(doc, {p: ['author'], od: 'Harper Lea', oi: 'Harper Lee'}),
milestoneDb.getMilestoneSnapshot.bind(milestoneDb, 'books', 'mocking-bird', 3),
function(snapshot, next) {
milestone = clone(snapshot);
next();
},
function(next) {
// Internally, this calls ot.applyOps(), which mutates the snapshot it's passed.
// This call shouldn't cause the in-memory milestone snapshot to be mutated.
connection.fetchSnapshot('books', 'mocking-bird', 3, next);
},
function(snapshot, next) {
expect(snapshot.v).to.equal(3);
expect(snapshot.data).to.eql({title: 'To Kill a Mocking Bird', author: 'Harper Lee'});
next();
},
milestoneDb.getMilestoneSnapshot.bind(milestoneDb, 'books', 'mocking-bird', 3),
function(snapshot, next) {
expect(snapshot).to.eql(milestone);
next();
}
], done);
});

describe('with version null', function() {
it('fetches a latest version', function(done) {
var doc = backendWithMilestones.connect().get('books', 'mocking-bird');
Expand Down

0 comments on commit 8ba276c

Please sign in to comment.