diff --git a/package.json b/package.json index 6b112f74..3e01023f 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "module": "./dist/yjs.mjs'", "sideEffects": false, "scripts": { - "test": "npm run lint && npm run dist &&", + "test": "npm run dist && node ./dist/tests.js --repitition-time 50", "test-exhaustive": "npm run lint && npm run dist && node ./dist/tests.js --repitition-time 10000", "dist": "rm -rf dist examples/build && rollup -c", "watch": "rollup -wc", diff --git a/src/index.js b/src/index.js index 43ab84d1..b99154e2 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ export { Y } from './utils/Y.js' export { UndoManager } from './utils/UndoManager.js' export { Transaction } from './utils/Transaction.js' -export { Item } from './structs/Item.js' +export { Item, stringifyItemID } from './structs/Item.js' export { Delete } from './structs/Delete.js' export { ItemJSON } from './structs/ItemJSON.js' export { ItemString } from './structs/ItemString.js' @@ -27,6 +27,4 @@ export { deleteItemRange } from './utils/structManipulation.js' export { integrateRemoteStructs } from './utils/integrateRemoteStructs.js' export { isParentOf } from './utils/isParentOf.js' -export { stringifyItemID } from './utils/structStringify.js' - export * from './utils/structReferences.js' diff --git a/src/structs/Delete.js b/src/structs/Delete.js index d75186c7..5b93d3f2 100644 --- a/src/structs/Delete.js +++ b/src/structs/Delete.js @@ -7,10 +7,9 @@ import * as ID from '../utils/ID.js' import { writeStructToTransaction } from '../utils/structEncoding.js' import * as decoding from 'lib0/decoding.js' import * as encoding from 'lib0/encoding.js' -// import { Item } from './Item.js' // eslint-disable-line +import * as Item from './Item.js' // import { Y } from '../utils/Y.js' // eslint-disable-line import { deleteItemRange } from '../utils/structManipulation.js' -import * as stringify from '../utils/structStringify.js' /** * @private @@ -25,7 +24,7 @@ export class Delete { */ this._targetID = null /** - * @type {Item} + * @type {Item.Item} */ this._target = null this._length = null @@ -99,6 +98,6 @@ export class Delete { * @private */ _logString () { - return `Delete - target: ${stringify.stringifyID(this._targetID)}, len: ${this._length}` + return `Delete - target: ${Item.stringifyID(this._targetID)}, len: ${this._length}` } } diff --git a/src/structs/Item.js b/src/structs/Item.js index d4ee75a5..7b3848c8 100644 --- a/src/structs/Item.js +++ b/src/structs/Item.js @@ -10,6 +10,39 @@ import { GC } from './GC.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' +/** + * Stringify an item id. + * + * @param {ID.ID | ID.RootID} id + * @return {string} + */ +export const stringifyID = id => id instanceof ID.ID ? `(${id.user},${id.clock})` : `(${id.name},${id.type})` + +/** + * Stringify an item as ID. HHere, an item could also be a Yjs instance (e.g. item._parent). + * + * @param {Item | Y | null} item + * @return {string} + */ +export const stringifyItemID = item => + item === null ? '()' : (item._id != null ? stringifyID(item._id) : 'y') + +/** + * Helper utility to convert an item to a readable format. + * + * @param {String} name The name of the item class (YText, ItemString, ..). + * @param {Item} item The item instance. + * @param {String} [append] Additional information to append to the returned + * string. + * @return {String} A readable string that represents the item object. + * + */ +export const logItemHelper = (name, item, append) => { + const left = item._left !== null ? stringifyID(item._left._lastId) : '()' + const origin = item._origin !== null ? stringifyID(item._origin._lastId) : '()' + return `${name}(id:${stringifyItemID(item)},left:${left},origin:${origin},right:${stringifyItemID(item._right)},parent:${stringifyItemID(item._parent)},parentSub:${item._parentSub}${append !== undefined ? ' - ' + append : ''})` +} + /** * @private */ diff --git a/src/structs/ItemBinary.js b/src/structs/ItemBinary.js index dd1fe957..1f8e6ae0 100644 --- a/src/structs/ItemBinary.js +++ b/src/structs/ItemBinary.js @@ -4,8 +4,7 @@ // TODO: ItemBinary should be able to merge with right (similar to other items). Or the other items (ItemJSON) should not be able to merge - extra byte + consistency -import { Item } from './Item.js' -import * as stringify from '../utils/structStringify.js' +import { Item, logItemHelper } from './Item.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line @@ -43,6 +42,6 @@ export class ItemBinary extends Item { * @private */ _logString () { - return stringify.logItemHelper('ItemBinary', this) + return logItemHelper('ItemBinary', this) } } diff --git a/src/structs/ItemEmbed.js b/src/structs/ItemEmbed.js index 14cd85d6..252ab1ee 100644 --- a/src/structs/ItemEmbed.js +++ b/src/structs/ItemEmbed.js @@ -2,8 +2,7 @@ * @module structs */ -import { Item } from './Item.js' -import * as stringify from '../utils/structStringify.js' +import { Item, logItemHelper } from './Item.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line @@ -44,6 +43,6 @@ export class ItemEmbed extends Item { * @private */ _logString () { - return stringify.logItemHelper('ItemEmbed', this, `embed:${JSON.stringify(this.embed)}`) + return logItemHelper('ItemEmbed', this, `embed:${JSON.stringify(this.embed)}`) } } diff --git a/src/structs/ItemFormat.js b/src/structs/ItemFormat.js index 40fa3b26..8c0e8056 100644 --- a/src/structs/ItemFormat.js +++ b/src/structs/ItemFormat.js @@ -2,8 +2,7 @@ * @module structs */ -import { Item } from './Item.js' -import * as stringify from '../utils/structStringify.js' +import { Item, logItemHelper } from './Item.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line diff --git a/src/structs/ItemJSON.js b/src/structs/ItemJSON.js index 7e29c8ae..e4933334 100644 --- a/src/structs/ItemJSON.js +++ b/src/structs/ItemJSON.js @@ -2,8 +2,7 @@ * @module structs */ -import { Item, splitHelper } from './Item.js' -import * as stringify from '../utils/structStringify.js' +import { Item, splitHelper, logItemHelper } from './Item.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line @@ -67,7 +66,7 @@ export class ItemJSON extends Item { * @private */ _logString () { - return stringify.logItemHelper('ItemJSON', this, `content:${JSON.stringify(this._content)}`) + return logItemHelper('ItemJSON', this, `content:${JSON.stringify(this._content)}`) } _splitAt (y, diff) { if (diff === 0) { diff --git a/src/structs/ItemString.js b/src/structs/ItemString.js index 0c613bfe..d4baa752 100644 --- a/src/structs/ItemString.js +++ b/src/structs/ItemString.js @@ -2,8 +2,7 @@ * @module structs */ -import { Item, splitHelper } from './Item.js' -import * as stringify from '../utils/structStringify.js' +import { Item, splitHelper, logItemHelper } from './Item.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line @@ -44,7 +43,7 @@ export class ItemString extends Item { * @private */ _logString () { - return stringify.logItemHelper('ItemString', this, `content:"${this._content}"`) + return logItemHelper('ItemString', this, `content:"${this._content}"`) } _splitAt (y, diff) { if (diff === 0) { diff --git a/src/types/YArray.js b/src/types/YArray.js index e31b081d..1e04527a 100644 --- a/src/types/YArray.js +++ b/src/types/YArray.js @@ -5,10 +5,9 @@ import { Type } from '../structs/Type.js' import { ItemJSON } from '../structs/ItemJSON.js' import { ItemString } from '../structs/ItemString.js' -import * as stringify from '../utils/structStringify.js' import { YEvent } from '../utils/YEvent.js' import { Transaction } from '../utils/Transaction.js' // eslint-disable-line -import { Item } from '../structs/Item.js' // eslint-disable-line +import { Item, stringifyItemID, logItemHelper } from '../structs/Item.js' // eslint-disable-line import { ItemBinary } from '../structs/ItemBinary.js' import { isVisible } from '../utils/snapshot.js' @@ -402,6 +401,6 @@ export class YArray extends Type { * @private */ _logString () { - return stringify.logItemHelper('YArray', this, `start:${stringify.stringifyItemID(this._start)}"`) + return logItemHelper('YArray', this, `start:${stringifyItemID(this._start)}"`) } } diff --git a/src/types/YMap.js b/src/types/YMap.js index 514ef2d5..fbcdfe9b 100644 --- a/src/types/YMap.js +++ b/src/types/YMap.js @@ -2,10 +2,9 @@ * @module types */ -import { Item } from '../structs/Item.js' +import { Item, logItemHelper } from '../structs/Item.js' import { Type } from '../structs/Type.js' import { ItemJSON } from '../structs/ItemJSON.js' -import * as stringify from '../utils/structStringify.js' import { YEvent } from '../utils/YEvent.js' import { ItemBinary } from '../structs/ItemBinary.js' import { isVisible } from '../utils/snapshot.js' @@ -208,6 +207,6 @@ export class YMap extends Type { * @private */ _logString () { - return stringify.logItemHelper('YMap', this, `mapSize:${this._map.size}`) + return logItemHelper('YMap', this, `mapSize:${this._map.size}`) } } diff --git a/src/types/YText.js b/src/types/YText.js index c6d5f309..0d78f1de 100644 --- a/src/types/YText.js +++ b/src/types/YText.js @@ -2,10 +2,10 @@ * @module types */ +import { logItemHelper } from '../structs/Item.js' import { ItemEmbed } from '../structs/ItemEmbed.js' import { ItemString } from '../structs/ItemString.js' import { ItemFormat } from '../structs/ItemFormat.js' -import * as stringify from '../utils/structStringify.js' import { YArrayEvent, YArray } from './YArray.js' import { isVisible } from '../utils/snapshot.js' @@ -720,6 +720,6 @@ export class YText extends YArray { * @private */ _logString () { - return stringify.logItemHelper('YText', this) + return logItemHelper('YText', this) } } diff --git a/src/types/YXmlElement.js b/src/types/YXmlElement.js index 8d8ffad1..cd919739 100644 --- a/src/types/YXmlElement.js +++ b/src/types/YXmlElement.js @@ -2,13 +2,13 @@ * @module types */ +import { logItemHelper } from '../structs/Item.js' import { YMap } from './YMap.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line import { YArray } from './YArray.js' import { YXmlEvent } from './YXmlEvent.js' -import * as stringify from '../utils/structStringify.js' /** * Define the elements to which a set of CSS queries apply. @@ -234,7 +234,7 @@ export class YXmlFragment extends YArray { * @private */ _logString () { - return stringify.logItemHelper('YXml', this) + return logItemHelper('YXml', this) } } diff --git a/src/utils/OperationStore.js b/src/utils/OperationStore.js index eb02aabb..4530234d 100644 --- a/src/utils/OperationStore.js +++ b/src/utils/OperationStore.js @@ -6,7 +6,7 @@ import { Tree } from 'lib0/tree.js' import * as ID from '../utils/ID.js' import { getStruct } from './structReferences.js' import { GC } from '../structs/GC.js' -import * as stringify from './structStringify.js' +import * as Item from '../structs/Item.js' export class OperationStore extends Tree { constructor (y) { @@ -18,18 +18,18 @@ export class OperationStore extends Tree { this.iterate(null, null, item => { if (item.constructor === GC) { items.push({ - id: stringify.stringifyItemID(item), + id: Item.stringifyItemID(item), content: item._length, deleted: 'GC' }) } else { items.push({ - id: stringify.stringifyItemID(item), - origin: item._origin === null ? '()' : stringify.stringifyID(item._origin._lastId), - left: item._left === null ? '()' : stringify.stringifyID(item._left._lastId), - right: stringify.stringifyItemID(item._right), - right_origin: stringify.stringifyItemID(item._right_origin), - parent: stringify.stringifyItemID(item._parent), + id: Item.stringifyItemID(item), + origin: item._origin === null ? '()' : Item.stringifyID(item._origin._lastId), + left: item._left === null ? '()' : Item.stringifyID(item._left._lastId), + right: Item.stringifyItemID(item._right), + right_origin: Item.stringifyItemID(item._right_origin), + parent: Item.stringifyItemID(item._parent), parentSub: item._parentSub, deleted: item._deleted, content: JSON.stringify(item._content) diff --git a/src/utils/structStringify.js b/src/utils/structStringify.js deleted file mode 100644 index 53bcd2bc..00000000 --- a/src/utils/structStringify.js +++ /dev/null @@ -1,46 +0,0 @@ - -import * as ID from './ID.js' - -/** - * Stringify an item id. - * - * @param {ID.ID | ID.RootID} id - * @return {string} - */ -export const stringifyID = id => id instanceof ID.ID ? `(${id.user},${id.clock})` : `(${id.name},${id.type})` - -/** - * Stringify an item as ID. HHere, an item could also be a Yjs instance (e.g. item._parent). - * - * @param {Y.Item | Y.Y | null} item - * @return {string} - */ -export const stringifyItemID = item => { - let result - if (item === null) { - result = '()' - } else if (item._id != null) { - result = stringifyID(item._id) - } else { - // must be a Yjs instance - // Don't include Y in this module, so we prevent circular dependencies. - result = 'y' - } - return result -} - -/** - * Helper utility to convert an item to a readable format. - * - * @param {String} name The name of the item class (YText, ItemString, ..). - * @param {Y.Item} item The item instance. - * @param {String} [append] Additional information to append to the returned - * string. - * @return {String} A readable string that represents the item object. - * - */ -export const logItemHelper = (name, item, append) => { - const left = item._left !== null ? stringifyID(item._left._lastId) : '()' - const origin = item._origin !== null ? stringifyID(item._origin._lastId) : '()' - return `${name}(id:${stringifyItemID(item)},left:${left},origin:${origin},right:${stringifyItemID(item._right)},parent:${stringifyItemID(item._parent)},parentSub:${item._parentSub}${append !== undefined ? ' - ' + append : ''})` -}