From 541306b254dac825a8e8f2393936bb67975f0122 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Thu, 29 Feb 2024 17:08:57 +0100 Subject: [PATCH] migrate to ObservableV2 --- src/utils/AbstractConnector.js | 6 ++--- src/utils/Doc.js | 45 +++++++++++++++++----------------- src/utils/UndoManager.js | 23 ++++++++++++----- tests/testHelper.js | 4 +-- tests/updates.tests.js | 16 ++++++------ 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/utils/AbstractConnector.js b/src/utils/AbstractConnector.js index 5f544684..f5c0566a 100644 --- a/src/utils/AbstractConnector.js +++ b/src/utils/AbstractConnector.js @@ -1,4 +1,4 @@ -import { Observable } from 'lib0/observable' +import { ObservableV2 } from 'lib0/observable' import { Doc // eslint-disable-line @@ -10,9 +10,9 @@ import { * @note This interface is experimental and it is not advised to actually inherit this class. * It just serves as typing information. * - * @extends {Observable} + * @extends {ObservableV2} */ -export class AbstractConnector extends Observable { +export class AbstractConnector extends ObservableV2 { /** * @param {Doc} ydoc * @param {any} awareness diff --git a/src/utils/Doc.js b/src/utils/Doc.js index 0d8d471b..8a8936b9 100644 --- a/src/utils/Doc.js +++ b/src/utils/Doc.js @@ -14,7 +14,7 @@ import { ContentDoc, Item, Transaction, YEvent // eslint-disable-line } from '../internals.js' -import { Observable } from 'lib0/observable' +import { ObservableV2 } from 'lib0/observable' import * as random from 'lib0/random' import * as map from 'lib0/map' import * as array from 'lib0/array' @@ -34,10 +34,26 @@ export const generateNewClientId = random.uint32 */ /** - * A Yjs instance handles the state of shared data. - * @extends Observable + * @typedef {Object} DocEvents + * @property {function(Doc):void} DocEvents.destroy + * @property {function(Doc):void} DocEvents.load + * @property {function(boolean, Doc):void} DocEvents.sync + * @property {function(Uint8Array, any, Doc, Transaction):void} DocEvents.update + * @property {function(Uint8Array, any, Doc, Transaction):void} DocEvents.updateV2 + * @property {function(Doc):void} DocEvents.beforeAllTransactions + * @property {function(Transaction, Doc):void} DocEvents.beforeTransaction + * @property {function(Transaction, Doc):void} DocEvents.beforeObserverCalls + * @property {function(Transaction, Doc):void} DocEvents.afterTransaction + * @property {function(Transaction, Doc):void} DocEvents.afterTransactionCleanup + * @property {function(Doc, Array):void} DocEvents.afterAllTransactions + * @property {function({ loaded: Set, added: Set, removed: Set }, Doc, Transaction):void} DocEvents.subdocs */ -export class Doc extends Observable { + +/** + * A Yjs instance handles the state of shared data. + * @extends ObservableV2 + */ +export class Doc extends ObservableV2 { /** * @param {DocOpts} opts configuration */ @@ -115,7 +131,7 @@ export class Doc extends Observable { } this.isSynced = isSynced === undefined || isSynced === true if (this.isSynced && !this.isLoaded) { - this.emit('load', []) + this.emit('load', [this]) } }) /** @@ -321,24 +337,9 @@ export class Doc extends Observable { transaction.subdocsRemoved.add(this) }, null, true) } - this.emit('destroyed', [true]) + // @ts-ignore + this.emit('destroyed', [true]) // DEPRECATED! this.emit('destroy', [this]) super.destroy() } - - /** - * @param {string} eventName - * @param {function(...any):any} f - */ - on (eventName, f) { - super.on(eventName, f) - } - - /** - * @param {string} eventName - * @param {function} f - */ - off (eventName, f) { - super.off(eventName, f) - } } diff --git a/src/utils/UndoManager.js b/src/utils/UndoManager.js index 16ccb7ae..27023ecf 100644 --- a/src/utils/UndoManager.js +++ b/src/utils/UndoManager.js @@ -10,13 +10,13 @@ import { getItemCleanStart, isDeleted, addToDeleteSet, - Transaction, Doc, Item, GC, DeleteSet, AbstractType // eslint-disable-line + YEvent, Transaction, Doc, Item, GC, DeleteSet, AbstractType // eslint-disable-line } from '../internals.js' import * as time from 'lib0/time' import * as array from 'lib0/array' import * as logging from 'lib0/logging' -import { Observable } from 'lib0/observable' +import { ObservableV2 } from 'lib0/observable' export class StackItem { /** @@ -48,7 +48,7 @@ const clearUndoManagerStackItem = (tr, um, stackItem) => { /** * @param {UndoManager} undoManager * @param {Array} stack - * @param {string} eventType + * @param {'undo'|'redo'} eventType * @return {StackItem?} */ const popStackItem = (undoManager, stack, eventType) => { @@ -120,7 +120,7 @@ const popStackItem = (undoManager, stack, eventType) => { }, undoManager) if (undoManager.currStackItem != null) { const changedParentTypes = _tr.changedParentTypes - undoManager.emit('stack-item-popped', [{ stackItem: undoManager.currStackItem, type: eventType, changedParentTypes }, undoManager]) + undoManager.emit('stack-item-popped', [{ stackItem: undoManager.currStackItem, type: eventType, changedParentTypes, origin: undoManager }, undoManager]) undoManager.currStackItem = null } return undoManager.currStackItem @@ -139,6 +139,14 @@ const popStackItem = (undoManager, stack, eventType) => { * @property {Doc} [doc] The document that this UndoManager operates on. Only needed if typeScope is empty. */ +/** + * @typedef {Object} StackItemEvent + * @property {StackItem} StackItemEvent.stackItem + * @property {any} StackItemEvent.origin + * @property {'undo'|'redo'} StackItemEvent.type + * @property {Map>,Array>>} StackItemEvent.changedParentTypes + */ + /** * Fires 'stack-item-added' event when a stack item was added to either the undo- or * the redo-stack. You may store additional stack information via the @@ -146,9 +154,9 @@ const popStackItem = (undoManager, stack, eventType) => { * Fires 'stack-item-popped' event when a stack item was popped from either the * undo- or the redo-stack. You may restore the saved stack information from `event.stackItem.meta`. * - * @extends {Observable<'stack-item-added'|'stack-item-popped'|'stack-cleared'|'stack-item-updated'>} + * @extends {ObservableV2<{'stack-item-added':function(StackItemEvent, UndoManager):void, 'stack-item-popped': function(StackItemEvent, UndoManager):void, 'stack-cleared': function({ undoStackCleared: boolean, redoStackCleared: boolean }):void, 'stack-item-updated': function(StackItemEvent, UndoManager):void }>} */ -export class UndoManager extends Observable { +export class UndoManager extends ObservableV2 { /** * @param {AbstractType|Array>} typeScope Accepts either a single type, or an array of types * @param {UndoManagerOptions} options @@ -246,6 +254,9 @@ export class UndoManager extends Observable { keepItem(item, true) } }) + /** + * @type {[StackItemEvent, UndoManager]} + */ const changeEvent = [{ stackItem: stack[stack.length - 1], origin: transaction.origin, type: undoing ? 'redo' : 'undo', changedParentTypes: transaction.changedParentTypes }, this] if (didAdd) { this.emit('stack-item-added', changeEvent) diff --git a/tests/testHelper.js b/tests/testHelper.js index c74b7438..56983679 100644 --- a/tests/testHelper.js +++ b/tests/testHelper.js @@ -34,7 +34,7 @@ export const encV1 = { mergeUpdates: Y.mergeUpdates, applyUpdate: Y.applyUpdate, logUpdate: Y.logUpdate, - updateEventName: 'update', + updateEventName: /** @type {'update'} */ ('update'), diffUpdate: Y.diffUpdate } @@ -43,7 +43,7 @@ export const encV2 = { mergeUpdates: Y.mergeUpdatesV2, applyUpdate: Y.applyUpdateV2, logUpdate: Y.logUpdateV2, - updateEventName: 'updateV2', + updateEventName: /** @type {'updateV2'} */ ('updateV2'), diffUpdate: Y.diffUpdateV2 } diff --git a/tests/updates.tests.js b/tests/updates.tests.js index 4ba3bab6..f3169cfe 100644 --- a/tests/updates.tests.js +++ b/tests/updates.tests.js @@ -15,7 +15,7 @@ import * as object from 'lib0/object' * @property {function(Uint8Array):{from:Map,to:Map}} Enc.parseUpdateMeta * @property {function(Y.Doc):Uint8Array} Enc.encodeStateVector * @property {function(Uint8Array):Uint8Array} Enc.encodeStateVectorFromUpdate - * @property {string} Enc.updateEventName + * @property {'update'|'updateV2'} Enc.updateEventName * @property {string} Enc.description * @property {function(Uint8Array, Uint8Array):Uint8Array} Enc.diffUpdate */ @@ -169,7 +169,7 @@ const checkUpdateCases = (ydoc, updates, enc, hasDeletes) => { // t.info('Target State: ') // enc.logUpdate(targetState) - cases.forEach((mergedUpdates, i) => { + cases.forEach((mergedUpdates) => { // t.info('State Case $' + i + ':') // enc.logUpdate(updates) const merged = new Y.Doc({ gc: false }) @@ -218,10 +218,10 @@ const checkUpdateCases = (ydoc, updates, enc, hasDeletes) => { } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testMergeUpdates1 = tc => { - encoders.forEach((enc, i) => { +export const testMergeUpdates1 = _tc => { + encoders.forEach((enc) => { t.info(`Using encoder: ${enc.description}`) const ydoc = new Y.Doc({ gc: false }) const updates = /** @type {Array} */ ([]) @@ -299,16 +299,16 @@ export const testMergePendingUpdates = tc => { Y.applyUpdate(yDoc5, update4) Y.applyUpdate(yDoc5, serverUpdates[4]) // @ts-ignore - const update5 = Y.encodeStateAsUpdate(yDoc5) // eslint-disable-line + const _update5 = Y.encodeStateAsUpdate(yDoc5) // eslint-disable-line const yText5 = yDoc5.getText('textBlock') t.compareStrings(yText5.toString(), 'nenor') } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testObfuscateUpdates = tc => { +export const testObfuscateUpdates = _tc => { const ydoc = new Y.Doc() const ytext = ydoc.getText('text') const ymap = ydoc.getMap('map')