fix a bunch of issues with range-move approach

This commit is contained in:
Kevin Jahns 2022-05-07 16:14:18 +02:00
parent 69b7f4bfb9
commit 1f99e8203a
3 changed files with 36 additions and 23 deletions

View File

@ -38,10 +38,10 @@ const maxSearchMarker = 80
export const useSearchMarker = (tr, yarray, index, f) => { export const useSearchMarker = (tr, yarray, index, f) => {
const searchMarker = yarray._searchMarker const searchMarker = yarray._searchMarker
if (searchMarker === null || yarray._start === null) { // @todo add condition `index < 5` if (searchMarker === null || yarray._start === null) { // @todo add condition `index < 5`
return f(new ListIterator(yarray).forward(tr, index)) return f(new ListIterator(yarray).forward(tr, index, true))
} }
if (searchMarker.length === 0) { if (searchMarker.length === 0) {
const sm = new ListIterator(yarray).forward(tr, index) const sm = new ListIterator(yarray).forward(tr, index, true)
searchMarker.push(sm) searchMarker.push(sm)
if (sm.nextItem) sm.nextItem.marker = true if (sm.nextItem) sm.nextItem.marker = true
} }
@ -59,7 +59,7 @@ export const useSearchMarker = (tr, yarray, index, f) => {
if (diff > 0) { if (diff > 0) {
fsm.backward(tr, diff) fsm.backward(tr, diff)
} else { } else {
fsm.forward(tr, -diff) fsm.forward(tr, -diff, true)
} }
// @todo remove this test // @todo remove this test
/* /*

View File

@ -144,17 +144,21 @@ export class ListIterator {
moveTo (tr, index) { moveTo (tr, index) {
const diff = index - this.index const diff = index - this.index
if (diff > 0) { if (diff > 0) {
this.forward(tr, diff) this.forward(tr, diff, true)
} else if (diff < 0) { } else if (diff < 0) {
this.backward(tr, -diff) this.backward(tr, -diff)
} }
} }
/** /**
* When using skipUncountables=false within a "useSearchMarker" call, it is recommended
* to move the marker to the end. @todo do this after each useSearchMarkerCall
*
* @param {Transaction} tr * @param {Transaction} tr
* @param {number} len * @param {number} len
* @param {boolean} skipUncountables Iterate as much as possible iterating over uncountables until we find the next item.
*/ */
forward (tr, len) { forward (tr, len, skipUncountables) {
if (len === 0 && this.nextItem == null) { if (len === 0 && this.nextItem == null) {
return this return this
} }
@ -168,7 +172,8 @@ export class ListIterator {
len += this.rel len += this.rel
this.rel = 0 this.rel = 0
} }
while ((!this.reachedEnd || this.currMove !== null) && (len > 0 || (len === 0 && item && (!item.countable || item.deleted || item === this.currMoveEnd || (this.reachedEnd && this.currMoveEnd === null) || item.moved !== this.currMove)))) { // eslint-disable-next-line no-unmodified-loop-condition
while ((!this.reachedEnd || this.currMove !== null) && (len > 0 || (skipUncountables && len === 0 && item && (!item.countable || item.deleted || item === this.currMoveEnd || (this.reachedEnd && this.currMoveEnd === null) || item.moved !== this.currMove)))) {
if (item === this.currMoveEnd || (this.currMoveEnd === null && this.reachedEnd && this.currMove)) { if (item === this.currMoveEnd || (this.currMoveEnd === null && this.reachedEnd && this.currMove)) {
item = /** @type {Item} */ (this.currMove) // we iterate to the right after the current condition item = /** @type {Item} */ (this.currMove) // we iterate to the right after the current condition
popMovedStack(tr, this) popMovedStack(tr, this)
@ -337,7 +342,7 @@ export class ListIterator {
if ((!this.reachedEnd || this.currMove !== null) && len > 0) { if ((!this.reachedEnd || this.currMove !== null) && len > 0) {
// always set nextItem before any method call // always set nextItem before any method call
this.nextItem = nextItem this.nextItem = nextItem
this.forward(tr, 0) this.forward(tr, 0, true)
if (this.nextItem == null) { if (this.nextItem == null) {
throw new Error('debug me') // @todo remove throw new Error('debug me') // @todo remove
} }
@ -381,7 +386,7 @@ export class ListIterator {
} }
if (len > 0) { if (len > 0) {
this.nextItem = item this.nextItem = item
this.forward(tr, 0) this.forward(tr, 0, true)
item = this.nextItem item = this.nextItem
} }
} }
@ -622,7 +627,7 @@ export const getMinimalListViewRanges = (tr, walker, len) => {
const preItem = /** @type {Item} */ (walker.nextItem) const preItem = /** @type {Item} */ (walker.nextItem)
const preRel = walker.rel const preRel = walker.rel
walker.forward(tr, len) walker.forward(tr, len, false)
// store the same information for the end, after we iterate forward // store the same information for the end, after we iterate forward
/** /**
@ -630,21 +635,30 @@ export const getMinimalListViewRanges = (tr, walker, len) => {
*/ */
const afterStack = walker.movedStack.map(si => si.move) const afterStack = walker.movedStack.map(si => si.move)
const afterMove = walker.currMove const afterMove = walker.currMove
const afterItem = /** @type {Item} */ (walker.nextItem) const nextIsCurrMoveStart = walker.nextItem === walker.currMoveStart
const afterRel = walker.rel const afterItem = /** @type {Item} */ (nextIsCurrMoveStart
? walker.currMove
: (walker.rel > 0 || walker.reachedEnd)
? walker.nextItem
: /** @type {Item} */ (walker.nextItem).left
)
/**
* afterRel is always > 0
*/
const afterRel = nextIsCurrMoveStart
? 1
: walker.rel > 0
? walker.rel
: afterItem.length
walker.forward(tr, 0, false) // @todo remove once this is done is useSearchMarker
let start = createRelativePosition(walker.type, createID(preItem.id.client, preItem.id.clock + preRel), 0) let start = createRelativePosition(walker.type, createID(preItem.id.client, preItem.id.clock + preRel), 0)
let end = walker.reachedEnd let end = createRelativePosition(
? createRelativePosition( walker.type,
walker.type, createID(afterItem.id.client, afterItem.id.clock + afterRel - 1),
createID(afterItem.id.client, afterItem.id.clock + afterItem.length - 1), -1
-1 )
)
: createRelativePosition(
walker.type,
createID(afterItem.id.client, afterItem.id.clock + afterRel),
0
)
if (preMove) { if (preMove) {
preStack.push(preMove) preStack.push(preMove)

View File

@ -569,7 +569,6 @@ const arrayTransactions = [
const newPos = _newPosAdj + (_newPosAdj > yarray.length - len ? len : 0) const newPos = _newPosAdj + (_newPosAdj > yarray.length - len ? len : 0)
const oldContent = yarray.toArray() const oldContent = yarray.toArray()
yarray.moveRange(pos, pos + len - 1, newPos) yarray.moveRange(pos, pos + len - 1, newPos)
console.log(`moving range ${pos}-${pos + len - 1} to ${newPos}`)
const movedValues = oldContent.splice(pos, len) const movedValues = oldContent.splice(pos, len)
oldContent.splice(pos < newPos ? newPos - len : newPos, 0, ...movedValues) oldContent.splice(pos < newPos ? newPos - len : newPos, 0, ...movedValues)
t.compareArrays(yarray.toArray(), oldContent) // we want to make sure that fastSearch markers insert at the correct position t.compareArrays(yarray.toArray(), oldContent) // we want to make sure that fastSearch markers insert at the correct position