fixed pos.rel cases
This commit is contained in:
parent
40c3be1732
commit
2a33507c00
@ -55,11 +55,19 @@ export const useSearchMarker = (tr, yarray, index, f) => {
|
|||||||
searchMarker.push(fsm)
|
searchMarker.push(fsm)
|
||||||
}
|
}
|
||||||
const diff = fsm.index - index
|
const diff = fsm.index - index
|
||||||
|
// @todo create fresh marker if diff > index
|
||||||
if (diff > 0) {
|
if (diff > 0) {
|
||||||
fsm.backward(tr, diff)
|
fsm.backward(tr, diff)
|
||||||
} else {
|
} else {
|
||||||
fsm.forward(tr, -diff)
|
fsm.forward(tr, -diff)
|
||||||
}
|
}
|
||||||
|
// @todo remove this tests
|
||||||
|
const otherTesting = new ListIterator(yarray)
|
||||||
|
otherTesting.forward(tr, index)
|
||||||
|
if (otherTesting.nextItem !== fsm.nextItem || otherTesting.index !== fsm.index || otherTesting.reachedEnd !== fsm.reachedEnd) {
|
||||||
|
throw new Error('udtirane')
|
||||||
|
}
|
||||||
|
|
||||||
const result = f(fsm)
|
const result = f(fsm)
|
||||||
if (fsm.reachedEnd) {
|
if (fsm.reachedEnd) {
|
||||||
fsm.reachedEnd = false
|
fsm.reachedEnd = false
|
||||||
@ -93,7 +101,7 @@ export const useSearchMarker = (tr, yarray, index, f) => {
|
|||||||
* @param {Array<ListIterator>} searchMarker
|
* @param {Array<ListIterator>} searchMarker
|
||||||
* @param {number} index
|
* @param {number} index
|
||||||
* @param {number} len If insertion, len is positive. If deletion, len is negative.
|
* @param {number} len If insertion, len is positive. If deletion, len is negative.
|
||||||
* @param {ListIterator} origSearchMarker Do not update this searchmarker because it is the one we used to manipulate.
|
* @param {ListIterator|null} origSearchMarker Do not update this searchmarker because it is the one we used to manipulate. @todo !=null for improved perf in ytext
|
||||||
*/
|
*/
|
||||||
export const updateMarkerChanges = (searchMarker, index, len, origSearchMarker) => {
|
export const updateMarkerChanges = (searchMarker, index, len, origSearchMarker) => {
|
||||||
for (let i = searchMarker.length - 1; i >= 0; i--) {
|
for (let i = searchMarker.length - 1; i >= 0; i--) {
|
||||||
|
@ -27,6 +27,7 @@ import {
|
|||||||
updateMarkerChanges,
|
updateMarkerChanges,
|
||||||
ContentType,
|
ContentType,
|
||||||
useSearchMarker,
|
useSearchMarker,
|
||||||
|
findIndexCleanStart,
|
||||||
ListIterator, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
|
ListIterator, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
|
|
||||||
@ -127,9 +128,27 @@ const findPosition = (transaction, parent, index) => {
|
|||||||
const currentAttributes = new Map()
|
const currentAttributes = new Map()
|
||||||
if (parent._searchMarker) {
|
if (parent._searchMarker) {
|
||||||
return useSearchMarker(transaction, parent, index, listIter => {
|
return useSearchMarker(transaction, parent, index, listIter => {
|
||||||
|
let left, right
|
||||||
|
if (listIter.rel > 0) {
|
||||||
|
// must exist because rel > 0
|
||||||
|
const nextItem = /** @type {Item} */ (listIter.nextItem)
|
||||||
|
if (listIter.rel === nextItem.length) {
|
||||||
|
left = nextItem
|
||||||
|
right = left.right
|
||||||
|
} else {
|
||||||
|
const structs = /** @type {Array<Item|GC>} */ (transaction.doc.store.clients.get(nextItem.id.client))
|
||||||
|
const after = /** @type {Item} */ (structs[findIndexCleanStart(transaction, structs, nextItem.id.clock + listIter.rel)])
|
||||||
|
listIter.nextItem = after
|
||||||
|
listIter.rel = 0
|
||||||
|
left = listIter.left
|
||||||
|
right = listIter.right
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
left = listIter.left
|
||||||
|
right = listIter.right
|
||||||
|
}
|
||||||
// @todo this should simply split if .rel > 0
|
// @todo this should simply split if .rel > 0
|
||||||
const pos = new ItemTextListPosition(listIter.left, listIter.right, listIter.index, currentAttributes)
|
return new ItemTextListPosition(left, right, index, currentAttributes)
|
||||||
return findNextPosition(transaction, pos, index - listIter.index + listIter.rel)
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
const pos = new ItemTextListPosition(null, parent._start, 0, currentAttributes)
|
const pos = new ItemTextListPosition(null, parent._start, 0, currentAttributes)
|
||||||
@ -266,7 +285,7 @@ const insertText = (transaction, parent, currPos, text, attributes) => {
|
|||||||
const content = text.constructor === String ? new ContentString(/** @type {string} */ (text)) : (text instanceof AbstractType ? new ContentType(text) : new ContentEmbed(text))
|
const content = text.constructor === String ? new ContentString(/** @type {string} */ (text)) : (text instanceof AbstractType ? new ContentType(text) : new ContentEmbed(text))
|
||||||
let { left, right, index } = currPos
|
let { left, right, index } = currPos
|
||||||
if (parent._searchMarker) {
|
if (parent._searchMarker) {
|
||||||
updateMarkerChanges(transaction, parent._searchMarker, currPos.index, content.getLength())
|
updateMarkerChanges(parent._searchMarker, currPos.index, content.getLength(), null)
|
||||||
}
|
}
|
||||||
right = new Item(createID(ownClientId, getState(doc.store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, content)
|
right = new Item(createID(ownClientId, getState(doc.store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, content)
|
||||||
right.integrate(transaction, 0)
|
right.integrate(transaction, 0)
|
||||||
@ -471,7 +490,7 @@ const deleteText = (transaction, currPos, length) => {
|
|||||||
}
|
}
|
||||||
const parent = /** @type {AbstractType<any>} */ (/** @type {Item} */ (currPos.left || currPos.right).parent)
|
const parent = /** @type {AbstractType<any>} */ (/** @type {Item} */ (currPos.left || currPos.right).parent)
|
||||||
if (parent._searchMarker) {
|
if (parent._searchMarker) {
|
||||||
updateMarkerChanges(transaction, parent._searchMarker, currPos.index, -startLength + length)
|
updateMarkerChanges(parent._searchMarker, currPos.index, -startLength + length, null)
|
||||||
}
|
}
|
||||||
return currPos
|
return currPos
|
||||||
}
|
}
|
||||||
|
@ -162,13 +162,18 @@ export class ListIterator {
|
|||||||
/**
|
/**
|
||||||
* @param {Transaction} tr
|
* @param {Transaction} tr
|
||||||
* @param {number} len
|
* @param {number} len
|
||||||
|
* @return {ListIterator}
|
||||||
*/
|
*/
|
||||||
backward (tr, len) {
|
backward (tr, len) {
|
||||||
if (this.index - len < 0) {
|
if (this.index - len < 0) {
|
||||||
throw lengthExceeded
|
throw lengthExceeded
|
||||||
}
|
}
|
||||||
let item = this.nextItem && this.nextItem.left
|
|
||||||
this.index -= len
|
this.index -= len
|
||||||
|
if (this.rel > len) {
|
||||||
|
this.rel -= len
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
let item = this.nextItem && this.nextItem.left
|
||||||
if (this.rel) {
|
if (this.rel) {
|
||||||
len -= this.rel
|
len -= this.rel
|
||||||
this.rel = 0
|
this.rel = 0
|
||||||
@ -177,8 +182,10 @@ export class ListIterator {
|
|||||||
if (item.countable && !item.deleted && item.moved === this.currMove) {
|
if (item.countable && !item.deleted && item.moved === this.currMove) {
|
||||||
len -= item.length
|
len -= item.length
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
this.rel = item.length + len
|
this.rel = -len
|
||||||
len = 0
|
len = 0
|
||||||
|
}
|
||||||
|
if (len === 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if (item.content.constructor === ContentMove && item.moved === this.currMove) {
|
} else if (item.content.constructor === ContentMove && item.moved === this.currMove) {
|
||||||
@ -201,8 +208,7 @@ export class ListIterator {
|
|||||||
}
|
}
|
||||||
item = item.left
|
item = item.left
|
||||||
}
|
}
|
||||||
this.index -= len
|
this.nextItem = item
|
||||||
this.nextItem = item && item.right
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +373,29 @@ export const compare = users => {
|
|||||||
t.compare(Y.encodeStateVector(users[i]), Y.encodeStateVector(users[i + 1]))
|
t.compare(Y.encodeStateVector(users[i]), Y.encodeStateVector(users[i + 1]))
|
||||||
compareDS(Y.createDeleteSetFromStructStore(users[i].store), Y.createDeleteSetFromStructStore(users[i + 1].store))
|
compareDS(Y.createDeleteSetFromStructStore(users[i].store), Y.createDeleteSetFromStructStore(users[i + 1].store))
|
||||||
compareStructStores(users[i].store, users[i + 1].store)
|
compareStructStores(users[i].store, users[i + 1].store)
|
||||||
|
// test list-iterator
|
||||||
|
{
|
||||||
|
const user = users[0]
|
||||||
|
user.transact(tr => {
|
||||||
|
const type = user.getArray('array')
|
||||||
|
Y.useSearchMarker(tr, type, type.length, walker => {
|
||||||
|
for (let i = type.length; i >= 0; i--) {
|
||||||
|
const otherWalker = new Y.ListIterator(type)
|
||||||
|
otherWalker.forward(tr, walker.index)
|
||||||
|
otherWalker.forward(tr, 0)
|
||||||
|
walker.forward(tr, 0)
|
||||||
|
t.assert(walker.index === i)
|
||||||
|
t.assert(walker.left === otherWalker.left)
|
||||||
|
t.assert(walker.right === otherWalker.right)
|
||||||
|
t.assert(walker.nextItem === otherWalker.nextItem)
|
||||||
|
t.assert(walker.reachedEnd === otherWalker.reachedEnd)
|
||||||
|
if (i > 0) {
|
||||||
|
walker.backward(tr, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
users.map(u => u.destroy())
|
users.map(u => u.destroy())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user