in backend/new.js [1756:1826]
applyChanges(changeBuffers, isLocal = false) {
// decoded change has the form { actor, seq, startOp, time, message, deps, actorIds, hash, columns, buffer }
let decodedChanges = changeBuffers.map(buffer => {
const decoded = decodeChangeColumns(buffer)
decoded.buffer = buffer
return decoded
})
let patches = {_root: {objectId: '_root', type: 'map', props: {}}}
let docState = {
maxOp: this.maxOp,
changeIndexByHash: this.changeIndexByHash,
actorIds: this.actorIds,
heads: this.heads,
clock: this.clock,
blocks: this.blocks.slice(),
objectMeta: Object.assign({}, this.objectMeta)
}
let queue = (this.queue.length === 0) ? decodedChanges : decodedChanges.concat(this.queue)
let allApplied = [], objectIds = new Set()
while (true) {
const [applied, enqueued] = applyChanges(patches, queue, docState, objectIds)
queue = enqueued
if (applied.length > 0) allApplied = allApplied.concat(applied)
if (queue.length === 0) break
// If we are missing a dependency, and we haven't computed the hash graph yet, first compute
// the hashes to see if we actually have it already
if (applied.length === 0) {
if (!this.haveHashGraph) this.computeHashGraph(); else break
}
}
setupPatches(patches, objectIds, docState)
// Update the document state only if `applyChanges` does not throw an exception
for (let change of allApplied) {
this.changes.push(change.buffer)
if (!this.hashesByActor[change.actor]) this.hashesByActor[change.actor] = []
this.hashesByActor[change.actor][change.seq - 1] = change.hash
this.changeIndexByHash[change.hash] = this.changes.length - 1
this.dependenciesByHash[change.hash] = change.deps
this.dependentsByHash[change.hash] = []
for (let dep of change.deps) {
if (!this.dependentsByHash[dep]) this.dependentsByHash[dep] = []
this.dependentsByHash[dep].push(change.hash)
}
appendChange(this.changesEncoders, change, docState.actorIds, this.changeIndexByHash)
}
this.maxOp = docState.maxOp
this.actorIds = docState.actorIds
this.heads = docState.heads
this.clock = docState.clock
this.blocks = docState.blocks
this.objectMeta = docState.objectMeta
this.queue = queue
this.binaryDoc = null
this.initPatch = null
let patch = {
maxOp: this.maxOp, clock: this.clock, deps: this.heads,
pendingChanges: this.queue.length, diffs: patches._root
}
if (isLocal && decodedChanges.length === 1) {
patch.actor = decodedChanges[0].actor
patch.seq = decodedChanges[0].seq
}
return patch
}