in backend/new.js [664:705]
function readNextChangeOp(docState, changeState) {
// If we've finished reading one change, move to the next change that contains at least one op
while (changeState.changeIndex < changeState.changes.length - 1 &&
(!changeState.columns || changeState.columns[actionIdx].decoder.done)) {
changeState.changeIndex += 1
const change = changeState.changes[changeState.changeIndex]
changeState.columns = makeDecoders(change.columns, CHANGE_COLUMNS)
changeState.opCtr = change.startOp
// Update docState based on the information in the change
updateBlockColumns(docState, changeState.columns)
const {actorIds, actorTable} = getActorTable(docState.actorIds, change)
docState.actorIds = actorIds
changeState.actorTable = actorTable
changeState.actorIndex = docState.actorIds.indexOf(change.actorIds[0])
}
// Reached the end of the last change?
if (changeState.columns[actionIdx].decoder.done) {
changeState.done = true
changeState.nextOp = null
return
}
changeState.nextOp = readOperation(changeState.columns, changeState.actorTable)
changeState.nextOp[idActorIdx] = changeState.actorIndex
changeState.nextOp[idCtrIdx] = changeState.opCtr
changeState.changes[changeState.changeIndex].maxOp = changeState.opCtr
if (changeState.opCtr > docState.maxOp) docState.maxOp = changeState.opCtr
changeState.opCtr += 1
const op = changeState.nextOp
if ((op[objCtrIdx] === null && op[objActorIdx] !== null) ||
(op[objCtrIdx] !== null && op[objActorIdx] === null)) {
throw new RangeError(`Mismatched object reference: (${op[objCtrIdx]}, ${op[objActorIdx]})`)
}
if ((op[keyCtrIdx] === null && op[keyActorIdx] !== null) ||
(op[keyCtrIdx] === 0 && op[keyActorIdx] !== null) ||
(op[keyCtrIdx] > 0 && op[keyActorIdx] === null)) {
throw new RangeError(`Mismatched operation key: (${op[keyCtrIdx]}, ${op[keyActorIdx]})`)
}
}