// yjs 13.6.7 — node_modules/yjs/src/structs/Item.js lines 414-487, Item.integrate(). MIT, Copyright (c) 2014 Kevin Jahns, Chair of Computer Science 5, RWTH Aachen University. // Copied byte for byte from the archive's own node_modules. The two header lines are not part of the source; the body below starts at line 414 and the tiebreak is at line 467. /** * @param {Transaction} transaction * @param {number} offset */ integrate (transaction, offset) { if (offset > 0) { this.id.clock += offset this.left = getItemCleanEnd(transaction, transaction.doc.store, createID(this.id.client, this.id.clock - 1)) this.origin = this.left.lastId this.content = this.content.splice(offset) this.length -= offset } if (this.parent) { if ((!this.left && (!this.right || this.right.left !== null)) || (this.left && this.left.right !== this.right)) { /** * @type {Item|null} */ let left = this.left /** * @type {Item|null} */ let o // set o to the first conflicting item if (left !== null) { o = left.right } else if (this.parentSub !== null) { o = /** @type {AbstractType} */ (this.parent)._map.get(this.parentSub) || null while (o !== null && o.left !== null) { o = o.left } } else { o = /** @type {AbstractType} */ (this.parent)._start } // TODO: use something like DeleteSet here (a tree implementation would be best) // @todo use global set definitions /** * @type {Set} */ const conflictingItems = new Set() /** * @type {Set} */ const itemsBeforeOrigin = new Set() // Let c in conflictingItems, b in itemsBeforeOrigin // ***{origin}bbbb{this}{c,b}{c,b}{o}*** // Note that conflictingItems is a subset of itemsBeforeOrigin while (o !== null && o !== this.right) { itemsBeforeOrigin.add(o) conflictingItems.add(o) if (compareIDs(this.origin, o.origin)) { // case 1 if (o.id.client < this.id.client) { left = o conflictingItems.clear() } else if (compareIDs(this.rightOrigin, o.rightOrigin)) { // this and o are conflicting and point to the same integration points. The id decides which item comes first. // Since this is to the left of o, we can break here break } // else, o might be integrated before an item that this conflicts with. If so, we will find it in the next iterations } else if (o.origin !== null && itemsBeforeOrigin.has(getItem(transaction.doc.store, o.origin))) { // use getItem instead of getItemCleanEnd because we don't want / need to split items. // case 2 if (!conflictingItems.has(getItem(transaction.doc.store, o.origin))) { left = o conflictingItems.clear() } } else { break } o = o.right } this.left = left }