Comparing version 13.4.14 to 13.5.0
@@ -1,1 +0,1 @@ | ||
export { Doc, Transaction, YArray as Array, YMap as Map, YText as Text, YXmlText as XmlText, YXmlHook as XmlHook, YXmlElement as XmlElement, YXmlFragment as XmlFragment, YXmlEvent, YMapEvent, YArrayEvent, YTextEvent, YEvent, Item, AbstractStruct, GC, ContentBinary, ContentDeleted, ContentEmbed, ContentFormat, ContentJSON, ContentAny, ContentString, ContentType, AbstractType, RelativePosition, getTypeChildren, createRelativePositionFromTypeIndex, createRelativePositionFromJSON, createAbsolutePositionFromRelativePosition, compareRelativePositions, ID, createID, compareIDs, getState, Snapshot, createSnapshot, createDeleteSet, createDeleteSetFromStructStore, snapshot, emptySnapshot, findRootTypeKey, getItem, typeListToArraySnapshot, typeMapGetSnapshot, createDocFromSnapshot, iterateDeletedStructs, applyUpdate, applyUpdateV2, readUpdate, readUpdateV2, encodeStateAsUpdate, encodeStateAsUpdateV2, encodeStateVector, encodeStateVectorV2, UndoManager, decodeSnapshot, encodeSnapshot, decodeSnapshotV2, encodeSnapshotV2, decodeStateVector, decodeStateVectorV2, encodeRelativePosition, decodeRelativePosition, relativePositionToJSON, isDeleted, isParentOf, equalSnapshots, PermanentUserData, tryGc, transact, AbstractConnector, logType } from "./internals.js"; | ||
export { Doc, Transaction, YArray as Array, YMap as Map, YText as Text, YXmlText as XmlText, YXmlHook as XmlHook, YXmlElement as XmlElement, YXmlFragment as XmlFragment, YXmlEvent, YMapEvent, YArrayEvent, YTextEvent, YEvent, Item, AbstractStruct, GC, ContentBinary, ContentDeleted, ContentEmbed, ContentFormat, ContentJSON, ContentAny, ContentString, ContentType, AbstractType, RelativePosition, getTypeChildren, createRelativePositionFromTypeIndex, createRelativePositionFromJSON, createAbsolutePositionFromRelativePosition, compareRelativePositions, ID, createID, compareIDs, getState, Snapshot, createSnapshot, createDeleteSet, createDeleteSetFromStructStore, snapshot, emptySnapshot, findRootTypeKey, getItem, typeListToArraySnapshot, typeMapGetSnapshot, createDocFromSnapshot, iterateDeletedStructs, applyUpdate, applyUpdateV2, readUpdate, readUpdateV2, encodeStateAsUpdate, encodeStateAsUpdateV2, encodeStateVector, UndoManager, decodeSnapshot, encodeSnapshot, decodeSnapshotV2, encodeSnapshotV2, decodeStateVector, logUpdate, logUpdateV2, relativePositionToJSON, isDeleted, isParentOf, equalSnapshots, PermanentUserData, tryGc, transact, AbstractConnector, logType, mergeUpdates, mergeUpdatesV2, parseUpdateMeta, parseUpdateMetaV2, encodeStateVectorFromUpdate, encodeStateVectorFromUpdateV2, encodeRelativePosition, decodeRelativePosition, diffUpdate, diffUpdateV2 } from "./internals.js"; |
@@ -17,2 +17,3 @@ export * from "./utils/AbstractConnector.js"; | ||
export * from "./utils/UndoManager.js"; | ||
export * from "./utils/updates.js"; | ||
export * from "./utils/YEvent.js"; | ||
@@ -40,1 +41,2 @@ export * from "./types/AbstractType.js"; | ||
export * from "./structs/Item.js"; | ||
export * from "./structs/Skip.js"; |
@@ -22,7 +22,7 @@ export class AbstractStruct { | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder The encoder to write data to. | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to. | ||
* @param {number} offset | ||
* @param {number} encodingRef | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number, encodingRef: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number, encodingRef: number): void; | ||
/** | ||
@@ -35,3 +35,4 @@ * @param {Transaction} transaction | ||
import { ID } from "../utils/ID.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { Transaction } from "../utils/Transaction.js"; |
@@ -50,6 +50,6 @@ export class ContentAny { | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -60,7 +60,9 @@ * @return {number} | ||
} | ||
export function readContentAny(decoder: AbstractUpdateDecoder): ContentAny; | ||
export function readContentAny(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentAny; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { Item } from "./Item.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -47,6 +47,6 @@ export class ContentBinary { | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -57,7 +57,9 @@ * @return {number} | ||
} | ||
export function readContentBinary(decoder: AbstractUpdateDecoder): ContentBinary; | ||
export function readContentBinary(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentBinary; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { Item } from "./Item.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -47,6 +47,6 @@ export class ContentDeleted { | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -57,7 +57,9 @@ * @return {number} | ||
} | ||
export function readContentDeleted(decoder: AbstractUpdateDecoder): ContentDeleted; | ||
export function readContentDeleted(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentDeleted; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { Item } from "./Item.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -54,6 +54,6 @@ /** | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -64,3 +64,3 @@ * @return {number} | ||
} | ||
export function readContentDoc(decoder: AbstractUpdateDecoder): ContentDoc; | ||
export function readContentDoc(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentDoc; | ||
import { Doc } from "../utils/Doc.js"; | ||
@@ -70,3 +70,5 @@ import { Transaction } from "../utils/Transaction.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -50,6 +50,6 @@ /** | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -60,7 +60,9 @@ * @return {number} | ||
} | ||
export function readContentEmbed(decoder: AbstractUpdateDecoder): ContentEmbed; | ||
export function readContentEmbed(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentEmbed; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { Item } from "./Item.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -52,6 +52,6 @@ /** | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -62,7 +62,9 @@ * @return {number} | ||
} | ||
export function readContentFormat(decoder: AbstractUpdateDecoder): ContentFormat; | ||
export function readContentFormat(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentFormat; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { Item } from "./Item.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -53,6 +53,6 @@ /** | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -63,7 +63,9 @@ * @return {number} | ||
} | ||
export function readContentJSON(decoder: AbstractUpdateDecoder): ContentJSON; | ||
export function readContentJSON(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentJSON; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { Item } from "./Item.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -53,6 +53,6 @@ /** | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -63,7 +63,9 @@ * @return {number} | ||
} | ||
export function readContentString(decoder: AbstractUpdateDecoder): ContentString; | ||
export function readContentString(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentString; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { Item } from "./Item.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
/** | ||
* @type {Array<function(AbstractUpdateDecoder):AbstractType<any>>} | ||
* @type {Array<function(UpdateDecoderV1 | UpdateDecoderV2):AbstractType<any>>} | ||
* @private | ||
*/ | ||
export const typeRefs: Array<(arg0: AbstractUpdateDecoder) => AbstractType<any>>; | ||
export const typeRefs: Array<(arg0: UpdateDecoderV1 | UpdateDecoderV2) => AbstractType<any>>; | ||
export const YArrayRefID: 0; | ||
@@ -65,6 +65,6 @@ export const YMapRefID: 1; | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -75,4 +75,5 @@ * @return {number} | ||
} | ||
export function readContentType(decoder: AbstractUpdateDecoder): ContentType; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
export function readContentType(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentType; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; | ||
import { AbstractType } from "../types/AbstractType.js"; | ||
@@ -82,3 +83,4 @@ import { Transaction } from "../utils/Transaction.js"; | ||
import { StructStore } from "../utils/StructStore.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { YEvent } from "../utils/YEvent.js"; |
@@ -119,9 +119,9 @@ export function followRedone(store: StructStore, id: ID): { | ||
} | ||
export function readItemContent(decoder: AbstractUpdateDecoder, info: number): AbstractContent; | ||
export function readItemContent(decoder: UpdateDecoderV1 | UpdateDecoderV2, info: number): AbstractContent; | ||
/** | ||
* A lookup map for reading Item content. | ||
* | ||
* @type {Array<function(AbstractUpdateDecoder):AbstractContent>} | ||
* @type {Array<function(UpdateDecoderV1 | UpdateDecoderV2):AbstractContent>} | ||
*/ | ||
export const contentRefs: Array<(arg0: AbstractUpdateDecoder) => AbstractContent>; | ||
export const contentRefs: Array<(arg0: UpdateDecoderV1 | UpdateDecoderV2) => AbstractContent>; | ||
/** | ||
@@ -177,6 +177,6 @@ * Do not implement this class! | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
*/ | ||
write(encoder: AbstractUpdateEncoder, offset: number): void; | ||
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void; | ||
/** | ||
@@ -192,3 +192,5 @@ * @return {number} | ||
import { AbstractType } from "../types/AbstractType.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; |
@@ -75,5 +75,5 @@ export class ArraySearchMarker { | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
*/ | ||
_write(encoder: AbstractUpdateEncoder): void; | ||
_write(encoder: UpdateEncoderV1 | UpdateEncoderV2): void; | ||
/** | ||
@@ -156,3 +156,4 @@ * The first non-deleted item | ||
import { YEvent } from "../utils/YEvent.js"; | ||
import { AbstractUpdateEncoder } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js"; | ||
import { Snapshot } from "../utils/Snapshot.js"; |
@@ -111,6 +111,7 @@ /** | ||
} | ||
export function readYArray(decoder: AbstractUpdateDecoder): YArray<any>; | ||
export function readYArray(decoder: UpdateDecoderV1 | UpdateDecoderV2): YArray<any>; | ||
import { YEvent } from "../utils/YEvent.js"; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { AbstractType } from "./AbstractType.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -96,6 +96,7 @@ /** | ||
} | ||
export function readYMap(decoder: AbstractUpdateDecoder): YMap<any>; | ||
export function readYMap(decoder: UpdateDecoderV1 | UpdateDecoderV2): YMap<any>; | ||
import { YEvent } from "../utils/YEvent.js"; | ||
import { Transaction } from "../utils/Transaction.js"; | ||
import { AbstractType } from "./AbstractType.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -224,3 +224,3 @@ export class ItemTextListPosition { | ||
} | ||
export function readYText(decoder: AbstractUpdateDecoder): YText; | ||
export function readYText(decoder: UpdateDecoderV1 | UpdateDecoderV2): YText; | ||
/** | ||
@@ -244,2 +244,3 @@ * Attributes that can be assigned to a selection of text. | ||
import { ID } from "../utils/ID.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -62,6 +62,7 @@ /** | ||
} | ||
export function readYXmlElement(decoder: AbstractUpdateDecoder): YXmlElement; | ||
export function readYXmlElement(decoder: UpdateDecoderV1 | UpdateDecoderV2): YXmlElement; | ||
import { YXmlFragment } from "./YXmlFragment.js"; | ||
import { YXmlText } from "./YXmlText.js"; | ||
import { Snapshot } from "../utils/Snapshot.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -198,3 +198,3 @@ /** | ||
} | ||
export function readYXmlFragment(decoder: AbstractUpdateDecoder): YXmlFragment; | ||
export function readYXmlFragment(decoder: UpdateDecoderV1 | UpdateDecoderV2): YXmlFragment; | ||
/** | ||
@@ -215,2 +215,3 @@ * Define the elements to which a set of CSS queries apply. | ||
import { YXmlEvent } from "./YXmlEvent.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -34,4 +34,5 @@ /** | ||
} | ||
export function readYXmlHook(decoder: AbstractUpdateDecoder): YXmlHook; | ||
export function readYXmlHook(decoder: UpdateDecoderV1 | UpdateDecoderV2): YXmlHook; | ||
import { YMap } from "./YMap.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -34,5 +34,6 @@ /** | ||
} | ||
export function readYXmlText(decoder: AbstractUpdateDecoder): YXmlText; | ||
export function readYXmlText(decoder: UpdateDecoderV1 | UpdateDecoderV2): YXmlText; | ||
import { YText } from "./YText.js"; | ||
import { YXmlElement } from "./YXmlElement.js"; | ||
import { AbstractUpdateDecoder } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js"; |
@@ -37,5 +37,5 @@ export class DeleteItem { | ||
export function createDeleteSetFromStructStore(ss: StructStore): DeleteSet; | ||
export function writeDeleteSet(encoder: AbstractDSEncoder, ds: DeleteSet): void; | ||
export function readDeleteSet(decoder: AbstractDSDecoder): DeleteSet; | ||
export function readAndApplyDeleteSet(decoder: AbstractDSDecoder, transaction: Transaction, store: StructStore): void; | ||
export function writeDeleteSet(encoder: DSEncoderV1 | DSEncoderV2, ds: DeleteSet): void; | ||
export function readDeleteSet(decoder: DSDecoderV1 | DSDecoderV2): DeleteSet; | ||
export function readAndApplyDeleteSet(decoder: DSDecoderV1 | DSDecoderV2, transaction: Transaction, store: StructStore): Uint8Array | null; | ||
import { Transaction } from "./Transaction.js"; | ||
@@ -46,3 +46,5 @@ import { GC } from "../structs/GC.js"; | ||
import { StructStore } from "./StructStore.js"; | ||
import { AbstractDSEncoder } from "./UpdateEncoder.js"; | ||
import { AbstractDSDecoder } from "./UpdateDecoder.js"; | ||
import { DSEncoderV1 } from "./UpdateEncoder.js"; | ||
import { DSEncoderV2 } from "./UpdateEncoder.js"; | ||
import { DSDecoderV1 } from "./UpdateDecoder.js"; | ||
import { DSDecoderV2 } from "./UpdateDecoder.js"; |
@@ -1,40 +0,33 @@ | ||
export let DefaultDSEncoder: typeof DSEncoderV1; | ||
export let DefaultDSDecoder: typeof DSDecoderV1; | ||
export let DefaultUpdateEncoder: typeof UpdateEncoderV1; | ||
export let DefaultUpdateDecoder: typeof UpdateDecoderV1; | ||
export function useV1Encoding(): void; | ||
export function useV2Encoding(): void; | ||
export function writeClientsStructs(encoder: AbstractUpdateEncoder, store: StructStore, _sm: Map<number, number>): void; | ||
export function readClientsStructRefs(decoder: AbstractUpdateDecoder, clientRefs: Map<number, Array<GC | Item>>, doc: Doc): Map<number, Array<GC | Item>>; | ||
export function tryResumePendingDeleteReaders(transaction: Transaction, store: StructStore): void; | ||
export function writeStructsFromTransaction(encoder: AbstractUpdateEncoder, transaction: Transaction): void; | ||
export function readStructs(decoder: AbstractUpdateDecoder, transaction: Transaction, store: StructStore): void; | ||
export function readUpdateV2(decoder: decoding.Decoder, ydoc: Doc, transactionOrigin?: any, structDecoder?: AbstractUpdateDecoder | undefined): void; | ||
export function writeClientsStructs(encoder: UpdateEncoderV1 | UpdateEncoderV2, store: StructStore, _sm: Map<number, number>): void; | ||
export function readClientsStructRefs(decoder: UpdateDecoderV1 | UpdateDecoderV2, doc: Doc): Map<number, { | ||
i: number; | ||
refs: Array<Item | GC>; | ||
}>; | ||
export function writeStructsFromTransaction(encoder: UpdateEncoderV1 | UpdateEncoderV2, transaction: Transaction): void; | ||
export function readUpdateV2(decoder: decoding.Decoder, ydoc: Doc, transactionOrigin?: any, structDecoder?: UpdateDecoderV1 | UpdateDecoderV2 | undefined): void; | ||
export function readUpdate(decoder: decoding.Decoder, ydoc: Doc, transactionOrigin?: any): void; | ||
export function applyUpdateV2(ydoc: Doc, update: Uint8Array, transactionOrigin?: any, YDecoder?: typeof UpdateDecoderV1 | typeof UpdateDecoderV2 | undefined): void; | ||
export function applyUpdate(ydoc: Doc, update: Uint8Array, transactionOrigin?: any): void; | ||
export function writeStateAsUpdate(encoder: AbstractUpdateEncoder, doc: Doc, targetStateVector?: Map<number, number> | undefined): void; | ||
export function encodeStateAsUpdateV2(doc: Doc, encodedTargetStateVector?: Uint8Array | undefined, encoder?: AbstractUpdateEncoder | undefined): Uint8Array; | ||
export function writeStateAsUpdate(encoder: UpdateEncoderV1 | UpdateEncoderV2, doc: Doc, targetStateVector?: Map<number, number> | undefined): void; | ||
export function encodeStateAsUpdateV2(doc: Doc, encodedTargetStateVector?: Uint8Array | undefined, encoder?: UpdateEncoderV2 | UpdateEncoderV1 | undefined): Uint8Array; | ||
export function encodeStateAsUpdate(doc: Doc, encodedTargetStateVector?: Uint8Array | undefined): Uint8Array; | ||
export function readStateVector(decoder: AbstractDSDecoder): Map<number, number>; | ||
export function decodeStateVectorV2(decodedState: Uint8Array): Map<number, number>; | ||
export function readStateVector(decoder: DSDecoderV1 | DSDecoderV2): Map<number, number>; | ||
export function decodeStateVector(decodedState: Uint8Array): Map<number, number>; | ||
export function writeStateVector(encoder: AbstractDSEncoder, sv: Map<number, number>): AbstractDSEncoder; | ||
export function writeDocumentStateVector(encoder: AbstractDSEncoder, doc: Doc): AbstractDSEncoder; | ||
export function encodeStateVectorV2(doc: Doc, encoder?: AbstractDSEncoder | undefined): Uint8Array; | ||
export function encodeStateVector(doc: Doc): Uint8Array; | ||
import { DSEncoderV1 } from "./UpdateEncoder.js"; | ||
import { DSDecoderV1 } from "./UpdateDecoder.js"; | ||
export function writeStateVector(encoder: DSEncoderV1 | DSEncoderV2, sv: Map<number, number>): DSEncoderV1 | DSEncoderV2; | ||
export function writeDocumentStateVector(encoder: DSEncoderV1 | DSEncoderV2, doc: Doc): DSEncoderV1 | DSEncoderV2; | ||
export function encodeStateVectorV2(doc: Doc | Map<number, number>, encoder?: DSEncoderV1 | DSEncoderV2 | undefined): Uint8Array; | ||
export function encodeStateVector(doc: Doc | Map<number, number>): Uint8Array; | ||
import { UpdateEncoderV1 } from "./UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "./UpdateEncoder.js"; | ||
import { StructStore } from "./StructStore.js"; | ||
import { UpdateDecoderV1 } from "./UpdateDecoder.js"; | ||
import { AbstractUpdateEncoder } from "./UpdateEncoder.js"; | ||
import { StructStore } from "./StructStore.js"; | ||
import { AbstractUpdateDecoder } from "./UpdateDecoder.js"; | ||
import { UpdateDecoderV2 } from "./UpdateDecoder.js"; | ||
import { Doc } from "./Doc.js"; | ||
import { Item } from "../structs/Item.js"; | ||
import { GC } from "../structs/GC.js"; | ||
import { Item } from "../structs/Item.js"; | ||
import { Doc } from "./Doc.js"; | ||
import { Transaction } from "./Transaction.js"; | ||
import * as decoding from "lib0/decoding"; | ||
import { UpdateDecoderV2 } from "./UpdateDecoder.js"; | ||
import { AbstractDSDecoder } from "./UpdateDecoder.js"; | ||
import { AbstractDSEncoder } from "./UpdateEncoder.js"; | ||
import { DSDecoderV1 } from "./UpdateDecoder.js"; | ||
import { DSDecoderV2 } from "./UpdateDecoder.js"; | ||
import { DSEncoderV1 } from "./UpdateEncoder.js"; | ||
import { DSEncoderV2 } from "./UpdateEncoder.js"; |
@@ -18,5 +18,5 @@ export class Snapshot { | ||
export function equalSnapshots(snap1: Snapshot, snap2: Snapshot): boolean; | ||
export function encodeSnapshotV2(snapshot: Snapshot, encoder?: AbstractDSEncoder | undefined): Uint8Array; | ||
export function encodeSnapshotV2(snapshot: Snapshot, encoder?: DSEncoderV1 | DSEncoderV2 | undefined): Uint8Array; | ||
export function encodeSnapshot(snapshot: Snapshot): Uint8Array; | ||
export function decodeSnapshotV2(buf: Uint8Array, decoder?: AbstractDSDecoder | undefined): Snapshot; | ||
export function decodeSnapshotV2(buf: Uint8Array, decoder?: DSDecoderV1 | DSDecoderV2 | undefined): Snapshot; | ||
export function decodeSnapshot(buf: Uint8Array): Snapshot; | ||
@@ -30,6 +30,8 @@ export function createSnapshot(ds: DeleteSet, sm: Map<number, number>): Snapshot; | ||
import { DeleteSet } from "./DeleteSet.js"; | ||
import { AbstractDSEncoder } from "./UpdateEncoder.js"; | ||
import { AbstractDSDecoder } from "./UpdateDecoder.js"; | ||
import { DSEncoderV1 } from "./UpdateEncoder.js"; | ||
import { DSEncoderV2 } from "./UpdateEncoder.js"; | ||
import { DSDecoderV1 } from "./UpdateDecoder.js"; | ||
import { DSDecoderV2 } from "./UpdateDecoder.js"; | ||
import { Doc } from "./Doc.js"; | ||
import { Item } from "../structs/Item.js"; | ||
import { Transaction } from "./Transaction.js"; |
@@ -7,23 +7,12 @@ export class StructStore { | ||
/** | ||
* Store incompleted struct reads here | ||
* `i` denotes to the next read operation | ||
* We could shift the array of refs instead, but shift is incredible | ||
* slow in Chrome for arrays with more than 100k elements | ||
* @see tryResumePendingStructRefs | ||
* @type {Map<number,{i:number,refs:Array<GC|Item>}>} | ||
* @type {null | { missing: Map<number, number>, update: Uint8Array }} | ||
*/ | ||
pendingClientsStructRefs: Map<number, { | ||
i: number; | ||
refs: Array<GC | Item>; | ||
}>; | ||
pendingStructs: { | ||
missing: Map<number, number>; | ||
update: Uint8Array; | ||
} | null; | ||
/** | ||
* Stack of pending structs waiting for struct dependencies | ||
* Maximum length of stack is structReaders.size | ||
* @type {Array<GC|Item>} | ||
* @type {null | Uint8Array} | ||
*/ | ||
pendingStack: Array<GC | Item>; | ||
/** | ||
* @type {Array<DSDecoderV2>} | ||
*/ | ||
pendingDeleteReaders: Array<DSDecoderV2>; | ||
pendingDs: null | Uint8Array; | ||
} | ||
@@ -49,4 +38,3 @@ export function getStateVector(store: StructStore): Map<number, number>; | ||
import { Item } from "../structs/Item.js"; | ||
import { DSDecoderV2 } from "./UpdateDecoder.js"; | ||
import { ID } from "./ID.js"; | ||
import { Transaction } from "./Transaction.js"; |
@@ -96,3 +96,3 @@ /** | ||
} | ||
export function writeUpdateMessageFromTransaction(encoder: AbstractUpdateEncoder, transaction: Transaction): boolean; | ||
export function writeUpdateMessageFromTransaction(encoder: UpdateEncoderV1 | UpdateEncoderV2, transaction: Transaction): boolean; | ||
export function nextID(transaction: Transaction): import("./ID.js").ID; | ||
@@ -107,4 +107,5 @@ export function addChangedTypeToTransaction(transaction: Transaction, type: AbstractType<YEvent>, parentSub: string | null): void; | ||
import { AbstractStruct } from "../structs/AbstractStruct.js"; | ||
import { AbstractUpdateEncoder } from "./UpdateEncoder.js"; | ||
import { UpdateEncoderV1 } from "./UpdateEncoder.js"; | ||
import { UpdateEncoderV2 } from "./UpdateEncoder.js"; | ||
import { StructStore } from "./StructStore.js"; | ||
import { Item } from "../structs/Item.js"; |
@@ -1,2 +0,2 @@ | ||
export class AbstractDSDecoder { | ||
export class DSDecoderV1 { | ||
/** | ||
@@ -17,3 +17,3 @@ * @param {decoding.Decoder} decoder | ||
} | ||
export class AbstractUpdateDecoder extends AbstractDSDecoder { | ||
export class UpdateDecoderV1 extends DSDecoderV1 { | ||
/** | ||
@@ -34,4 +34,2 @@ * @param {decoding.Decoder} decoder | ||
* Use this in favor of readID whenever possible to reduce the number of objects created. | ||
* | ||
* @return {number} | ||
*/ | ||
@@ -80,3 +78,3 @@ readClient(): number; | ||
} | ||
export class DSDecoderV1 { | ||
export class DSDecoderV2 { | ||
/** | ||
@@ -86,2 +84,6 @@ * @param {decoding.Decoder} decoder | ||
constructor(decoder: decoding.Decoder); | ||
/** | ||
* @private | ||
*/ | ||
private dsCurrVal; | ||
restDecoder: decoding.Decoder; | ||
@@ -98,72 +100,2 @@ resetDsCurVal(): void; | ||
} | ||
export class UpdateDecoderV1 extends DSDecoderV1 { | ||
/** | ||
* @param {decoding.Decoder} decoder | ||
*/ | ||
constructor(decoder: decoding.Decoder); | ||
/** | ||
* @return {ID} | ||
*/ | ||
readLeftID(): ID; | ||
/** | ||
* @return {ID} | ||
*/ | ||
readRightID(): ID; | ||
/** | ||
* Read the next client id. | ||
* Use this in favor of readID whenever possible to reduce the number of objects created. | ||
*/ | ||
readClient(): number; | ||
/** | ||
* @return {number} info An unsigned 8-bit integer | ||
*/ | ||
readInfo(): number; | ||
/** | ||
* @return {string} | ||
*/ | ||
readString(): string; | ||
/** | ||
* @return {boolean} isKey | ||
*/ | ||
readParentInfo(): boolean; | ||
/** | ||
* @return {number} info An unsigned 8-bit integer | ||
*/ | ||
readTypeRef(): number; | ||
/** | ||
* Write len of a struct - well suited for Opt RLE encoder. | ||
* | ||
* @return {number} len | ||
*/ | ||
readLen(): number; | ||
/** | ||
* @return {any} | ||
*/ | ||
readAny(): any; | ||
/** | ||
* @return {Uint8Array} | ||
*/ | ||
readBuf(): Uint8Array; | ||
/** | ||
* Legacy implementation uses JSON parse. We use any-decoding in v2. | ||
* | ||
* @return {any} | ||
*/ | ||
readJSON(): any; | ||
/** | ||
* @return {string} | ||
*/ | ||
readKey(): string; | ||
} | ||
export class DSDecoderV2 { | ||
/** | ||
* @param {decoding.Decoder} decoder | ||
*/ | ||
constructor(decoder: decoding.Decoder); | ||
dsCurrVal: number; | ||
restDecoder: decoding.Decoder; | ||
resetDsCurVal(): void; | ||
readDsClock(): number; | ||
readDsLen(): number; | ||
} | ||
export class UpdateDecoderV2 extends DSDecoderV2 { | ||
@@ -170,0 +102,0 @@ /** |
@@ -1,74 +0,1 @@ | ||
export class AbstractDSEncoder { | ||
restEncoder: encoding.Encoder; | ||
/** | ||
* @return {Uint8Array} | ||
*/ | ||
toUint8Array(): Uint8Array; | ||
/** | ||
* Resets the ds value to 0. | ||
* The v2 encoder uses this information to reset the initial diff value. | ||
*/ | ||
resetDsCurVal(): void; | ||
/** | ||
* @param {number} clock | ||
*/ | ||
writeDsClock(clock: number): void; | ||
/** | ||
* @param {number} len | ||
*/ | ||
writeDsLen(len: number): void; | ||
} | ||
export class AbstractUpdateEncoder extends AbstractDSEncoder { | ||
/** | ||
* @param {ID} id | ||
*/ | ||
writeLeftID(id: ID): void; | ||
/** | ||
* @param {ID} id | ||
*/ | ||
writeRightID(id: ID): void; | ||
/** | ||
* Use writeClient and writeClock instead of writeID if possible. | ||
* @param {number} client | ||
*/ | ||
writeClient(client: number): void; | ||
/** | ||
* @param {number} info An unsigned 8-bit integer | ||
*/ | ||
writeInfo(info: number): void; | ||
/** | ||
* @param {string} s | ||
*/ | ||
writeString(s: string): void; | ||
/** | ||
* @param {boolean} isYKey | ||
*/ | ||
writeParentInfo(isYKey: boolean): void; | ||
/** | ||
* @param {number} info An unsigned 8-bit integer | ||
*/ | ||
writeTypeRef(info: number): void; | ||
/** | ||
* Write len of a struct - well suited for Opt RLE encoder. | ||
* | ||
* @param {number} len | ||
*/ | ||
writeLen(len: number): void; | ||
/** | ||
* @param {any} any | ||
*/ | ||
writeAny(any: any): void; | ||
/** | ||
* @param {Uint8Array} buf | ||
*/ | ||
writeBuf(buf: Uint8Array): void; | ||
/** | ||
* @param {any} embed | ||
*/ | ||
writeJSON(embed: any): void; | ||
/** | ||
* @param {string} key | ||
*/ | ||
writeKey(key: string): void; | ||
} | ||
export class DSEncoderV1 { | ||
@@ -75,0 +2,0 @@ restEncoder: encoding.Encoder; |
{ | ||
"name": "yjs", | ||
"version": "13.4.14", | ||
"version": "13.5.0", | ||
"description": "Shared Editing Library", | ||
@@ -5,0 +5,0 @@ "main": "./dist/yjs.cjs", |
@@ -58,3 +58,2 @@ | ||
encodeStateVector, | ||
encodeStateVectorV2, | ||
UndoManager, | ||
@@ -66,5 +65,4 @@ decodeSnapshot, | ||
decodeStateVector, | ||
decodeStateVectorV2, | ||
encodeRelativePosition, | ||
decodeRelativePosition, | ||
logUpdate, | ||
logUpdateV2, | ||
relativePositionToJSON, | ||
@@ -78,3 +76,13 @@ isDeleted, | ||
AbstractConnector, | ||
logType | ||
logType, | ||
mergeUpdates, | ||
mergeUpdatesV2, | ||
parseUpdateMeta, | ||
parseUpdateMetaV2, | ||
encodeStateVectorFromUpdate, | ||
encodeStateVectorFromUpdateV2, | ||
encodeRelativePosition, | ||
decodeRelativePosition, | ||
diffUpdate, | ||
diffUpdateV2 | ||
} from './internals.js' |
@@ -18,2 +18,3 @@ | ||
export * from './utils/UndoManager.js' | ||
export * from './utils/updates.js' | ||
export * from './utils/YEvent.js' | ||
@@ -43,1 +44,2 @@ | ||
export * from './structs/Item.js' | ||
export * from './structs/Skip.js' |
import { | ||
AbstractUpdateEncoder, ID, Transaction // eslint-disable-line | ||
UpdateEncoderV1, UpdateEncoderV2, ID, Transaction // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -37,3 +37,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder The encoder to write data to. | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to. | ||
* @param {number} offset | ||
@@ -40,0 +40,0 @@ * @param {number} encodingRef |
import { | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, Transaction, Item, StructStore // eslint-disable-line | ||
UpdateEncoderV1, UpdateEncoderV2, UpdateDecoderV1, UpdateDecoderV2, Transaction, Item, StructStore // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -77,3 +77,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -99,3 +99,3 @@ */ | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {ContentAny} | ||
@@ -102,0 +102,0 @@ */ |
import { | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Item, Transaction // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -73,3 +73,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -90,5 +90,5 @@ */ | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2 } decoder | ||
* @return {ContentBinary} | ||
*/ | ||
export const readContentBinary = decoder => new ContentBinary(decoder.readBuf()) |
import { | ||
addToDeleteSet, | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Item, Transaction // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -80,3 +80,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -99,5 +99,5 @@ */ | ||
* | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2 } decoder | ||
* @return {ContentDeleted} | ||
*/ | ||
export const readContentDeleted = decoder => new ContentDeleted(decoder.readLen()) |
import { | ||
Doc, AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Transaction, Item // eslint-disable-line | ||
Doc, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, Item // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -113,3 +113,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -133,5 +133,5 @@ */ | ||
* | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {ContentDoc} | ||
*/ | ||
export const readContentDoc = decoder => new ContentDoc(new Doc({ guid: decoder.readString(), ...decoder.readAny() })) |
import { | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Item, Transaction // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -77,3 +77,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -96,5 +96,5 @@ */ | ||
* | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {ContentEmbed} | ||
*/ | ||
export const readContentEmbed = decoder => new ContentEmbed(decoder.readJSON()) |
import { | ||
AbstractType, AbstractUpdateDecoder, AbstractUpdateEncoder, Item, StructStore, Transaction // eslint-disable-line | ||
AbstractType, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Item, StructStore, Transaction // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -83,3 +83,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -101,5 +101,5 @@ */ | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {ContentFormat} | ||
*/ | ||
export const readContentFormat = decoder => new ContentFormat(decoder.readString(), decoder.readJSON()) |
import { | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, Transaction, Item, StructStore // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Transaction, Item, StructStore // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -80,3 +80,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -104,3 +104,3 @@ */ | ||
* | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {ContentJSON} | ||
@@ -107,0 +107,0 @@ */ |
import { | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, Transaction, Item, StructStore // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Transaction, Item, StructStore // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -91,3 +91,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -110,5 +110,5 @@ */ | ||
* | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {ContentString} | ||
*/ | ||
export const readContentString = decoder => new ContentString(decoder.readString()) |
@@ -10,3 +10,3 @@ | ||
readYXmlText, | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, StructStore, Transaction, Item, YEvent, AbstractType // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, Item, YEvent, AbstractType // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -17,3 +17,3 @@ | ||
/** | ||
* @type {Array<function(AbstractUpdateDecoder):AbstractType<any>>} | ||
* @type {Array<function(UpdateDecoderV1 | UpdateDecoderV2):AbstractType<any>>} | ||
* @private | ||
@@ -153,3 +153,3 @@ */ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -172,5 +172,5 @@ */ | ||
* | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {ContentType} | ||
*/ | ||
export const readContentType = decoder => new ContentType(typeRefs[decoder.readTypeRef()](decoder)) |
@@ -5,3 +5,3 @@ | ||
addStruct, | ||
AbstractUpdateEncoder, StructStore, Transaction, ID // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, ID // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -26,2 +26,5 @@ | ||
mergeWith (right) { | ||
if (this.constructor !== right.constructor) { | ||
return false | ||
} | ||
this.length += right.length | ||
@@ -44,3 +47,3 @@ return true | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -47,0 +50,0 @@ */ |
@@ -25,3 +25,3 @@ | ||
addChangedTypeToTransaction, | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, ContentType, ContentDeleted, StructStore, ID, AbstractType, Transaction // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ContentType, ContentDeleted, StructStore, ID, AbstractType, Transaction // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -558,2 +558,3 @@ | ||
if ( | ||
this.constructor === right.constructor && | ||
compareIDs(right.origin, this.lastId) && | ||
@@ -624,3 +625,3 @@ this.right === right && | ||
* | ||
* @param {AbstractUpdateEncoder} encoder The encoder to write data to. | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to. | ||
* @param {number} offset | ||
@@ -645,12 +646,22 @@ */ | ||
const parent = /** @type {AbstractType<any>} */ (this.parent) | ||
const parentItem = parent._item | ||
if (parentItem === null) { | ||
// parent type on y._map | ||
// find the correct key | ||
const ykey = findRootTypeKey(parent) | ||
if (parent._item !== undefined) { | ||
const parentItem = parent._item | ||
if (parentItem === null) { | ||
// parent type on y._map | ||
// find the correct key | ||
const ykey = findRootTypeKey(parent) | ||
encoder.writeParentInfo(true) // write parentYKey | ||
encoder.writeString(ykey) | ||
} else { | ||
encoder.writeParentInfo(false) // write parent id | ||
encoder.writeLeftID(parentItem.id) | ||
} | ||
} else if (parent.constructor === String) { // this edge case was added by differential updates | ||
encoder.writeParentInfo(true) // write parentYKey | ||
encoder.writeString(ykey) | ||
encoder.writeString(parent) | ||
} else if (parent.constructor === ID) { | ||
encoder.writeParentInfo(false) // write parent id | ||
encoder.writeLeftID(parent) | ||
} else { | ||
encoder.writeParentInfo(false) // write parent id | ||
encoder.writeLeftID(parentItem.id) | ||
error.unexpectedCase() | ||
} | ||
@@ -666,3 +677,3 @@ if (parentSub !== null) { | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @param {number} info | ||
@@ -675,6 +686,6 @@ */ | ||
* | ||
* @type {Array<function(AbstractUpdateDecoder):AbstractContent>} | ||
* @type {Array<function(UpdateDecoderV1 | UpdateDecoderV2):AbstractContent>} | ||
*/ | ||
export const contentRefs = [ | ||
() => { throw error.unexpectedCase() }, // GC is not ItemContent | ||
() => { error.unexpectedCase() }, // GC is not ItemContent | ||
readContentDeleted, // 1 | ||
@@ -688,3 +699,4 @@ readContentJSON, // 2 | ||
readContentAny, // 8 | ||
readContentDoc // 9 | ||
readContentDoc, // 9 | ||
() => { error.unexpectedCase() } // 10 - Skip is not ItemContent | ||
] | ||
@@ -769,3 +781,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {number} offset | ||
@@ -772,0 +784,0 @@ */ |
@@ -14,3 +14,3 @@ | ||
getItemCleanStart, | ||
ContentDoc, YText, YArray, AbstractUpdateEncoder, Doc, Snapshot, Transaction, EventHandler, YEvent, Item, // eslint-disable-line | ||
ContentDoc, YText, YArray, UpdateEncoderV1, UpdateEncoderV2, Doc, Snapshot, Transaction, EventHandler, YEvent, Item, // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -328,3 +328,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
*/ | ||
@@ -331,0 +331,0 @@ _write (encoder) { } |
@@ -18,3 +18,3 @@ /** | ||
transact, | ||
ArraySearchMarker, AbstractUpdateDecoder, AbstractUpdateEncoder, Doc, Transaction, Item // eslint-disable-line | ||
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -245,3 +245,3 @@ import { typeListSlice } from './AbstractType.js' | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
*/ | ||
@@ -254,3 +254,3 @@ _write (encoder) { | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* | ||
@@ -257,0 +257,0 @@ * @private |
@@ -17,3 +17,3 @@ | ||
transact, | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, Doc, Transaction, Item // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -242,3 +242,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
*/ | ||
@@ -251,3 +251,3 @@ _write (encoder) { | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* | ||
@@ -254,0 +254,0 @@ * @private |
@@ -29,3 +29,3 @@ | ||
updateMarkerChanges, | ||
ArraySearchMarker, AbstractUpdateDecoder, AbstractUpdateEncoder, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line | ||
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -168,9 +168,8 @@ | ||
const ownClientId = doc.clientID | ||
let left = currPos.left | ||
let nextFormat = currPos.left | ||
const right = currPos.right | ||
negatedAttributes.forEach((val, key) => { | ||
left = new Item(createID(ownClientId, getState(doc.store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentFormat(key, val)) | ||
left.integrate(transaction, 0) | ||
currPos.currentAttributes.set(key, val) | ||
updateCurrentAttributes(currPos.currentAttributes, /** @type {ContentFormat} */ (left.content)) | ||
nextFormat = new Item(createID(ownClientId, getState(doc.store, ownClientId)), nextFormat, nextFormat && nextFormat.lastId, right, right && right.id, parent, null, new ContentFormat(key, val)) | ||
nextFormat.integrate(transaction, 0) | ||
currPos.right = nextFormat | ||
}) | ||
@@ -1210,3 +1209,3 @@ } | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
*/ | ||
@@ -1219,3 +1218,3 @@ _write (encoder) { | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {YText} | ||
@@ -1222,0 +1221,0 @@ * |
@@ -11,3 +11,3 @@ | ||
YXmlElementRefID, | ||
YXmlText, ContentType, AbstractType, AbstractUpdateDecoder, AbstractUpdateEncoder, Snapshot, Doc, Item // eslint-disable-line | ||
YXmlText, ContentType, AbstractType, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Snapshot, Doc, Item // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -212,3 +212,3 @@ | ||
* | ||
* @param {AbstractUpdateEncoder} encoder The encoder to write data to. | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to. | ||
*/ | ||
@@ -222,3 +222,3 @@ _write (encoder) { | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {YXmlElement} | ||
@@ -225,0 +225,0 @@ * |
@@ -20,3 +20,3 @@ /** | ||
typeListSlice, | ||
AbstractUpdateDecoder, AbstractUpdateEncoder, Doc, ContentType, Transaction, Item, YXmlText, YXmlHook, Snapshot // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, ContentType, Transaction, Item, YXmlText, YXmlHook, Snapshot // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -414,3 +414,3 @@ | ||
* | ||
* @param {AbstractUpdateEncoder} encoder The encoder to write data to. | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to. | ||
*/ | ||
@@ -423,3 +423,3 @@ _write (encoder) { | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {YXmlFragment} | ||
@@ -426,0 +426,0 @@ * |
@@ -5,3 +5,3 @@ | ||
YXmlHookRefID, | ||
AbstractUpdateDecoder, AbstractUpdateEncoder // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2 // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -80,3 +80,3 @@ | ||
* | ||
* @param {AbstractUpdateEncoder} encoder The encoder to write data to. | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to. | ||
*/ | ||
@@ -90,3 +90,3 @@ _write (encoder) { | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {YXmlHook} | ||
@@ -93,0 +93,0 @@ * |
@@ -5,3 +5,3 @@ | ||
YXmlTextRefID, | ||
ContentType, YXmlElement, AbstractUpdateDecoder, AbstractUpdateEncoder // eslint-disable-line | ||
ContentType, YXmlElement, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -108,3 +108,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
*/ | ||
@@ -117,3 +117,3 @@ _write (encoder) { | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder | ||
* @return {YXmlText} | ||
@@ -120,0 +120,0 @@ * |
@@ -7,3 +7,4 @@ | ||
iterateStructs, | ||
AbstractUpdateDecoder, AbstractDSDecoder, AbstractDSEncoder, DSDecoderV2, DSEncoderV2, Item, GC, StructStore, Transaction, ID // eslint-disable-line | ||
UpdateEncoderV2, | ||
DSDecoderV1, DSEncoderV1, DSDecoderV2, DSEncoderV2, Item, GC, StructStore, Transaction, ID // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -125,4 +126,4 @@ | ||
const right = dels[i] | ||
if (left.clock + left.len === right.clock) { | ||
left.len += right.len | ||
if (left.clock + left.len >= right.clock) { | ||
left.len = math.max(left.len, right.clock + right.len - left.clock) | ||
} else { | ||
@@ -215,3 +216,3 @@ if (j < i) { | ||
/** | ||
* @param {AbstractDSEncoder} encoder | ||
* @param {DSEncoderV1 | DSEncoderV2} encoder | ||
* @param {DeleteSet} ds | ||
@@ -238,3 +239,3 @@ * | ||
/** | ||
* @param {AbstractDSDecoder} decoder | ||
* @param {DSDecoderV1 | DSDecoderV2} decoder | ||
* @return {DeleteSet} | ||
@@ -267,5 +268,6 @@ * | ||
/** | ||
* @param {AbstractDSDecoder} decoder | ||
* @param {DSDecoderV1 | DSDecoderV2} decoder | ||
* @param {Transaction} transaction | ||
* @param {StructStore} store | ||
* @return {Uint8Array|null} Returns a v2 update containing all deletes that couldn't be applied yet; or null if all deletes were applied successfully. | ||
* | ||
@@ -323,7 +325,8 @@ * @private | ||
if (unappliedDS.clients.size > 0) { | ||
// TODO: no need for encoding+decoding ds anymore | ||
const unappliedDSEncoder = new DSEncoderV2() | ||
writeDeleteSet(unappliedDSEncoder, unappliedDS) | ||
store.pendingDeleteReaders.push(new DSDecoderV2(decoding.createDecoder((unappliedDSEncoder.toUint8Array())))) | ||
const ds = new UpdateEncoderV2() | ||
encoding.writeVarUint(ds.restEncoder, 0) // encode 0 structs | ||
writeDeleteSet(ds, unappliedDS) | ||
return ds.toUint8Array() | ||
} | ||
return null | ||
} |
@@ -32,7 +32,9 @@ | ||
UpdateEncoderV2, | ||
DSDecoderV2, | ||
DSEncoderV2, | ||
DSDecoderV1, | ||
DSEncoderV1, | ||
AbstractDSEncoder, AbstractDSDecoder, AbstractUpdateEncoder, AbstractUpdateDecoder, AbstractContent, Doc, Transaction, GC, Item, StructStore, ID // eslint-disable-line | ||
mergeUpdatesV2, | ||
Skip, | ||
diffUpdateV2, | ||
DSDecoderV2, Doc, Transaction, GC, Item, StructStore // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -44,24 +46,6 @@ | ||
import * as map from 'lib0/map.js' | ||
import * as math from 'lib0/math.js' | ||
export let DefaultDSEncoder = DSEncoderV1 | ||
export let DefaultDSDecoder = DSDecoderV1 | ||
export let DefaultUpdateEncoder = UpdateEncoderV1 | ||
export let DefaultUpdateDecoder = UpdateDecoderV1 | ||
export const useV1Encoding = () => { | ||
DefaultDSEncoder = DSEncoderV1 | ||
DefaultDSDecoder = DSDecoderV1 | ||
DefaultUpdateEncoder = UpdateEncoderV1 | ||
DefaultUpdateDecoder = UpdateDecoderV1 | ||
} | ||
export const useV2Encoding = () => { | ||
DefaultDSEncoder = DSEncoderV2 | ||
DefaultDSDecoder = DSDecoderV2 | ||
DefaultUpdateEncoder = UpdateEncoderV2 | ||
DefaultUpdateDecoder = UpdateDecoderV2 | ||
} | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {Array<GC|Item>} structs All structs by `client` | ||
@@ -75,2 +59,3 @@ * @param {number} client | ||
// write first id | ||
clock = math.max(clock, structs[0].id.clock) // make sure the first id exists | ||
const startNewStructs = findIndexSS(structs, clock) | ||
@@ -90,3 +75,3 @@ // write # encoded structs | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {StructStore} store | ||
@@ -123,6 +108,5 @@ * @param {Map<number,number>} _sm | ||
/** | ||
* @param {AbstractUpdateDecoder} decoder The decoder object to read data from. | ||
* @param {Map<number,Array<GC|Item>>} clientRefs | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder The decoder object to read data from. | ||
* @param {Doc} doc | ||
* @return {Map<number,Array<GC|Item>>} | ||
* @return {Map<number, { i: number, refs: Array<Item | GC> }>} | ||
* | ||
@@ -132,3 +116,7 @@ * @private | ||
*/ | ||
export const readClientsStructRefs = (decoder, clientRefs, doc) => { | ||
export const readClientsStructRefs = (decoder, doc) => { | ||
/** | ||
* @type {Map<number, { i: number, refs: Array<Item | GC> }>} | ||
*/ | ||
const clientRefs = map.create() | ||
const numOfStateUpdates = decoding.readVarUint(decoder.restDecoder) | ||
@@ -144,57 +132,68 @@ for (let i = 0; i < numOfStateUpdates; i++) { | ||
// const start = performance.now() | ||
clientRefs.set(client, refs) | ||
clientRefs.set(client, { i: 0, refs }) | ||
for (let i = 0; i < numberOfStructs; i++) { | ||
const info = decoder.readInfo() | ||
if ((binary.BITS5 & info) !== 0) { | ||
/** | ||
* The optimized implementation doesn't use any variables because inlining variables is faster. | ||
* Below a non-optimized version is shown that implements the basic algorithm with | ||
* a few comments | ||
*/ | ||
const cantCopyParentInfo = (info & (binary.BIT7 | binary.BIT8)) === 0 | ||
// If parent = null and neither left nor right are defined, then we know that `parent` is child of `y` | ||
// and we read the next string as parentYKey. | ||
// It indicates how we store/retrieve parent from `y.share` | ||
// @type {string|null} | ||
const struct = new Item( | ||
createID(client, clock), | ||
null, // leftd | ||
(info & binary.BIT8) === binary.BIT8 ? decoder.readLeftID() : null, // origin | ||
null, // right | ||
(info & binary.BIT7) === binary.BIT7 ? decoder.readRightID() : null, // right origin | ||
cantCopyParentInfo ? (decoder.readParentInfo() ? doc.get(decoder.readString()) : decoder.readLeftID()) : null, // parent | ||
cantCopyParentInfo && (info & binary.BIT6) === binary.BIT6 ? decoder.readString() : null, // parentSub | ||
readItemContent(decoder, info) // item content | ||
) | ||
/* A non-optimized implementation of the above algorithm: | ||
switch (binary.BITS5 & info) { | ||
case 0: { // GC | ||
const len = decoder.readLen() | ||
refs[i] = new GC(createID(client, clock), len) | ||
clock += len | ||
break | ||
} | ||
case 10: { // Skip Struct (nothing to apply) | ||
// @todo we could reduce the amount of checks by adding Skip struct to clientRefs so we know that something is missing. | ||
const len = decoding.readVarUint(decoder.restDecoder) | ||
refs[i] = new Skip(createID(client, clock), len) | ||
clock += len | ||
break | ||
} | ||
default: { // Item with content | ||
/** | ||
* The optimized implementation doesn't use any variables because inlining variables is faster. | ||
* Below a non-optimized version is shown that implements the basic algorithm with | ||
* a few comments | ||
*/ | ||
const cantCopyParentInfo = (info & (binary.BIT7 | binary.BIT8)) === 0 | ||
// If parent = null and neither left nor right are defined, then we know that `parent` is child of `y` | ||
// and we read the next string as parentYKey. | ||
// It indicates how we store/retrieve parent from `y.share` | ||
// @type {string|null} | ||
const struct = new Item( | ||
createID(client, clock), | ||
null, // leftd | ||
(info & binary.BIT8) === binary.BIT8 ? decoder.readLeftID() : null, // origin | ||
null, // right | ||
(info & binary.BIT7) === binary.BIT7 ? decoder.readRightID() : null, // right origin | ||
cantCopyParentInfo ? (decoder.readParentInfo() ? doc.get(decoder.readString()) : decoder.readLeftID()) : null, // parent | ||
cantCopyParentInfo && (info & binary.BIT6) === binary.BIT6 ? decoder.readString() : null, // parentSub | ||
readItemContent(decoder, info) // item content | ||
) | ||
/* A non-optimized implementation of the above algorithm: | ||
// The item that was originally to the left of this item. | ||
const origin = (info & binary.BIT8) === binary.BIT8 ? decoder.readLeftID() : null | ||
// The item that was originally to the right of this item. | ||
const rightOrigin = (info & binary.BIT7) === binary.BIT7 ? decoder.readRightID() : null | ||
const cantCopyParentInfo = (info & (binary.BIT7 | binary.BIT8)) === 0 | ||
const hasParentYKey = cantCopyParentInfo ? decoder.readParentInfo() : false | ||
// If parent = null and neither left nor right are defined, then we know that `parent` is child of `y` | ||
// and we read the next string as parentYKey. | ||
// It indicates how we store/retrieve parent from `y.share` | ||
// @type {string|null} | ||
const parentYKey = cantCopyParentInfo && hasParentYKey ? decoder.readString() : null | ||
// The item that was originally to the left of this item. | ||
const origin = (info & binary.BIT8) === binary.BIT8 ? decoder.readLeftID() : null | ||
// The item that was originally to the right of this item. | ||
const rightOrigin = (info & binary.BIT7) === binary.BIT7 ? decoder.readRightID() : null | ||
const cantCopyParentInfo = (info & (binary.BIT7 | binary.BIT8)) === 0 | ||
const hasParentYKey = cantCopyParentInfo ? decoder.readParentInfo() : false | ||
// If parent = null and neither left nor right are defined, then we know that `parent` is child of `y` | ||
// and we read the next string as parentYKey. | ||
// It indicates how we store/retrieve parent from `y.share` | ||
// @type {string|null} | ||
const parentYKey = cantCopyParentInfo && hasParentYKey ? decoder.readString() : null | ||
const struct = new Item( | ||
createID(client, clock), | ||
null, // leftd | ||
origin, // origin | ||
null, // right | ||
rightOrigin, // right origin | ||
cantCopyParentInfo && !hasParentYKey ? decoder.readLeftID() : (parentYKey !== null ? doc.get(parentYKey) : null), // parent | ||
cantCopyParentInfo && (info & binary.BIT6) === binary.BIT6 ? decoder.readString() : null, // parentSub | ||
readItemContent(decoder, info) // item content | ||
) | ||
*/ | ||
refs[i] = struct | ||
clock += struct.length | ||
} else { | ||
const len = decoder.readLen() | ||
refs[i] = new GC(createID(client, clock), len) | ||
clock += len | ||
const struct = new Item( | ||
createID(client, clock), | ||
null, // leftd | ||
origin, // origin | ||
null, // right | ||
rightOrigin, // right origin | ||
cantCopyParentInfo && !hasParentYKey ? decoder.readLeftID() : (parentYKey !== null ? doc.get(parentYKey) : null), // parent | ||
cantCopyParentInfo && (info & binary.BIT6) === binary.BIT6 ? decoder.readString() : null, // parentSub | ||
readItemContent(decoder, info) // item content | ||
) | ||
*/ | ||
refs[i] = struct | ||
clock += struct.length | ||
} | ||
} | ||
@@ -228,2 +227,4 @@ } | ||
* @param {StructStore} store | ||
* @param {Map<number, { i: number, refs: (GC | Item)[] }>} clientsStructRefs | ||
* @return { null | { update: Uint8Array, missing: Map<number,number> } } | ||
* | ||
@@ -233,11 +234,16 @@ * @private | ||
*/ | ||
const resumeStructIntegration = (transaction, store) => { | ||
const stack = store.pendingStack // @todo don't forget to append stackhead at the end | ||
const clientsStructRefs = store.pendingClientsStructRefs | ||
const integrateStructs = (transaction, store, clientsStructRefs) => { | ||
/** | ||
* @type {Array<Item | GC>} | ||
*/ | ||
const stack = [] | ||
// sort them so that we take the higher id first, in case of conflicts the lower id will probably not conflict with the id from the higher user. | ||
const clientsStructRefsIds = Array.from(clientsStructRefs.keys()).sort((a, b) => a - b) | ||
let clientsStructRefsIds = Array.from(clientsStructRefs.keys()).sort((a, b) => a - b) | ||
if (clientsStructRefsIds.length === 0) { | ||
return | ||
return null | ||
} | ||
const getNextStructTarget = () => { | ||
if (clientsStructRefsIds.length === 0) { | ||
return null | ||
} | ||
let nextStructsTarget = /** @type {{i:number,refs:Array<GC|Item>}} */ (clientsStructRefs.get(clientsStructRefsIds[clientsStructRefsIds.length - 1])) | ||
@@ -249,3 +255,2 @@ while (nextStructsTarget.refs.length === nextStructsTarget.i) { | ||
} else { | ||
store.pendingClientsStructRefs.clear() | ||
return null | ||
@@ -258,94 +263,111 @@ } | ||
if (curStructsTarget === null && stack.length === 0) { | ||
return | ||
return null | ||
} | ||
/** | ||
* @type {StructStore} | ||
*/ | ||
const restStructs = new StructStore() | ||
const missingSV = new Map() | ||
/** | ||
* @param {number} client | ||
* @param {number} clock | ||
*/ | ||
const updateMissingSv = (client, clock) => { | ||
const mclock = missingSV.get(client) | ||
if (mclock == null || mclock > clock) { | ||
missingSV.set(client, clock) | ||
} | ||
} | ||
/** | ||
* @type {GC|Item} | ||
*/ | ||
let stackHead = stack.length > 0 | ||
? /** @type {GC|Item} */ (stack.pop()) | ||
: /** @type {any} */ (curStructsTarget).refs[/** @type {any} */ (curStructsTarget).i++] | ||
let stackHead = /** @type {any} */ (curStructsTarget).refs[/** @type {any} */ (curStructsTarget).i++] | ||
// caching the state because it is used very often | ||
const state = new Map() | ||
const addStackToRestSS = () => { | ||
for (const item of stack) { | ||
const client = item.id.client | ||
const unapplicableItems = clientsStructRefs.get(client) | ||
if (unapplicableItems) { | ||
// decrement because we weren't able to apply previous operation | ||
unapplicableItems.i-- | ||
restStructs.clients.set(client, unapplicableItems.refs.slice(unapplicableItems.i)) | ||
clientsStructRefs.delete(client) | ||
unapplicableItems.i = 0 | ||
unapplicableItems.refs = [] | ||
} else { | ||
// item was the last item on clientsStructRefs and the field was already cleared. Add item to restStructs and continue | ||
restStructs.clients.set(client, [item]) | ||
} | ||
// remove client from clientsStructRefsIds to prevent users from applying the same update again | ||
clientsStructRefsIds = clientsStructRefsIds.filter(c => c !== client) | ||
} | ||
stack.length = 0 | ||
} | ||
// iterate over all struct readers until we are done | ||
while (true) { | ||
const localClock = map.setIfUndefined(state, stackHead.id.client, () => getState(store, stackHead.id.client)) | ||
const offset = stackHead.id.clock < localClock ? localClock - stackHead.id.clock : 0 | ||
if (stackHead.id.clock + offset !== localClock) { | ||
// A previous message from this client is missing | ||
// check if there is a pending structRef with a smaller clock and switch them | ||
/** | ||
* @type {{ refs: Array<GC|Item>, i: number }} | ||
*/ | ||
const structRefs = clientsStructRefs.get(stackHead.id.client) || { refs: [], i: 0 } | ||
if (structRefs.refs.length !== structRefs.i) { | ||
const r = structRefs.refs[structRefs.i] | ||
if (r.id.clock < stackHead.id.clock) { | ||
// put ref with smaller clock on stack instead and continue | ||
structRefs.refs[structRefs.i] = stackHead | ||
stackHead = r | ||
// sort the set because this approach might bring the list out of order | ||
structRefs.refs = structRefs.refs.slice(structRefs.i).sort((r1, r2) => r1.id.clock - r2.id.clock) | ||
structRefs.i = 0 | ||
continue | ||
if (stackHead.constructor !== Skip) { | ||
const localClock = map.setIfUndefined(state, stackHead.id.client, () => getState(store, stackHead.id.client)) | ||
const offset = localClock - stackHead.id.clock | ||
if (offset < 0) { | ||
// update from the same client is missing | ||
stack.push(stackHead) | ||
updateMissingSv(stackHead.id.client, stackHead.id.clock - 1) | ||
// hid a dead wall, add all items from stack to restSS | ||
addStackToRestSS() | ||
} else { | ||
const missing = stackHead.getMissing(transaction, store) | ||
if (missing !== null) { | ||
stack.push(stackHead) | ||
// get the struct reader that has the missing struct | ||
/** | ||
* @type {{ refs: Array<GC|Item>, i: number }} | ||
*/ | ||
const structRefs = clientsStructRefs.get(/** @type {number} */ (missing)) || { refs: [], i: 0 } | ||
if (structRefs.refs.length === structRefs.i) { | ||
// This update message causally depends on another update message that doesn't exist yet | ||
updateMissingSv(/** @type {number} */ (missing), getState(store, missing)) | ||
addStackToRestSS() | ||
} else { | ||
stackHead = structRefs.refs[structRefs.i++] | ||
continue | ||
} | ||
} else if (offset === 0 || offset < stackHead.length) { | ||
// all fine, apply the stackhead | ||
stackHead.integrate(transaction, offset) | ||
state.set(stackHead.id.client, stackHead.id.clock + stackHead.length) | ||
} | ||
} | ||
// wait until missing struct is available | ||
stack.push(stackHead) | ||
return | ||
} | ||
const missing = stackHead.getMissing(transaction, store) | ||
if (missing === null) { | ||
if (offset === 0 || offset < stackHead.length) { | ||
stackHead.integrate(transaction, offset) | ||
state.set(stackHead.id.client, stackHead.id.clock + stackHead.length) | ||
} | ||
// iterate to next stackHead | ||
if (stack.length > 0) { | ||
stackHead = /** @type {GC|Item} */ (stack.pop()) | ||
} else if (curStructsTarget !== null && curStructsTarget.i < curStructsTarget.refs.length) { | ||
// iterate to next stackHead | ||
if (stack.length > 0) { | ||
stackHead = /** @type {GC|Item} */ (stack.pop()) | ||
} else if (curStructsTarget !== null && curStructsTarget.i < curStructsTarget.refs.length) { | ||
stackHead = /** @type {GC|Item} */ (curStructsTarget.refs[curStructsTarget.i++]) | ||
} else { | ||
curStructsTarget = getNextStructTarget() | ||
if (curStructsTarget === null) { | ||
// we are done! | ||
break | ||
} else { | ||
stackHead = /** @type {GC|Item} */ (curStructsTarget.refs[curStructsTarget.i++]) | ||
} else { | ||
curStructsTarget = getNextStructTarget() | ||
if (curStructsTarget === null) { | ||
// we are done! | ||
break | ||
} else { | ||
stackHead = /** @type {GC|Item} */ (curStructsTarget.refs[curStructsTarget.i++]) | ||
} | ||
} | ||
} else { | ||
// get the struct reader that has the missing struct | ||
/** | ||
* @type {{ refs: Array<GC|Item>, i: number }} | ||
*/ | ||
const structRefs = clientsStructRefs.get(missing) || { refs: [], i: 0 } | ||
if (structRefs.refs.length === structRefs.i) { | ||
// This update message causally depends on another update message. | ||
stack.push(stackHead) | ||
return | ||
} | ||
stack.push(stackHead) | ||
stackHead = structRefs.refs[structRefs.i++] | ||
} | ||
} | ||
store.pendingClientsStructRefs.clear() | ||
} | ||
/** | ||
* @param {Transaction} transaction | ||
* @param {StructStore} store | ||
* | ||
* @private | ||
* @function | ||
*/ | ||
export const tryResumePendingDeleteReaders = (transaction, store) => { | ||
const pendingReaders = store.pendingDeleteReaders | ||
store.pendingDeleteReaders = [] | ||
for (let i = 0; i < pendingReaders.length; i++) { | ||
readAndApplyDeleteSet(pendingReaders[i], transaction, store) | ||
if (restStructs.clients.size > 0) { | ||
const encoder = new UpdateEncoderV2() | ||
writeClientsStructs(encoder, restStructs, new Map()) | ||
// write empty deleteset | ||
// writeDeleteSet(encoder, new DeleteSet()) | ||
encoding.writeVarUint(encoder.restEncoder, 0) // => no need for an extra function call, just write 0 deletes | ||
return { missing: missingSV, update: encoder.toUint8Array() } | ||
} | ||
return null | ||
} | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {Transaction} transaction | ||
@@ -359,74 +381,2 @@ * | ||
/** | ||
* @param {StructStore} store | ||
* @param {Map<number, Array<GC|Item>>} clientsStructsRefs | ||
* | ||
* @private | ||
* @function | ||
*/ | ||
const mergeReadStructsIntoPendingReads = (store, clientsStructsRefs) => { | ||
const pendingClientsStructRefs = store.pendingClientsStructRefs | ||
clientsStructsRefs.forEach((structRefs, client) => { | ||
const pendingStructRefs = pendingClientsStructRefs.get(client) | ||
if (pendingStructRefs === undefined) { | ||
pendingClientsStructRefs.set(client, { refs: structRefs, i: 0 }) | ||
} else { | ||
// merge into existing structRefs | ||
const merged = pendingStructRefs.i > 0 ? pendingStructRefs.refs.slice(pendingStructRefs.i) : pendingStructRefs.refs | ||
for (let i = 0; i < structRefs.length; i++) { | ||
merged.push(structRefs[i]) | ||
} | ||
pendingStructRefs.i = 0 | ||
pendingStructRefs.refs = merged.sort((r1, r2) => r1.id.clock - r2.id.clock) | ||
} | ||
}) | ||
} | ||
/** | ||
* @param {Map<number,{refs:Array<GC|Item>,i:number}>} pendingClientsStructRefs | ||
*/ | ||
const cleanupPendingStructs = pendingClientsStructRefs => { | ||
// cleanup pendingClientsStructs if not fully finished | ||
pendingClientsStructRefs.forEach((refs, client) => { | ||
if (refs.i === refs.refs.length) { | ||
pendingClientsStructRefs.delete(client) | ||
} else { | ||
refs.refs.splice(0, refs.i) | ||
refs.i = 0 | ||
} | ||
}) | ||
} | ||
/** | ||
* Read the next Item in a Decoder and fill this Item with the read data. | ||
* | ||
* This is called when data is received from a remote peer. | ||
* | ||
* @param {AbstractUpdateDecoder} decoder The decoder object to read data from. | ||
* @param {Transaction} transaction | ||
* @param {StructStore} store | ||
* | ||
* @private | ||
* @function | ||
*/ | ||
export const readStructs = (decoder, transaction, store) => { | ||
const clientsStructRefs = new Map() | ||
// let start = performance.now() | ||
readClientsStructRefs(decoder, clientsStructRefs, transaction.doc) | ||
// console.log('time to read structs: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
mergeReadStructsIntoPendingReads(store, clientsStructRefs) | ||
// console.log('time to merge: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
resumeStructIntegration(transaction, store) | ||
// console.log('time to integrate: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
cleanupPendingStructs(store.pendingClientsStructRefs) | ||
// console.log('time to cleanup: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
tryResumePendingDeleteReaders(transaction, store) | ||
// console.log('time to resume delete readers: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
} | ||
/** | ||
* Read and apply a document update. | ||
@@ -439,3 +389,3 @@ * | ||
* @param {any} [transactionOrigin] This will be stored on `transaction.origin` and `.on('update', (update, origin))` | ||
* @param {AbstractUpdateDecoder} [structDecoder] | ||
* @param {UpdateDecoderV1 | UpdateDecoderV2} [structDecoder] | ||
* | ||
@@ -446,4 +396,65 @@ * @function | ||
transact(ydoc, transaction => { | ||
readStructs(structDecoder, transaction, ydoc.store) | ||
readAndApplyDeleteSet(structDecoder, transaction, ydoc.store) | ||
let retry = false | ||
const doc = transaction.doc | ||
const store = doc.store | ||
// let start = performance.now() | ||
const ss = readClientsStructRefs(structDecoder, doc) | ||
// console.log('time to read structs: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
// console.log('time to merge: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
const restStructs = integrateStructs(transaction, store, ss) | ||
const pending = store.pendingStructs | ||
if (pending) { | ||
// check if we can apply something | ||
for (const [client, clock] of pending.missing) { | ||
if (clock < getState(store, client)) { | ||
retry = true | ||
break | ||
} | ||
} | ||
if (restStructs) { | ||
// merge restStructs into store.pending | ||
for (const [client, clock] of restStructs.missing) { | ||
const mclock = pending.missing.get(client) | ||
if (mclock == null || mclock > clock) { | ||
pending.missing.set(client, clock) | ||
} | ||
} | ||
pending.update = mergeUpdatesV2([pending.update, restStructs.update]) | ||
} | ||
} else { | ||
store.pendingStructs = restStructs | ||
} | ||
// console.log('time to integrate: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
const dsRest = readAndApplyDeleteSet(structDecoder, transaction, store) | ||
if (store.pendingDs) { | ||
// @todo we could make a lower-bound state-vector check as we do above | ||
const pendingDSUpdate = new UpdateDecoderV2(decoding.createDecoder(store.pendingDs)) | ||
decoding.readVarUint(pendingDSUpdate.restDecoder) // read 0 structs, because we only encode deletes in pendingdsupdate | ||
const dsRest2 = readAndApplyDeleteSet(pendingDSUpdate, transaction, store) | ||
if (dsRest && dsRest2) { | ||
// case 1: ds1 != null && ds2 != null | ||
store.pendingDs = mergeUpdatesV2([dsRest, dsRest2]) | ||
} else { | ||
// case 2: ds1 != null | ||
// case 3: ds2 != null | ||
// case 4: ds1 == null && ds2 == null | ||
store.pendingDs = dsRest || dsRest2 | ||
} | ||
} else { | ||
// Either dsRest == null && pendingDs == null OR dsRest != null | ||
store.pendingDs = dsRest | ||
} | ||
// console.log('time to cleanup: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
// console.log('time to resume delete readers: ', performance.now() - start) // @todo remove | ||
// start = performance.now() | ||
if (retry) { | ||
const update = /** @type {{update: Uint8Array}} */ (store.pendingStructs).update | ||
store.pendingStructs = null | ||
applyUpdateV2(transaction.doc, update) | ||
} | ||
}, transactionOrigin, false) | ||
@@ -462,3 +473,3 @@ | ||
*/ | ||
export const readUpdate = (decoder, ydoc, transactionOrigin) => readUpdateV2(decoder, ydoc, transactionOrigin, new DefaultUpdateDecoder(decoder)) | ||
export const readUpdate = (decoder, ydoc, transactionOrigin) => readUpdateV2(decoder, ydoc, transactionOrigin, new UpdateDecoderV1(decoder)) | ||
@@ -493,3 +504,3 @@ /** | ||
*/ | ||
export const applyUpdate = (ydoc, update, transactionOrigin) => applyUpdateV2(ydoc, update, transactionOrigin, DefaultUpdateDecoder) | ||
export const applyUpdate = (ydoc, update, transactionOrigin) => applyUpdateV2(ydoc, update, transactionOrigin, UpdateDecoderV1) | ||
@@ -500,3 +511,3 @@ /** | ||
* | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {Doc} doc | ||
@@ -520,3 +531,3 @@ * @param {Map<number,number>} [targetStateVector] The state of the target that receives the update. Leave empty to write all known structs | ||
* @param {Uint8Array} [encodedTargetStateVector] The state of the target that receives the update. Leave empty to write all known structs | ||
* @param {AbstractUpdateEncoder} [encoder] | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} [encoder] | ||
* @return {Uint8Array} | ||
@@ -526,6 +537,20 @@ * | ||
*/ | ||
export const encodeStateAsUpdateV2 = (doc, encodedTargetStateVector, encoder = new UpdateEncoderV2()) => { | ||
const targetStateVector = encodedTargetStateVector == null ? new Map() : decodeStateVector(encodedTargetStateVector) | ||
export const encodeStateAsUpdateV2 = (doc, encodedTargetStateVector = new Uint8Array([0]), encoder = new UpdateEncoderV2()) => { | ||
const targetStateVector = decodeStateVector(encodedTargetStateVector) | ||
writeStateAsUpdate(encoder, doc, targetStateVector) | ||
return encoder.toUint8Array() | ||
const updates = [encoder.toUint8Array()] | ||
// also add the pending updates (if there are any) | ||
// @todo support diffirent encoders | ||
if (encoder.constructor === UpdateEncoderV2) { | ||
if (doc.store.pendingDs) { | ||
updates.push(doc.store.pendingDs) | ||
} | ||
if (doc.store.pendingStructs) { | ||
updates.push(diffUpdateV2(doc.store.pendingStructs.update, encodedTargetStateVector)) | ||
} | ||
if (updates.length > 1) { | ||
return mergeUpdatesV2(updates) | ||
} | ||
} | ||
return updates[0] | ||
} | ||
@@ -545,3 +570,3 @@ | ||
*/ | ||
export const encodeStateAsUpdate = (doc, encodedTargetStateVector) => encodeStateAsUpdateV2(doc, encodedTargetStateVector, new DefaultUpdateEncoder()) | ||
export const encodeStateAsUpdate = (doc, encodedTargetStateVector) => encodeStateAsUpdateV2(doc, encodedTargetStateVector, new UpdateEncoderV1()) | ||
@@ -551,3 +576,3 @@ /** | ||
* | ||
* @param {AbstractDSDecoder} decoder | ||
* @param {DSDecoderV1 | DSDecoderV2} decoder | ||
* @return {Map<number,number>} Maps `client` to the number next expected `clock` from that client. | ||
@@ -576,3 +601,3 @@ * | ||
*/ | ||
export const decodeStateVectorV2 = decodedState => readStateVector(new DSDecoderV2(decoding.createDecoder(decodedState))) | ||
// export const decodeStateVectorV2 = decodedState => readStateVector(new DSDecoderV2(decoding.createDecoder(decodedState))) | ||
@@ -587,6 +612,6 @@ /** | ||
*/ | ||
export const decodeStateVector = decodedState => readStateVector(new DefaultDSDecoder(decoding.createDecoder(decodedState))) | ||
export const decodeStateVector = decodedState => readStateVector(new DSDecoderV1(decoding.createDecoder(decodedState))) | ||
/** | ||
* @param {AbstractDSEncoder} encoder | ||
* @param {DSEncoderV1 | DSEncoderV2} encoder | ||
* @param {Map<number,number>} sv | ||
@@ -605,3 +630,3 @@ * @function | ||
/** | ||
* @param {AbstractDSEncoder} encoder | ||
* @param {DSEncoderV1 | DSEncoderV2} encoder | ||
* @param {Doc} doc | ||
@@ -616,4 +641,4 @@ * | ||
* | ||
* @param {Doc} doc | ||
* @param {AbstractDSEncoder} [encoder] | ||
* @param {Doc|Map<number,number>} doc | ||
* @param {DSEncoderV1 | DSEncoderV2} [encoder] | ||
* @return {Uint8Array} | ||
@@ -624,3 +649,7 @@ * | ||
export const encodeStateVectorV2 = (doc, encoder = new DSEncoderV2()) => { | ||
writeDocumentStateVector(encoder, doc) | ||
if (doc instanceof Map) { | ||
writeStateVector(encoder, doc) | ||
} else { | ||
writeDocumentStateVector(encoder, doc) | ||
} | ||
return encoder.toUint8Array() | ||
@@ -632,3 +661,3 @@ } | ||
* | ||
* @param {Doc} doc | ||
* @param {Doc|Map<number,number>} doc | ||
* @return {Uint8Array} | ||
@@ -638,2 +667,2 @@ * | ||
*/ | ||
export const encodeStateVector = doc => encodeStateVectorV2(doc, new DefaultDSEncoder()) | ||
export const encodeStateVector = doc => encodeStateVectorV2(doc, new DSEncoderV1()) |
@@ -17,5 +17,4 @@ | ||
UpdateEncoderV2, | ||
DefaultDSEncoder, | ||
applyUpdateV2, | ||
AbstractDSDecoder, AbstractDSEncoder, DSEncoderV2, DSDecoderV1, DSDecoderV2, Transaction, Doc, DeleteSet, Item // eslint-disable-line | ||
DSEncoderV1, DSEncoderV2, DSDecoderV1, DSDecoderV2, Transaction, Doc, DeleteSet, Item // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -82,3 +81,3 @@ | ||
* @param {Snapshot} snapshot | ||
* @param {AbstractDSEncoder} [encoder] | ||
* @param {DSEncoderV1 | DSEncoderV2} [encoder] | ||
* @return {Uint8Array} | ||
@@ -96,7 +95,7 @@ */ | ||
*/ | ||
export const encodeSnapshot = snapshot => encodeSnapshotV2(snapshot, new DefaultDSEncoder()) | ||
export const encodeSnapshot = snapshot => encodeSnapshotV2(snapshot, new DSEncoderV1()) | ||
/** | ||
* @param {Uint8Array} buf | ||
* @param {AbstractDSDecoder} [decoder] | ||
* @param {DSDecoderV1 | DSDecoderV2} [decoder] | ||
* @return {Snapshot} | ||
@@ -103,0 +102,0 @@ */ |
@@ -18,20 +18,9 @@ | ||
/** | ||
* Store incompleted struct reads here | ||
* `i` denotes to the next read operation | ||
* We could shift the array of refs instead, but shift is incredible | ||
* slow in Chrome for arrays with more than 100k elements | ||
* @see tryResumePendingStructRefs | ||
* @type {Map<number,{i:number,refs:Array<GC|Item>}>} | ||
* @type {null | { missing: Map<number, number>, update: Uint8Array }} | ||
*/ | ||
this.pendingClientsStructRefs = new Map() | ||
this.pendingStructs = null | ||
/** | ||
* Stack of pending structs waiting for struct dependencies | ||
* Maximum length of stack is structReaders.size | ||
* @type {Array<GC|Item>} | ||
* @type {null | Uint8Array} | ||
*/ | ||
this.pendingStack = [] | ||
/** | ||
* @type {Array<DSDecoderV2>} | ||
*/ | ||
this.pendingDeleteReaders = [] | ||
this.pendingDs = null | ||
} | ||
@@ -38,0 +27,0 @@ } |
@@ -14,3 +14,3 @@ | ||
createID, | ||
AbstractUpdateEncoder, GC, StructStore, UpdateEncoderV2, DefaultUpdateEncoder, AbstractType, AbstractStruct, YEvent, Doc // eslint-disable-line | ||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, GC, StructStore, AbstractType, AbstractStruct, YEvent, Doc // eslint-disable-line | ||
} from '../internals.js' | ||
@@ -122,3 +122,3 @@ | ||
/** | ||
* @param {AbstractUpdateEncoder} encoder | ||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder | ||
* @param {Transaction} transaction | ||
@@ -342,3 +342,3 @@ * @return {boolean} Whether data was written. | ||
if (doc._observers.has('update')) { | ||
const encoder = new DefaultUpdateEncoder() | ||
const encoder = new UpdateEncoderV1() | ||
const hasContent = writeUpdateMessageFromTransaction(encoder, transaction) | ||
@@ -345,0 +345,0 @@ if (hasContent) { |
import * as buffer from 'lib0/buffer.js' | ||
import * as error from 'lib0/error.js' | ||
import * as decoding from 'lib0/decoding.js' | ||
@@ -8,121 +7,2 @@ import { | ||
export class AbstractDSDecoder { | ||
/** | ||
* @param {decoding.Decoder} decoder | ||
*/ | ||
constructor (decoder) { | ||
this.restDecoder = decoder | ||
error.methodUnimplemented() | ||
} | ||
resetDsCurVal () { } | ||
/** | ||
* @return {number} | ||
*/ | ||
readDsClock () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {number} | ||
*/ | ||
readDsLen () { | ||
error.methodUnimplemented() | ||
} | ||
} | ||
export class AbstractUpdateDecoder extends AbstractDSDecoder { | ||
/** | ||
* @return {ID} | ||
*/ | ||
readLeftID () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {ID} | ||
*/ | ||
readRightID () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* Read the next client id. | ||
* Use this in favor of readID whenever possible to reduce the number of objects created. | ||
* | ||
* @return {number} | ||
*/ | ||
readClient () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {number} info An unsigned 8-bit integer | ||
*/ | ||
readInfo () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {string} | ||
*/ | ||
readString () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {boolean} isKey | ||
*/ | ||
readParentInfo () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {number} info An unsigned 8-bit integer | ||
*/ | ||
readTypeRef () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* Write len of a struct - well suited for Opt RLE encoder. | ||
* | ||
* @return {number} len | ||
*/ | ||
readLen () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {any} | ||
*/ | ||
readAny () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {Uint8Array} | ||
*/ | ||
readBuf () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* Legacy implementation uses JSON parse. We use any-decoding in v2. | ||
* | ||
* @return {any} | ||
*/ | ||
readJSON () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @return {string} | ||
*/ | ||
readKey () { | ||
error.methodUnimplemented() | ||
} | ||
} | ||
export class DSDecoderV1 { | ||
@@ -251,2 +131,5 @@ /** | ||
constructor (decoder) { | ||
/** | ||
* @private | ||
*/ | ||
this.dsCurrVal = 0 | ||
@@ -260,2 +143,5 @@ this.restDecoder = decoder | ||
/** | ||
* @return {number} | ||
*/ | ||
readDsClock () { | ||
@@ -266,2 +152,5 @@ this.dsCurrVal += decoding.readVarUint(this.restDecoder) | ||
/** | ||
* @return {number} | ||
*/ | ||
readDsLen () { | ||
@@ -287,3 +176,3 @@ const diff = decoding.readVarUint(this.restDecoder) + 1 | ||
this.keys = [] | ||
decoding.readUint8(decoder) // read feature flag - currently unused | ||
decoding.readVarUint(decoder) // read feature flag - currently unused | ||
this.keyClockDecoder = new decoding.IntDiffOptRleDecoder(decoding.readVarUint8Array(decoder)) | ||
@@ -290,0 +179,0 @@ this.clientDecoder = new decoding.UintOptRleDecoder(decoding.readVarUint8Array(decoder)) |
@@ -9,3 +9,3 @@ | ||
export class AbstractDSEncoder { | ||
export class DSEncoderV1 { | ||
constructor () { | ||
@@ -15,104 +15,3 @@ this.restEncoder = encoding.createEncoder() | ||
/** | ||
* @return {Uint8Array} | ||
*/ | ||
toUint8Array () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* Resets the ds value to 0. | ||
* The v2 encoder uses this information to reset the initial diff value. | ||
*/ | ||
resetDsCurVal () { } | ||
/** | ||
* @param {number} clock | ||
*/ | ||
writeDsClock (clock) { } | ||
/** | ||
* @param {number} len | ||
*/ | ||
writeDsLen (len) { } | ||
} | ||
export class AbstractUpdateEncoder extends AbstractDSEncoder { | ||
/** | ||
* @return {Uint8Array} | ||
*/ | ||
toUint8Array () { | ||
error.methodUnimplemented() | ||
} | ||
/** | ||
* @param {ID} id | ||
*/ | ||
writeLeftID (id) { } | ||
/** | ||
* @param {ID} id | ||
*/ | ||
writeRightID (id) { } | ||
/** | ||
* Use writeClient and writeClock instead of writeID if possible. | ||
* @param {number} client | ||
*/ | ||
writeClient (client) { } | ||
/** | ||
* @param {number} info An unsigned 8-bit integer | ||
*/ | ||
writeInfo (info) { } | ||
/** | ||
* @param {string} s | ||
*/ | ||
writeString (s) { } | ||
/** | ||
* @param {boolean} isYKey | ||
*/ | ||
writeParentInfo (isYKey) { } | ||
/** | ||
* @param {number} info An unsigned 8-bit integer | ||
*/ | ||
writeTypeRef (info) { } | ||
/** | ||
* Write len of a struct - well suited for Opt RLE encoder. | ||
* | ||
* @param {number} len | ||
*/ | ||
writeLen (len) { } | ||
/** | ||
* @param {any} any | ||
*/ | ||
writeAny (any) { } | ||
/** | ||
* @param {Uint8Array} buf | ||
*/ | ||
writeBuf (buf) { } | ||
/** | ||
* @param {any} embed | ||
*/ | ||
writeJSON (embed) { } | ||
/** | ||
* @param {string} key | ||
*/ | ||
writeKey (key) { } | ||
} | ||
export class DSEncoderV1 { | ||
constructor () { | ||
this.restEncoder = new encoding.Encoder() | ||
} | ||
toUint8Array () { | ||
return encoding.toUint8Array(this.restEncoder) | ||
@@ -233,3 +132,3 @@ } | ||
constructor () { | ||
this.restEncoder = new encoding.Encoder() // encodes all the rest / non-optimized | ||
this.restEncoder = encoding.createEncoder() // encodes all the rest / non-optimized | ||
this.dsCurrVal = 0 | ||
@@ -294,3 +193,3 @@ } | ||
const encoder = encoding.createEncoder() | ||
encoding.writeUint8(encoder, 0) // this is a feature flag that we might use in the future | ||
encoding.writeVarUint(encoder, 0) // this is a feature flag that we might use in the future | ||
encoding.writeVarUint8Array(encoder, this.keyClockEncoder.toUint8Array()) | ||
@@ -297,0 +196,0 @@ encoding.writeVarUint8Array(encoder, this.clientEncoder.toUint8Array()) |
@@ -30,2 +30,35 @@ | ||
export let useV2 = false | ||
export const encV1 = { | ||
encodeStateAsUpdate: Y.encodeStateAsUpdate, | ||
mergeUpdates: Y.mergeUpdates, | ||
applyUpdate: Y.applyUpdate, | ||
logUpdate: Y.logUpdate, | ||
updateEventName: 'update', | ||
diffUpdate: Y.diffUpdate | ||
} | ||
export const encV2 = { | ||
encodeStateAsUpdate: Y.encodeStateAsUpdateV2, | ||
mergeUpdates: Y.mergeUpdatesV2, | ||
applyUpdate: Y.applyUpdateV2, | ||
logUpdate: Y.logUpdateV2, | ||
updateEventName: 'updateV2', | ||
diffUpdate: Y.diffUpdateV2 | ||
} | ||
export let enc = encV1 | ||
const useV1Encoding = () => { | ||
useV2 = false | ||
enc = encV1 | ||
} | ||
const useV2Encoding = () => { | ||
console.error('sync protocol doesnt support v2 protocol yet, fallback to v1 encoding') // @Todo | ||
useV2 = false | ||
enc = encV1 | ||
} | ||
export class TestYInstance extends Y.Doc { | ||
@@ -48,4 +81,10 @@ /** | ||
testConnector.allConns.add(this) | ||
/** | ||
* The list of received updates. | ||
* We are going to merge them later using Y.mergeUpdates and check if the resulting document is correct. | ||
* @type {Array<Uint8Array>} | ||
*/ | ||
this.updates = [] | ||
// set up observe on local model | ||
this.on('update', /** @param {Uint8Array} update @param {any} origin */ (update, origin) => { | ||
this.on(enc.updateEventName, /** @param {Uint8Array} update @param {any} origin */ (update, origin) => { | ||
if (origin !== testConnector) { | ||
@@ -55,2 +94,3 @@ const encoder = encoding.createEncoder() | ||
broadcastMessage(this, encoding.toUint8Array(encoder)) | ||
this.updates.push(update) | ||
} | ||
@@ -168,2 +208,13 @@ }) | ||
} | ||
{ | ||
// If update message, add the received message to the list of received messages | ||
const decoder = decoding.createDecoder(m) | ||
const messageType = decoding.readVarUint(decoder) | ||
switch (messageType) { | ||
case syncProtocol.messageYjsUpdate: | ||
case syncProtocol.messageYjsSyncStep2: | ||
receiver.updates.push(decoding.readVarUint8Array(decoder)) | ||
break | ||
} | ||
} | ||
return true | ||
@@ -247,5 +298,5 @@ } | ||
if (prng.bool(gen)) { | ||
Y.useV2Encoding() | ||
useV2Encoding() | ||
} else { | ||
Y.useV1Encoding() | ||
useV1Encoding() | ||
} | ||
@@ -266,3 +317,3 @@ | ||
result.testObjects = result.users.map(initTestObject || (() => null)) | ||
Y.useV1Encoding() | ||
useV1Encoding() | ||
return /** @type {any} */ (result) | ||
@@ -283,2 +334,10 @@ } | ||
while (users[0].tc.flushAllMessages()) {} | ||
// For each document, merge all received document updates with Y.mergeUpdates and create a new document which will be added to the list of "users" | ||
// This ensures that mergeUpdates works correctly | ||
const mergedDocs = users.map(user => { | ||
const ydoc = new Y.Doc() | ||
enc.applyUpdate(ydoc, enc.mergeUpdates(user.updates)) | ||
return ydoc | ||
}) | ||
users.push(.../** @type {any} */(mergedDocs)) | ||
const userArrayValues = users.map(u => u.getArray('array').toJSON()) | ||
@@ -289,5 +348,4 @@ const userMapValues = users.map(u => u.getMap('map').toJSON()) | ||
for (const u of users) { | ||
t.assert(u.store.pendingDeleteReaders.length === 0) | ||
t.assert(u.store.pendingStack.length === 0) | ||
t.assert(u.store.pendingClientsStructRefs.size === 0) | ||
t.assert(u.store.pendingDs === null) | ||
t.assert(u.store.pendingStructs === null) | ||
} | ||
@@ -294,0 +352,0 @@ // Test Array iterator |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1986705
93
30847