parent
							
								
									90f2a06b5e
								
							
						
					
					
						commit
						c77dedb68d
					
				@ -108,7 +108,7 @@ export class ContentType {
 | 
				
			|||||||
    while (item !== null) {
 | 
					    while (item !== null) {
 | 
				
			||||||
      if (!item.deleted) {
 | 
					      if (!item.deleted) {
 | 
				
			||||||
        item.delete(transaction)
 | 
					        item.delete(transaction)
 | 
				
			||||||
      } else {
 | 
					      } else if (item.id.clock < (transaction.beforeState.get(item.id.client) || 0)) {
 | 
				
			||||||
        // This will be gc'd later and we want to merge it if possible
 | 
					        // This will be gc'd later and we want to merge it if possible
 | 
				
			||||||
        // We try to merge all deleted items after each transaction,
 | 
					        // We try to merge all deleted items after each transaction,
 | 
				
			||||||
        // but we have no knowledge about that this needs to be merged
 | 
					        // but we have no knowledge about that this needs to be merged
 | 
				
			||||||
@ -120,7 +120,7 @@ export class ContentType {
 | 
				
			|||||||
    this.type._map.forEach(item => {
 | 
					    this.type._map.forEach(item => {
 | 
				
			||||||
      if (!item.deleted) {
 | 
					      if (!item.deleted) {
 | 
				
			||||||
        item.delete(transaction)
 | 
					        item.delete(transaction)
 | 
				
			||||||
      } else {
 | 
					      } else if (item.id.clock < (transaction.beforeState.get(item.id.client) || 0)) {
 | 
				
			||||||
        // same as above
 | 
					        // same as above
 | 
				
			||||||
        transaction._mergeStructs.push(item)
 | 
					        transaction._mergeStructs.push(item)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
@ -166,18 +166,29 @@ export const addChangedTypeToTransaction = (transaction, type, parentSub) => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {Array<AbstractStruct>} structs
 | 
					 * @param {Array<AbstractStruct>} structs
 | 
				
			||||||
 * @param {number} pos
 | 
					 * @param {number} pos
 | 
				
			||||||
 | 
					 * @return {number} # of merged structs
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const tryToMergeWithLeft = (structs, pos) => {
 | 
					const tryToMergeWithLefts = (structs, pos) => {
 | 
				
			||||||
  const left = structs[pos - 1]
 | 
					  let right = structs[pos]
 | 
				
			||||||
  const right = structs[pos]
 | 
					  let left = structs[pos - 1]
 | 
				
			||||||
  if (left.deleted === right.deleted && left.constructor === right.constructor) {
 | 
					  let i = pos
 | 
				
			||||||
    if (left.mergeWith(right)) {
 | 
					  for (; i > 0; right = left, left = structs[--i - 1]) {
 | 
				
			||||||
      structs.splice(pos, 1)
 | 
					    if (left.deleted === right.deleted && left.constructor === right.constructor) {
 | 
				
			||||||
      if (right instanceof Item && right.parentSub !== null && /** @type {AbstractType<any>} */ (right.parent)._map.get(right.parentSub) === right) {
 | 
					      if (left.mergeWith(right)) {
 | 
				
			||||||
        /** @type {AbstractType<any>} */ (right.parent)._map.set(right.parentSub, /** @type {Item} */ (left))
 | 
					        if (right instanceof Item && right.parentSub !== null && /** @type {AbstractType<any>} */ (right.parent)._map.get(right.parentSub) === right) {
 | 
				
			||||||
 | 
					          /** @type {AbstractType<any>} */ (right.parent)._map.set(right.parentSub, /** @type {Item} */ (left))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        continue
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    break
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  const merged = pos - i
 | 
				
			||||||
 | 
					  if (merged) {
 | 
				
			||||||
 | 
					    // remove all merged structs from the array
 | 
				
			||||||
 | 
					    structs.splice(pos + 1 - merged, merged)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return merged
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -224,9 +235,9 @@ const tryMergeDeleteSet = (ds, store) => {
 | 
				
			|||||||
      for (
 | 
					      for (
 | 
				
			||||||
        let si = mostRightIndexToCheck, struct = structs[si];
 | 
					        let si = mostRightIndexToCheck, struct = structs[si];
 | 
				
			||||||
        si > 0 && struct.id.clock >= deleteItem.clock;
 | 
					        si > 0 && struct.id.clock >= deleteItem.clock;
 | 
				
			||||||
        struct = structs[--si]
 | 
					        struct = structs[si]
 | 
				
			||||||
      ) {
 | 
					      ) {
 | 
				
			||||||
        tryToMergeWithLeft(structs, si)
 | 
					        si -= 1 + tryToMergeWithLefts(structs, si)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -318,23 +329,25 @@ const cleanupTransactions = (transactionCleanups, i) => {
 | 
				
			|||||||
          const structs = /** @type {Array<GC|Item>} */ (store.clients.get(client))
 | 
					          const structs = /** @type {Array<GC|Item>} */ (store.clients.get(client))
 | 
				
			||||||
          // we iterate from right to left so we can safely remove entries
 | 
					          // we iterate from right to left so we can safely remove entries
 | 
				
			||||||
          const firstChangePos = math.max(findIndexSS(structs, beforeClock), 1)
 | 
					          const firstChangePos = math.max(findIndexSS(structs, beforeClock), 1)
 | 
				
			||||||
          for (let i = structs.length - 1; i >= firstChangePos; i--) {
 | 
					          for (let i = structs.length - 1; i >= firstChangePos;) {
 | 
				
			||||||
            tryToMergeWithLeft(structs, i)
 | 
					            i -= 1 + tryToMergeWithLefts(structs, i)
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      // try to merge mergeStructs
 | 
					      // try to merge mergeStructs
 | 
				
			||||||
      // @todo: it makes more sense to transform mergeStructs to a DS, sort it, and merge from right to left
 | 
					      // @todo: it makes more sense to transform mergeStructs to a DS, sort it, and merge from right to left
 | 
				
			||||||
      //        but at the moment DS does not handle duplicates
 | 
					      //        but at the moment DS does not handle duplicates
 | 
				
			||||||
      for (let i = 0; i < mergeStructs.length; i++) {
 | 
					      for (let i = mergeStructs.length - 1; i >= 0; i--) {
 | 
				
			||||||
        const { client, clock } = mergeStructs[i].id
 | 
					        const { client, clock } = mergeStructs[i].id
 | 
				
			||||||
        const structs = /** @type {Array<GC|Item>} */ (store.clients.get(client))
 | 
					        const structs = /** @type {Array<GC|Item>} */ (store.clients.get(client))
 | 
				
			||||||
        const replacedStructPos = findIndexSS(structs, clock)
 | 
					        const replacedStructPos = findIndexSS(structs, clock)
 | 
				
			||||||
        if (replacedStructPos + 1 < structs.length) {
 | 
					        if (replacedStructPos + 1 < structs.length) {
 | 
				
			||||||
          tryToMergeWithLeft(structs, replacedStructPos + 1)
 | 
					          if (tryToMergeWithLefts(structs, replacedStructPos + 1) > 1) {
 | 
				
			||||||
 | 
					            continue // no need to perform next check, both are already merged
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (replacedStructPos > 0) {
 | 
					        if (replacedStructPos > 0) {
 | 
				
			||||||
          tryToMergeWithLeft(structs, replacedStructPos)
 | 
					          tryToMergeWithLefts(structs, replacedStructPos)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (!transaction.local && transaction.afterState.get(doc.clientID) !== transaction.beforeState.get(doc.clientID)) {
 | 
					      if (!transaction.local && transaction.afterState.get(doc.clientID) !== transaction.beforeState.get(doc.clientID)) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user