diff --git a/src/structs/ContentAny.js b/src/structs/ContentAny.js index 3ab2dc5f..ba7a1b77 100644 --- a/src/structs/ContentAny.js +++ b/src/structs/ContentAny.js @@ -76,9 +76,9 @@ export class ContentAny { */ delete (transaction) {} /** - * @param {StructStore} store + * @param {Transaction} _tr */ - gc (store) {} + gc (_tr) {} /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder * @param {number} offset diff --git a/src/structs/ContentBinary.js b/src/structs/ContentBinary.js index 2708f53b..a376dbbc 100644 --- a/src/structs/ContentBinary.js +++ b/src/structs/ContentBinary.js @@ -66,9 +66,9 @@ export class ContentBinary { */ delete (transaction) {} /** - * @param {StructStore} store + * @param {Transaction} _tr */ - gc (store) {} + gc (_tr) {} /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder * @param {number} offset diff --git a/src/structs/ContentDeleted.js b/src/structs/ContentDeleted.js index dc9b776c..102bcdfa 100644 --- a/src/structs/ContentDeleted.js +++ b/src/structs/ContentDeleted.js @@ -68,13 +68,13 @@ export class ContentDeleted { } /** - * @param {Transaction} transaction + * @param {Transaction} _transaction */ - delete (transaction) {} + delete (_transaction) {} /** - * @param {StructStore} store + * @param {Transaction} _tr */ - gc (store) {} + gc (_tr) {} /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder * @param {number} offset diff --git a/src/structs/ContentDoc.js b/src/structs/ContentDoc.js index 15836f51..8491272b 100644 --- a/src/structs/ContentDoc.js +++ b/src/structs/ContentDoc.js @@ -110,9 +110,9 @@ export class ContentDoc { } /** - * @param {StructStore} store + * @param {Transaction} _tr */ - gc (store) { } + gc (_tr) {} /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder diff --git a/src/structs/ContentEmbed.js b/src/structs/ContentEmbed.js index 46fba375..4cb2f922 100644 --- a/src/structs/ContentEmbed.js +++ b/src/structs/ContentEmbed.js @@ -69,9 +69,9 @@ export class ContentEmbed { */ delete (transaction) {} /** - * @param {StructStore} store + * @param {Transaction} _tr */ - gc (store) {} + gc (_tr) {} /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder * @param {number} offset diff --git a/src/structs/ContentFormat.js b/src/structs/ContentFormat.js index 631e7755..d79aa885 100644 --- a/src/structs/ContentFormat.js +++ b/src/structs/ContentFormat.js @@ -77,9 +77,9 @@ export class ContentFormat { */ delete (_transaction) {} /** - * @param {StructStore} _store + * @param {Transaction} _tr */ - gc (_store) {} + gc (_tr) {} /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder * @param {number} _offset diff --git a/src/structs/ContentJSON.js b/src/structs/ContentJSON.js index 29b2f754..17591756 100644 --- a/src/structs/ContentJSON.js +++ b/src/structs/ContentJSON.js @@ -73,9 +73,9 @@ export class ContentJSON { */ delete (transaction) {} /** - * @param {StructStore} store + * @param {Transaction} _tr */ - gc (store) {} + gc (_tr) {} /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder * @param {number} offset diff --git a/src/structs/ContentString.js b/src/structs/ContentString.js index fa023ef9..a2f5f368 100644 --- a/src/structs/ContentString.js +++ b/src/structs/ContentString.js @@ -84,9 +84,9 @@ export class ContentString { */ delete (transaction) {} /** - * @param {StructStore} store + * @param {Transaction} _tr */ - gc (store) {} + gc (_tr) {} /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder * @param {number} offset diff --git a/src/structs/ContentType.js b/src/structs/ContentType.js index 597c8719..13a09cd0 100644 --- a/src/structs/ContentType.js +++ b/src/structs/ContentType.js @@ -128,18 +128,18 @@ export class ContentType { } /** - * @param {StructStore} store + * @param {Transaction} tr */ - gc (store) { + gc (tr) { let item = this.type._start while (item !== null) { - item.gc(store, true) + item.gc(tr, true) item = item.right } this.type._start = null this.type._map.forEach(/** @param {Item | null} item */ (item) => { while (item !== null) { - item.gc(store, true) + item.gc(tr, true) item = item.left } }) @@ -148,9 +148,9 @@ export class ContentType { /** * @param {UpdateEncoderV1 | UpdateEncoderV2} encoder - * @param {number} offset + * @param {number} _offset */ - write (encoder, offset) { + write (encoder, _offset) { this.type._write(encoder) } diff --git a/src/structs/GC.js b/src/structs/GC.js index 788cb5ec..8f1d2f9e 100644 --- a/src/structs/GC.js +++ b/src/structs/GC.js @@ -3,8 +3,7 @@ import { addStruct, addStructToIdSet, addToIdSet, - UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, // eslint-disable-line - createID + UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction // eslint-disable-line } from '../internals.js' export const structGCRefNumber = 0 @@ -55,20 +54,23 @@ export class GC extends AbstractStruct { } /** - * @param {Transaction} transaction - * @param {StructStore} store + * @param {Transaction} _transaction + * @param {StructStore} _store * @return {null | number} */ - getMissing (transaction, store) { + getMissing (_transaction, _store) { return null } /** - * @param {number} diff + * gc structs can't be spliced. + * + * If this feature is required in the future, then need to try to merge this struct after + * transaction. + * + * @param {number} _diff */ - splice (diff) { - const other = new GC(createID(this.id.client, this.id.clock + diff), this.length - diff) - this.length = diff - return other + splice (_diff) { + return this } } diff --git a/src/structs/Item.js b/src/structs/Item.js index c0b281ec..042c971c 100644 --- a/src/structs/Item.js +++ b/src/structs/Item.js @@ -634,16 +634,16 @@ export class Item extends AbstractStruct { } /** - * @param {StructStore} store + * @param {Transaction} tr * @param {boolean} parentGCd */ - gc (store, parentGCd) { + gc (tr, parentGCd) { if (!this.deleted) { throw error.unexpectedCase() } - this.content.gc(store) + this.content.gc(tr) if (parentGCd) { - replaceStruct(store, this, new GC(this.id, this.length)) + replaceStruct(tr, this, new GC(this.id, this.length)) } else { this.content = new ContentDeleted(this.length) } @@ -799,9 +799,9 @@ export class AbstractContent { } /** - * @param {StructStore} _store + * @param {Transaction} _transaction */ - gc (_store) { + gc (_transaction) { throw error.methodUnimplemented() } diff --git a/src/utils/StructStore.js b/src/utils/StructStore.js index 27cc6126..fdcd7a5a 100644 --- a/src/utils/StructStore.js +++ b/src/utils/StructStore.js @@ -198,7 +198,7 @@ export const getItem = /** @type {function(StructStore,ID):Item} */ (find) export const findIndexCleanStart = (transaction, structs, clock) => { const index = findIndexSS(structs, clock) const struct = structs[index] - if (struct.id.clock < clock) { + if (struct.id.clock < clock && struct.constructor !== GC) { structs.splice(index + 1, 0, struct instanceof Item ? splitItem(transaction, struct, clock - struct.id.clock) : struct.splice(clock - struct.id.clock)) return index + 1 } @@ -247,16 +247,17 @@ export const getItemCleanEnd = (transaction, store, id) => { /** * Replace `item` with `newitem` in store - * @param {StructStore} store + * @param {Transaction} tr * @param {GC|Item} struct * @param {GC|Item} newStruct * * @private * @function */ -export const replaceStruct = (store, struct, newStruct) => { - const structs = /** @type {Array} */ (store.clients.get(struct.id.client)) +export const replaceStruct = (tr, struct, newStruct) => { + const structs = /** @type {Array} */ (tr.doc.store.clients.get(struct.id.client)) structs[findIndexSS(structs, struct.id.clock)] = newStruct + tr._mergeStructs.push(newStruct) } /** diff --git a/src/utils/Transaction.js b/src/utils/Transaction.js index eab66829..98caf979 100644 --- a/src/utils/Transaction.js +++ b/src/utils/Transaction.js @@ -10,8 +10,7 @@ import { generateNewClientId, createID, cleanupYTextAfterTransaction, - IdSet, UpdateEncoderV1, UpdateEncoderV2, GC, StructStore, AbstractType, AbstractStruct, YEvent, Doc, - diffIdSet, // eslint-disable-line + IdSet, UpdateEncoderV1, UpdateEncoderV2, GC, StructStore, AbstractType, AbstractStruct, YEvent, Doc // insertIntoIdSet } from '../internals.js' @@ -239,14 +238,14 @@ const tryToMergeWithLefts = (structs, pos) => { } /** + * @param {Transaction} tr * @param {IdSet} ds - * @param {StructStore} store * @param {function(Item):boolean} gcFilter */ -const tryGcDeleteSet = (ds, store, gcFilter) => { +const tryGcDeleteSet = (tr, ds, gcFilter) => { for (const [client, _deleteItems] of ds.clients.entries()) { const deleteItems = _deleteItems.getIds() - const structs = /** @type {Array} */ (store.clients.get(client)) + const structs = /** @type {Array} */ (tr.doc.store.clients.get(client)) for (let di = deleteItems.length - 1; di >= 0; di--) { const deleteItem = deleteItems[di] const endDeleteItemClock = deleteItem.clock + deleteItem.len @@ -260,7 +259,7 @@ const tryGcDeleteSet = (ds, store, gcFilter) => { break } if (struct instanceof Item && struct.deleted && !struct.keep && gcFilter(struct)) { - struct.gc(store, false) + struct.gc(tr, false) } } } @@ -271,7 +270,7 @@ const tryGcDeleteSet = (ds, store, gcFilter) => { * @param {IdSet} ds * @param {StructStore} store */ -const tryMergeDeleteSet = (ds, store) => { +const tryMerge = (ds, store) => { // try to merge deleted / gc'd items // merge from right to left for better efficiency and so we don't miss any merge targets ds.clients.forEach((_deleteItems, client) => { @@ -293,13 +292,13 @@ const tryMergeDeleteSet = (ds, store) => { } /** - * @param {IdSet} ds - * @param {StructStore} store + * @param {Transaction} tr + * @param {IdSet} idset * @param {function(Item):boolean} gcFilter */ -export const tryGc = (ds, store, gcFilter) => { - tryGcDeleteSet(ds, store, gcFilter) - tryMergeDeleteSet(ds, store) +export const tryGc = (tr, idset, gcFilter) => { + tryGcDeleteSet(tr, idset, gcFilter) + tryMerge(idset, tr.doc.store) } /** @@ -367,9 +366,9 @@ const cleanupTransactions = (transactionCleanups, i) => { // Replace deleted items with ItemDeleted / GC. // This is where content is actually remove from the Yjs Doc. if (doc.gc) { - tryGcDeleteSet(ds, store, doc.gcFilter) + tryGcDeleteSet(transaction, ds, doc.gcFilter) } - tryMergeDeleteSet(ds, store) + tryMerge(ds, store) // on all affected store.clients props, try to merge transaction.insertSet.clients.forEach((ids, client) => {