in backend/new.js [50:192]
function seekWithinBlock(ops, docCols, actorIds, resumeInsertion) {
for (let col of docCols) col.decoder.reset()
const { objActor, objCtr, keyActor, keyCtr, keyStr, idActor, idCtr, insert } = ops
const [objActorD, objCtrD, /* keyActorD */, /* keyCtrD */, keyStrD, idActorD, idCtrD, insertD, actionD,
/* valLenD */, /* valRawD */, /* chldActorD */, /* chldCtrD */, succNumD] = docCols.map(col => col.decoder)
let skipCount = 0, visibleCount = 0, elemVisible = false, nextObjActor = null, nextObjCtr = null
let nextIdActor = null, nextIdCtr = null, nextKeyStr = null, nextInsert = null, nextSuccNum = 0
// Seek to the beginning of the object being updated
if (objCtr !== null && !resumeInsertion) {
while (!objCtrD.done || !objActorD.done || !actionD.done) {
nextObjCtr = objCtrD.readValue()
nextObjActor = actorIds[objActorD.readValue()]
actionD.skipValues(1)
if (nextObjCtr === null || !nextObjActor || nextObjCtr < objCtr ||
(nextObjCtr === objCtr && nextObjActor < objActor)) {
skipCount += 1
} else {
break
}
}
}
if ((nextObjCtr !== objCtr || nextObjActor !== objActor) && !resumeInsertion) {
return {found: true, skipCount, visibleCount}
}
// Seek to the appropriate key (if string key is used)
if (keyStr !== null) {
keyStrD.skipValues(skipCount)
while (!keyStrD.done) {
const objActorIndex = objActorD.readValue()
nextObjActor = objActorIndex === null ? null : actorIds[objActorIndex]
nextObjCtr = objCtrD.readValue()
nextKeyStr = keyStrD.readValue()
if (nextKeyStr !== null && nextKeyStr < keyStr &&
nextObjCtr === objCtr && nextObjActor === objActor) {
skipCount += 1
} else {
break
}
}
return {found: true, skipCount, visibleCount}
}
idCtrD.skipValues(skipCount)
idActorD.skipValues(skipCount)
insertD.skipValues(skipCount)
succNumD.skipValues(skipCount)
nextIdCtr = idCtrD.readValue()
nextIdActor = actorIds[idActorD.readValue()]
nextInsert = insertD.readValue()
nextSuccNum = succNumD.readValue()
// If we are inserting into a list, an opId key is used, and we need to seek to a position *after*
// the referenced operation. Moreover, we need to skip over any existing operations with a greater
// opId than the new insertion, for CRDT convergence on concurrent insertions in the same place.
if (insert) {
// If insertion is not at the head, search for the reference element
if (!resumeInsertion && keyCtr !== null && keyCtr > 0 && keyActor !== null) {
skipCount += 1
while (!idCtrD.done && !idActorD.done && (nextIdCtr !== keyCtr || nextIdActor !== keyActor)) {
if (nextInsert) elemVisible = false
if (nextSuccNum === 0 && !elemVisible) {
visibleCount += 1
elemVisible = true
}
nextIdCtr = idCtrD.readValue()
nextIdActor = actorIds[idActorD.readValue()]
nextObjCtr = objCtrD.readValue()
nextObjActor = actorIds[objActorD.readValue()]
nextInsert = insertD.readValue()
nextSuccNum = succNumD.readValue()
if (nextObjCtr === objCtr && nextObjActor === objActor) skipCount += 1; else break
}
if (nextObjCtr !== objCtr || nextObjActor !== objActor || nextIdCtr !== keyCtr ||
nextIdActor !== keyActor || !nextInsert) {
return {found: false, skipCount, visibleCount}
}
if (nextInsert) elemVisible = false
if (nextSuccNum === 0 && !elemVisible) {
visibleCount += 1
elemVisible = true
}
// Set up the next* variables to the operation following the reference element
if (idCtrD.done || idActorD.done) return {found: true, skipCount, visibleCount}
nextIdCtr = idCtrD.readValue()
nextIdActor = actorIds[idActorD.readValue()]
nextObjCtr = objCtrD.readValue()
nextObjActor = actorIds[objActorD.readValue()]
nextInsert = insertD.readValue()
nextSuccNum = succNumD.readValue()
}
// Skip over any list elements with greater ID than the new one, and any non-insertions
while ((!nextInsert || nextIdCtr > idCtr || (nextIdCtr === idCtr && nextIdActor > idActor)) &&
nextObjCtr === objCtr && nextObjActor === objActor) {
skipCount += 1
if (nextInsert) elemVisible = false
if (nextSuccNum === 0 && !elemVisible) {
visibleCount += 1
elemVisible = true
}
if (!idCtrD.done && !idActorD.done) {
nextIdCtr = idCtrD.readValue()
nextIdActor = actorIds[idActorD.readValue()]
nextObjCtr = objCtrD.readValue()
nextObjActor = actorIds[objActorD.readValue()]
nextInsert = insertD.readValue()
nextSuccNum = succNumD.readValue()
} else {
break
}
}
} else if (keyCtr !== null && keyCtr > 0 && keyActor !== null) {
// If we are updating an existing list element, seek to just before the referenced ID
while ((!nextInsert || nextIdCtr !== keyCtr || nextIdActor !== keyActor) &&
nextObjCtr === objCtr && nextObjActor === objActor) {
skipCount += 1
if (nextInsert) elemVisible = false
if (nextSuccNum === 0 && !elemVisible) {
visibleCount += 1
elemVisible = true
}
if (!idCtrD.done && !idActorD.done) {
nextIdCtr = idCtrD.readValue()
nextIdActor = actorIds[idActorD.readValue()]
nextObjCtr = objCtrD.readValue()
nextObjActor = actorIds[objActorD.readValue()]
nextInsert = insertD.readValue()
nextSuccNum = succNumD.readValue()
} else {
break
}
}
if (nextObjCtr !== objCtr || nextObjActor !== objActor || nextIdCtr !== keyCtr ||
nextIdActor !== keyActor || !nextInsert) {
return {found: false, skipCount, visibleCount}
}
}
return {found: true, skipCount, visibleCount}
}