From 6578727c9cac0d79c6fcc1af5094e4c1ddd72677 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Wed, 3 Apr 2019 13:23:27 +0200 Subject: [PATCH] fixed all type issues --- package-lock.json | 3 +- src/index.js | 3 ++ src/types/YXmlElement.js | 70 +++++++++++++++++++++++++++++++++++++--- src/utils/StructStore.js | 35 ++++++++++++++++++++ src/utils/Y.js | 3 -- src/utils/YEvent.js | 6 ++-- tests/y-xml.tests.js | 16 ++++----- tsconfig.json | 1 - 8 files changed, 116 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index 18eb8e39..9bb20a29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6467,7 +6467,8 @@ "typescript": { "version": "3.3.3333", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3333.tgz", - "integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==" + "integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==", + "dev": true }, "ua-parser-js": { "version": "0.7.18", diff --git a/src/index.js b/src/index.js index ca2fd9cf..990aab25 100644 --- a/src/index.js +++ b/src/index.js @@ -19,3 +19,6 @@ export { YXmlElement as XmlElement, YXmlFragment as XmlFragment } from './types/ export { createRelativePosition, createRelativePositionByOffset, createAbsolutePosition, compareRelativePositions, writeRelativePosition, readRelativePosition, AbsolutePosition, RelativePosition } from './utils/relativePosition.js' export { ID, createID, compareIDs } from './utils/ID.js' export { isParentOf } from './utils/isParentOf.js' + +export { writeStructs, writeStructsFromTransaction, readStructs } from './utils/structEncoding.js' +export { getState, getStates, readStatesAsMap, writeStates } from './utils/StructStore.js' diff --git a/src/types/YXmlElement.js b/src/types/YXmlElement.js index a349c9ee..e03df0d5 100644 --- a/src/types/YXmlElement.js +++ b/src/types/YXmlElement.js @@ -3,15 +3,13 @@ */ import { Transaction } from '../utils/Transaction.js' // eslint-disable-line -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 { YXmlEvent } from './YXmlEvent.js' import { ItemType } from '../structs/ItemType.js' // eslint-disable-line import { YXmlText } from './YXmlText.js' // eslint-disable-line import { YXmlHook } from './YXmlHook.js' // eslint-disable-line -import { AbstractType, typeArrayMap, typeArrayForEach, typeMapGet, typeMapGetAll, typeArrayInsertGenerics } from './AbstractType.js' +import { AbstractType, typeArrayMap, typeArrayForEach, typeMapGet, typeMapGetAll, typeArrayInsertGenerics, typeArrayDelete, typeMapSet, typeMapDelete } from './AbstractType.js' import { Snapshot } from '../utils/Snapshot.js' // eslint-disable-line /** @@ -237,6 +235,37 @@ export class YXmlElement extends YXmlFragment { constructor (nodeName = 'UNDEFINED') { super() this.nodeName = nodeName.toUpperCase() + /** + * @type {Array|null} + */ + this._prelimContent = [] + /** + * @type {Map|null} + */ + this._prelimAttrs = new Map() + } + + /** + * Integrate this type into the Yjs instance. + * + * * Save this struct in the os + * * This type is sent to other client + * * Observer functions are fired + * + * @param {Transaction} transaction The Yjs instance + * @param {ItemType} item + * @private + */ + _integrate (transaction, item) { + super._integrate(transaction, item) + // @ts-ignore + this.insert(0, this._prelimContent) + this._prelimContent = null + // @ts-ignore + this._prelimAttrs.forEach((value, key) => { + this.setAttribute(key, value) + }) + this._prelimContent = null } /** @@ -301,7 +330,14 @@ export class YXmlElement extends YXmlFragment { * @public */ removeAttribute (attributeName) { - return YMap.prototype.delete.call(this, attributeName) + if (this._y !== null) { + this._y.transact(transaction => { + typeMapDelete(transaction, this, attributeName) + }) + } else { + // @ts-ignore + this._prelimAttrs.delete(attributeName) + } } /** @@ -313,7 +349,14 @@ export class YXmlElement extends YXmlFragment { * @public */ setAttribute (attributeName, attributeValue) { - return YMap.prototype.set.call(this, attributeName, attributeValue) + if (this._y !== null) { + this._y.transact(transaction => { + typeMapSet(transaction, this, attributeName, attributeValue) + }) + } else { + // @ts-ignore + this._prelimAttrs.set(attributeName, attributeValue) + } } /** @@ -363,6 +406,23 @@ export class YXmlElement extends YXmlFragment { } } + /** + * Deletes elements starting from an index. + * + * @param {number} index Index at which to start deleting elements + * @param {number} [length=1] The number of elements to remove. Defaults to 1. + */ + delete (index, length = 1) { + if (this._y !== null) { + this._y.transact(transaction => { + typeArrayDelete(transaction, this, index, length) + }) + } else { + // @ts-ignore _prelimContent is defined because this is not yet integrated + this._prelimContent.splice(index, length) + } + } + // TODO: outsource the binding property. /** * Creates a Dom Element that mirrors this YXmlElement. diff --git a/src/utils/StructStore.js b/src/utils/StructStore.js index 771a1045..80fdcde9 100644 --- a/src/utils/StructStore.js +++ b/src/utils/StructStore.js @@ -6,6 +6,8 @@ import { Transaction } from './Transaction.js' // eslint-disable-line import * as map from 'lib0/map.js' import * as math from 'lib0/math.js' import * as error from 'lib0/error.js' +import * as encoding from 'lib0/encoding.js' +import * as decoding from 'lib0/decoding.js' export class StructStore { constructor () { @@ -227,3 +229,36 @@ export const replaceStruct = (store, struct, newStruct) => { * @return {boolean} */ export const exists = (store, id) => id.clock < getState(store, id.client) + +/** + * Read StateMap from Decoder and return as Map + * + * @param {decoding.Decoder} decoder + * @return {Map} + */ +export const readStatesAsMap = decoder => { + const ss = new Map() + const ssLength = decoding.readVarUint(decoder) + for (let i = 0; i < ssLength; i++) { + const client = decoding.readVarUint(decoder) + const clock = decoding.readVarUint(decoder) + ss.set(client, clock) + } + return ss +} + +/** + * Write StateMap to Encoder + * + * @param {encoding.Encoder} encoder + * @param {StructStore} store + */ +export const writeStates = (encoder, store) => { + encoding.writeVarUint(encoder, store.clients.size) + store.clients.forEach((structs, client) => { + const id = structs[structs.length - 1].id + encoding.writeVarUint(encoder, id.client) + encoding.writeVarUint(encoder, id.clock) + }) + return encoder +} diff --git a/src/utils/Y.js b/src/utils/Y.js index aaefd955..829edad5 100644 --- a/src/utils/Y.js +++ b/src/utils/Y.js @@ -199,9 +199,6 @@ export class Y extends Observable { * comments: y.getArray('comments') * } * - * @TODO: implement getText, getArray, .. - * @TODO: Decide wether to use define() or get() and then use it consistently - * * @param {string} name * @param {Function} TypeConstructor The constructor of the type definition * @return {AbstractType} The created type. Constructed with TypeConstructor diff --git a/src/utils/YEvent.js b/src/utils/YEvent.js index d0da6e09..999c1f88 100644 --- a/src/utils/YEvent.js +++ b/src/utils/YEvent.js @@ -13,18 +13,18 @@ import { isDeleted } from './DeleteSet.js' */ export class YEvent { /** - * @param {AbstractType target The changed type. + * @param {AbstractType} target The changed type. * @param {Transaction} transaction */ constructor (target, transaction) { /** * The type on which this event was created on. - * @type {AbstractType + * @type {AbstractType} */ this.target = target /** * The current target on which the observe callback is called. - * @type {AbstractType + * @type {AbstractType} */ this.currentTarget = target /** diff --git a/tests/y-xml.tests.js b/tests/y-xml.tests.js index 60d0748b..ad25d757 100644 --- a/tests/y-xml.tests.js +++ b/tests/y-xml.tests.js @@ -19,18 +19,18 @@ export const testSetProperty = tc => { */ export const testEvents = tc => { const { testConnector, users, xml0, xml1 } = init(tc, { users: 2 }) - let event = { attributesChanged: new Set() } - let remoteEvent = { attributesChanged: new Set() } + /** + * @type {any} + */ + let event + /** + * @type {any} + */ + let remoteEvent xml0.observe(e => { - delete e._content - delete e.nodes - delete e.values event = e }) xml1.observe(e => { - delete e._content - delete e.nodes - delete e.values remoteEvent = e }) xml0.setAttribute('key', 'value') diff --git a/tsconfig.json b/tsconfig.json index 884d76d2..d7f1fa24 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -55,7 +55,6 @@ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ "maxNodeModuleJsDepth": 5, - "typeRoots": ["./src/utils/typedefs.js"], // "types": ["./src/utils/typedefs.js"] }, "include": ["./src/**/*", "./tests/**/*"],