proper iteration through arrays (for mappings, toJSON, ..)

This commit is contained in:
Kevin Jahns 2021-11-19 18:54:27 +01:00
parent fc38f3b848
commit 6df152c4ec
2 changed files with 16 additions and 2 deletions

View File

@ -18,6 +18,7 @@ const lengthExceeded = error.create('Length exceeded!')
/** /**
* @todo rename to walker? * @todo rename to walker?
* @todo check that inserting character one after another always reuses ListIterators
*/ */
export class ListIterator { export class ListIterator {
/** /**
@ -214,6 +215,7 @@ export class ListIterator {
* @param {function(T, T): T} concat * @param {function(T, T): T} concat
*/ */
_slice (tr, len, value, slice, concat) { _slice (tr, len, value, slice, concat) {
this.index += len
while (len > 0 && !this.reachedEnd) { while (len > 0 && !this.reachedEnd) {
while (this.nextItem && this.nextItem.countable && !this.reachedEnd && len > 0) { while (this.nextItem && this.nextItem.countable && !this.reachedEnd && len > 0) {
if (!this.nextItem.deleted) { if (!this.nextItem.deleted) {
@ -240,6 +242,9 @@ export class ListIterator {
this.forward(tr, 0) this.forward(tr, 0)
} }
} }
if (len < 0) {
this.index -= len
}
return value return value
} }
@ -297,6 +302,7 @@ export class ListIterator {
this.nextItem = getItemCleanStart(tr, createID(itemid.client, itemid.clock + this.rel)) this.nextItem = getItemCleanStart(tr, createID(itemid.client, itemid.clock + this.rel))
this.rel = 0 this.rel = 0
} }
const sm = this.type._searchMarker
const parent = this.type const parent = this.type
const store = tr.doc.store const store = tr.doc.store
const ownClientId = tr.doc.clientID const ownClientId = tr.doc.clientID
@ -362,6 +368,10 @@ export class ListIterator {
} else { } else {
this.nextItem = right this.nextItem = right
} }
if (sm) {
updateMarkerChanges(tr, sm, this.index, content.length)
}
this.index += content.length
} }
/** /**
@ -406,9 +416,12 @@ export class ListIterator {
return this return this
}, },
next: () => { next: () => {
if (this.reachedEnd) {
return { done: true }
}
const [value] = this.slice(tr, 1) const [value] = this.slice(tr, 1)
return { return {
done: value == null, done: false,
value: value value: value
} }
} }

View File

@ -1,4 +1,4 @@
import { init, compare, applyRandomTests, Doc } from './testHelper.js' // eslint-disable-line import { init, compare, applyRandomTests, Doc, AbstractType } from './testHelper.js' // eslint-disable-line
import * as Y from '../src/index.js' import * as Y from '../src/index.js'
import * as t from 'lib0/testing' import * as t from 'lib0/testing'
@ -473,6 +473,7 @@ const arrayTransactions = [
yarray.insert(pos, content) yarray.insert(pos, content)
oldContent.splice(pos, 0, ...content) oldContent.splice(pos, 0, ...content)
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
t.compare(yarray.toJSON(), yarray.toArray().map(x => x instanceof AbstractType ? x.toJSON() : x))
}, },
function insertTypeArray (user, gen) { function insertTypeArray (user, gen) {
const yarray = user.getArray('array') const yarray = user.getArray('array')