diff --git a/src/index.js b/src/index.js index ec2b4c5d..d8d70b32 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +2,6 @@ export { Y } from './utils/Y.js' export { UndoManager } from './utils/UndoManager.js' export { Transaction } from './utils/Transaction.js' -export { Delete } from './Delete.js' export { ItemJSON } from './structs/ItemJSON.js' export { ItemString } from './structs/ItemString.js' export { ItemFormat } from './structs/ItemFormat.js' @@ -20,7 +19,5 @@ export { YXmlElement as XmlElement, YXmlFragment as XmlFragment } from './types/ export { getRelativePosition, fromRelativePosition, equal as equalRelativePosition } from './utils/relativePosition.js' export { ID, createID } from './utils/ID.js' -export { DeleteStore, DSNode } from './utils/DeleteSet.js/index.js' -export { deleteItemRange } from './utils/structManipulation.js' export { integrateRemoteStructs } from './utils/integrateRemoteStructs.js' export { isParentOf } from './utils/isParentOf.js' diff --git a/src/structs/AbstractItem.js b/src/structs/AbstractItem.js index 69288c31..4e717dd9 100644 --- a/src/structs/AbstractItem.js +++ b/src/structs/AbstractItem.js @@ -51,7 +51,7 @@ export const splitItem = (transaction, leftItem, diff) => { foundOrigins.add(o) o = o.right } - const right = leftItem.splitAt(diff) + const right = leftItem.splitAt(transaction, diff) if (transaction.added.has(leftItem)) { transaction.added.add(right) } else if (transaction.deleted.has(leftItem)) { diff --git a/src/types/YMap.js b/src/types/YMap.js index 4f4b7e72..9df8b638 100644 --- a/src/types/YMap.js +++ b/src/types/YMap.js @@ -2,11 +2,10 @@ * @module types */ -import { AbstractType, typeMapDelete } from './AbstractType.js' -import { ItemJSON } from '../structs/ItemJSON.js' +import { AbstractType, typeMapDelete, typeMapSet, typeMapGet, typeMapHas } from './AbstractType.js' import { ItemType } from '../structs/ItemType.js' // eslint-disable-line import { YEvent } from '../utils/YEvent.js' -import { ItemBinary } from '../structs/ItemBinary.js' +import * as decoding from 'lib0/decoding.js' // eslint-disable-line import { Transaction } from '../utils/Transaction.js' // eslint-disable-line class YMapIterator { @@ -159,94 +158,39 @@ export class YMap extends AbstractType { * @param {Object | string | number | AbstractType | ArrayBuffer } value The value of the element to add */ set (key, value) { - this._transact(y => { - const old = this._map.get(key) || null - if (old !== null) { - if ( - old.constructor === ItemJSON && - !old._deleted && old._content[0] === value - ) { - // Trying to overwrite with same value - // break here - return value - } - if (y !== null) { - old._delete(y) - } - } - let v - if (typeof value === 'function') { - v = new value() // eslint-disable-line new-cap - value = v - } else if (value instanceof Item) { - v = value - } else if (value != null && value.constructor === ArrayBuffer) { - v = new ItemBinary() - v._content = value - } else { - v = new ItemJSON() - v._content = [value] - } - v._right = old - v._right_origin = old - v._parent = this - v._parentSub = key - if (y !== null) { - v._integrate(y) - } else { - this._map.set(key, v) - } - }) + if (this._y !== null) { + this._y.transact(transaction => { + typeMapSet(transaction, this, key, value) + }) + } else { + // @ts-ignore + this._prelimContent.set(key, value) + } return value } /** * Returns a specified element from this YMap. * - * @param {string} key The key of the element to return. - * @param {HistorySnapshot} [snapshot] + * @param {string} key + * @return {Object|number|Array|string|ArrayBuffer|AbstractType|undefined} */ - get (key, snapshot) { - let v = this._map.get(key) - if (v === undefined) { - return undefined - } - if (snapshot !== undefined) { - // iterate until found element that exists - while (!snapshot.sm.has(v._id.user) || v._id.clock >= snapshot.sm.get(v._id.user)) { - v = v._right - } - } - if (isVisible(v, snapshot)) { - if (v instanceof Type) { - return v - } else if (v.constructor === ItemBinary) { - return v._content - } else { - return v._content[v._content.length - 1] - } - } + get (key) { + return typeMapGet(this, key) } /** * Returns a boolean indicating whether the specified key exists or not. * * @param {string} key The key to test. - * @param {HistorySnapshot} [snapshot] + * @return {boolean} */ - has (key, snapshot) { - let v = this._map.get(key) - if (v === undefined) { - return false - } - if (snapshot !== undefined) { - // iterate until found element that exists - while (!snapshot.sm.has(v._id.user) || v._id.clock >= snapshot.sm.get(v._id.user)) { - v = v._right - } - } - return isVisible(v, snapshot) + has (key) { + return typeMapHas(this, key) } } -export const readYMap = decoder => new YMap() \ No newline at end of file +/** + * @param {decoding.Decoder} decoder + */ +export const readYMap = decoder => new YMap() diff --git a/src/types/YText.js b/src/types/YText.js index 5813c43d..9ede5fd2 100644 --- a/src/types/YText.js +++ b/src/types/YText.js @@ -2,7 +2,6 @@ * @module types */ -import { logItemHelper } from '../structs/AbstractItem.js/index.js' import { ItemEmbed } from '../structs/ItemEmbed.js' import { ItemString } from '../structs/ItemString.js' import { ItemFormat } from '../structs/ItemFormat.js' diff --git a/src/types/YXmlElement.js b/src/types/YXmlElement.js index 953dd3c0..65e3adf5 100644 --- a/src/types/YXmlElement.js +++ b/src/types/YXmlElement.js @@ -3,7 +3,6 @@ */ import { Transaction } from '../utils/Transaction.js' // eslint-disable-line -import { logItemHelper } from '../structs/AbstractItem.js' import { YMap } from './YMap.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' diff --git a/src/types/YXmlEvent.js b/src/types/YXmlEvent.js index db871ac9..dc109694 100644 --- a/src/types/YXmlEvent.js +++ b/src/types/YXmlEvent.js @@ -4,7 +4,7 @@ import { YEvent } from '../utils/YEvent.js' -import { Type } from './AbstractType.js/index.js.js.js.js' // eslint-disable-line +import { Type } from './AbstractType.js' // eslint-disable-line import { Transaction } from '../utils/Transaction.js' // eslint-disable-line /** diff --git a/src/utils/DeleteSet.js b/src/utils/DeleteSet.js index bf33e84f..f09d4c85 100644 --- a/src/utils/DeleteSet.js +++ b/src/utils/DeleteSet.js @@ -3,8 +3,7 @@ import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { StructStore, getItemRange } from './StructStore.js' // eslint-disable-line import { Transaction } from './Transaction.js' // eslint-disable-line -import * as error from 'lib0/error.js' -import { ID } from './ID.js' +import { ID } from './ID.js' // eslint-disable-line class DeleteItem { /** diff --git a/src/utils/integrateRemoteStructs.js b/src/utils/integrateRemoteStructs.js index a066a98e..9d790740 100644 --- a/src/utils/integrateRemoteStructs.js +++ b/src/utils/integrateRemoteStructs.js @@ -2,11 +2,9 @@ * @module utils */ -import { getStruct } from '../utils/structReferences.js' import * as decoding from 'lib0/decoding.js' -import { GC } from '../structs/GC.js/index.js.js' +import { GC } from '../structs/GC.js' import { Y } from '../utils/Y.js' // eslint-disable-line -import { Item } from '../structs/AbstractItem.js/index.js' // eslint-disable-line class MissingEntry { constructor (decoder, missing, struct) { diff --git a/src/utils/isParentOf.js b/src/utils/isParentOf.js index 26fb8431..d965b259 100644 --- a/src/utils/isParentOf.js +++ b/src/utils/isParentOf.js @@ -3,24 +3,23 @@ */ import { Y } from '../utils/Y.js' // eslint-disable-line -import { Type } from '../types/AbstractType.js/index.js.js.js.js' // eslint-disable-line +import { AbstractType } from '../types/AbstractType.js' // eslint-disable-line /** * Check if `parent` is a parent of `child`. * - * @param {Type | Y} parent - * @param {Type | Y} child + * @param {AbstractType} parent + * @param {AbstractType} child * @return {Boolean} Whether `parent` is a parent of `child`. * * @public */ export const isParentOf = (parent, child) => { - child = child._parent - while (child !== null) { + while (child._item !== null) { if (child === parent) { return true } - child = child._parent + child = child._item.parent } return false } diff --git a/src/utils/relativePosition.js b/src/utils/relativePosition.js index 507de6a9..9cf540be 100644 --- a/src/utils/relativePosition.js +++ b/src/utils/relativePosition.js @@ -3,7 +3,7 @@ */ import * as ID from './ID.js' -import { GC } from '../structs/GC.js/index.js.js' +import { GC } from '../structs/GC.js' // TODO: Implement function to describe ranges diff --git a/src/utils/structEncoding.js b/src/utils/structEncoding.js index 09586864..f2743e8a 100644 --- a/src/utils/structEncoding.js +++ b/src/utils/structEncoding.js @@ -1,7 +1,6 @@ import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { AbstractStruct, AbstractRef } from '../structs/AbstractStruct.js' -import { ID, createID, writeID, writeNullID } from './ID.js' import * as binary from 'lib0/binary.js' import { Transaction } from './Transaction.js' import { findIndex } from './StructStore.js' diff --git a/tests/DeleteStore.tests.js b/tests/DeleteStore.tests.js deleted file mode 100644 index d947a11a..00000000 --- a/tests/DeleteStore.tests.js +++ /dev/null @@ -1,86 +0,0 @@ -import * as prng from 'lib0/prng.js' -import * as t from 'lib0/testing.js' -import { DeleteStore } from '../src/utils/DeleteStore.js' -import * as ID from '../src/utils/ID.js' - -/** - * Converts a DS to an array of length 10. - * - * @example - * const ds = new DeleteStore() - * ds.mark(ID.createID(0, 0), 1, false) - * ds.mark(ID.createID(0, 1), 1, true) - * ds.mark(ID.createID(0, 3), 1, false) - * dsToArray(ds) // => [0, 1, undefined, 0] - * - * @return {Array<(null|number)>} Array of numbers indicating if array[i] is deleted (0), garbage collected (1), or undeleted (undefined). - */ -const dsToArray = ds => { - const array = [] - let i = 0 - ds.iterate(null, null, n => { - // fill with null - while (i < n._id.clock) { - array[i++] = null - } - while (i < n._id.clock + n.len) { - array[i++] = n.gc ? 1 : 0 - } - }) - return array -} - -/** - * @param {t.TestCase} tc - */ -export const testDeleteStore = tc => { - t.describe('Integrity tests') - const ds = new DeleteStore() - ds.mark(ID.createID(0, 1), 1, false) - ds.mark(ID.createID(0, 2), 1, false) - ds.mark(ID.createID(0, 3), 1, false) - t.compareArrays(dsToArray(ds), [null, 0, 0, 0]) - ds.mark(ID.createID(0, 2), 1, true) - t.compareArrays(dsToArray(ds), [null, 0, 1, 0]) - ds.mark(ID.createID(0, 1), 1, true) - t.compareArrays(dsToArray(ds), [null, 1, 1, 0]) - ds.mark(ID.createID(0, 3), 1, true) - t.compareArrays(dsToArray(ds), [null, 1, 1, 1]) - ds.mark(ID.createID(0, 5), 1, true) - ds.mark(ID.createID(0, 4), 1, true) - t.compareArrays(dsToArray(ds), [null, 1, 1, 1, 1, 1]) - ds.mark(ID.createID(0, 0), 3, false) - t.compareArrays(dsToArray(ds), [0, 0, 0, 1, 1, 1]) -} - -export const testRepeatDeleteStoreTests = tc => { - const gen = tc.prng - const ds = new DeleteStore() - const dsArray = [] - for (let i = 0; i < 200; i++) { - const pos = prng.int31(gen, 0, 10) - const len = prng.int31(gen, 0, 4) - const gc = prng.bool(gen) - ds.mark(ID.createID(0, pos), len, gc) - for (let j = 0; j < len; j++) { - dsArray[pos + j] = gc ? 1 : 0 - } - } - // fill empty fields - for (let i = 0; i < dsArray.length; i++) { - if (dsArray[i] !== 0 && dsArray[i] !== 1) { - dsArray[i] = null - } - } - t.compareArrays(dsToArray(ds), dsArray) - let size = 0 - let lastEl = null - for (let i = 0; i < dsArray.length; i++) { - let el = dsArray[i] - if (lastEl !== el && el !== null) { - size++ - } - lastEl = el - } - t.assert(size === ds.length) -} diff --git a/tsconfig.json b/tsconfig.json index dfedd65e..e33bdc3a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -58,5 +58,5 @@ "typeRoots": ["./src/utils/typedefs.js"], // "types": ["./src/utils/typedefs.js"] }, - "files": ["./src/index.js"] + "exclude": ["./dist/**"] }