Create Structs based on offset, if necessary
implement offset parameter in Ref.toStruct
This commit is contained in:
@@ -139,9 +139,6 @@ export class AbstractItem extends AbstractStruct {
|
||||
const parent = this.parent
|
||||
const parentSub = this.parentSub
|
||||
const length = this.length
|
||||
const left = this.left
|
||||
const right = this.right
|
||||
// integrate
|
||||
/*
|
||||
# $this has to find a unique position between origin and the next known character
|
||||
# case 1: $origin equals $o.origin: the $creator parameter decides if left or right
|
||||
@@ -163,8 +160,8 @@ export class AbstractItem extends AbstractStruct {
|
||||
*/
|
||||
let o
|
||||
// set o to the first conflicting item
|
||||
if (left !== null) {
|
||||
o = left.right
|
||||
if (this.left !== null) {
|
||||
o = this.left.right
|
||||
} else if (parentSub !== null) {
|
||||
o = parent._map.get(parentSub) || null
|
||||
} else {
|
||||
@@ -175,7 +172,7 @@ export class AbstractItem extends AbstractStruct {
|
||||
// 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 !== right) {
|
||||
while (o !== null && o !== this.right) {
|
||||
itemsBeforeOrigin.add(o)
|
||||
conflictingItems.add(o)
|
||||
if (this.origin === o.origin) {
|
||||
@@ -199,10 +196,10 @@ export class AbstractItem extends AbstractStruct {
|
||||
o = o.right
|
||||
}
|
||||
// reconnect left/right + update parent map/start if necessary
|
||||
if (left !== null) {
|
||||
const right = left.right
|
||||
if (this.left !== null) {
|
||||
const right = this.left.right
|
||||
this.right = right
|
||||
left.right = this
|
||||
this.left.right = this
|
||||
if (right !== null) {
|
||||
right.left = this
|
||||
}
|
||||
@@ -230,12 +227,12 @@ export class AbstractItem extends AbstractStruct {
|
||||
maplib.setIfUndefined(transaction.changed, parent, set.create).add(parentSub)
|
||||
}
|
||||
// @ts-ignore
|
||||
if ((parent._item !== null && parent._item.deleted) || (left !== null && parentSub !== null)) {
|
||||
if ((parent._item !== null && parent._item.deleted) || (this.left !== null && parentSub !== null)) {
|
||||
// delete if parent is deleted or if this is not the current attribute value of parent
|
||||
this.delete(transaction)
|
||||
} else if (parentSub !== null && left === null && right !== null) {
|
||||
} else if (parentSub !== null && this.left === null && this.right !== null) {
|
||||
// this is the current attribute value of parent. delete right
|
||||
right.delete(transaction)
|
||||
this.right.delete(transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,3 +526,12 @@ export class AbstractItemRef extends AbstractRef {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AbstractItemRef} item
|
||||
* @param {number} offset
|
||||
*/
|
||||
export const changeItemRefOffset = (item, offset) => {
|
||||
item.id = createID(item.id.client, item.id.clock + offset)
|
||||
item.left = createID(item.id.client, item.id.clock - 1)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import {
|
||||
Y, ID, Transaction // eslint-disable-line
|
||||
ID, Transaction // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as encoding from 'lib0/encoding.js' // eslint-disable-line
|
||||
@@ -77,9 +77,10 @@ export class AbstractRef {
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {number} offset
|
||||
* @return {AbstractStruct}
|
||||
*/
|
||||
toStruct (transaction) {
|
||||
toStruct (transaction, offset) {
|
||||
throw error.methodUnimplemented()
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
AbstractStruct,
|
||||
createID,
|
||||
writeID,
|
||||
ID // eslint-disable-line
|
||||
addStruct,
|
||||
Transaction, ID // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as decoding from 'lib0/decoding.js'
|
||||
@@ -42,6 +43,13 @@ export class GC extends AbstractStruct {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
*/
|
||||
integrate (transaction) {
|
||||
addStruct(transaction.y.store, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {encoding.Encoder} encoder
|
||||
* @param {number} offset
|
||||
@@ -65,10 +73,6 @@ export class GCRef extends AbstractRef {
|
||||
*/
|
||||
constructor (decoder, id, info) {
|
||||
super(id)
|
||||
/**
|
||||
* @type {ID}
|
||||
*/
|
||||
this.id = id
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
@@ -83,9 +87,16 @@ export class GCRef extends AbstractRef {
|
||||
]
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @param {number} offset
|
||||
* @return {GC}
|
||||
*/
|
||||
toStruct () {
|
||||
toStruct (transaction, offset) {
|
||||
if (offset > 0) {
|
||||
// @ts-ignore
|
||||
this.id = createID(this.id.client, this.id.clock + offset)
|
||||
this._len = this._len - offset
|
||||
}
|
||||
return new GC(
|
||||
this.id,
|
||||
this._len
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
GC,
|
||||
ItemDeleted,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
@@ -69,17 +71,32 @@ export class ItemBinaryRef extends AbstractItemRef {
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @return {ItemBinary}
|
||||
* @param {number} offset
|
||||
* @return {ItemBinary|GC}
|
||||
*/
|
||||
toStruct (transaction) {
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemBinary(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, transaction, this.left),
|
||||
this.right === null ? null : getItemCleanStart(store, transaction, this.right),
|
||||
// @ts-ignore
|
||||
this.parent === null ? y.get(this.parentYKey) : getItemType(store, this.parent).type,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.content
|
||||
)
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
changeItemRefOffset,
|
||||
GC,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
@@ -84,17 +86,36 @@ export class ItemDeletedRef extends AbstractItemRef {
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @return {ItemDeleted}
|
||||
* @param {number} offset
|
||||
* @return {ItemDeleted|GC}
|
||||
*/
|
||||
toStruct (transaction) {
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
if (offset > 0) {
|
||||
changeItemRefOffset(this, offset)
|
||||
this.len = this.len - offset
|
||||
}
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemDeleted(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, transaction, this.left),
|
||||
this.right === null ? null : getItemCleanStart(store, transaction, this.right),
|
||||
// @ts-ignore
|
||||
this.parent === null ? y.get(this.parentYKey) : getItemType(store, this.parent).type,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.len
|
||||
)
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
ItemDeleted,
|
||||
GC,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
@@ -64,17 +66,32 @@ export class ItemEmbedRef extends AbstractItemRef {
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @return {ItemEmbed}
|
||||
* @param {number} offset
|
||||
* @return {ItemEmbed|GC}
|
||||
*/
|
||||
toStruct (transaction) {
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemEmbed(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, transaction, this.left),
|
||||
this.right === null ? null : getItemCleanStart(store, transaction, this.right),
|
||||
// @ts-ignore
|
||||
this.parent === null ? y.get(this.parentYKey) : getItemType(store, this.parent).type,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.embed
|
||||
)
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
getItemCleanEnd,
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
ItemDeleted,
|
||||
GC,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
@@ -71,17 +73,32 @@ export class ItemFormatRef extends AbstractItemRef {
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @return {ItemFormat}
|
||||
* @param {number} offset
|
||||
* @return {ItemFormat|GC}
|
||||
*/
|
||||
toStruct (transaction) {
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemFormat(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, transaction, this.left),
|
||||
this.right === null ? null : getItemCleanStart(store, transaction, this.right),
|
||||
// @ts-ignore
|
||||
this.parent === null ? y.get(this.parentYKey) : getItemType(store, this.parent).type,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.key,
|
||||
this.value
|
||||
|
||||
@@ -9,6 +9,9 @@ import {
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
splitItem,
|
||||
changeItemRefOffset,
|
||||
GC,
|
||||
ItemDeleted,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
@@ -106,6 +109,9 @@ export class ItemJSONRef extends AbstractItemRef {
|
||||
cs.push(JSON.parse(c))
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
this.content = cs
|
||||
}
|
||||
get length () {
|
||||
@@ -113,17 +119,34 @@ export class ItemJSONRef extends AbstractItemRef {
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @return {ItemJSON}
|
||||
* @param {number} offset
|
||||
* @return {ItemJSON|GC}
|
||||
*/
|
||||
toStruct (transaction) {
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
if (offset > 0) {
|
||||
changeItemRefOffset(this, offset)
|
||||
this.content = this.content.slice(offset)
|
||||
}
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, this.content.length)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
return new ItemJSON(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, transaction, this.left),
|
||||
this.right === null ? null : getItemCleanStart(store, transaction, this.right),
|
||||
// @ts-ignore
|
||||
this.parent === null ? y.get(this.parentYKey) : getItemType(store, this.parent).type,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.content
|
||||
)
|
||||
|
||||
@@ -8,6 +8,9 @@ import {
|
||||
getItemCleanStart,
|
||||
getItemType,
|
||||
splitItem,
|
||||
changeItemRefOffset,
|
||||
ItemDeleted,
|
||||
GC,
|
||||
Transaction, ID, AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
@@ -102,17 +105,36 @@ export class ItemStringRef extends AbstractItemRef {
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @return {ItemString}
|
||||
* @param {number} offset
|
||||
* @return {ItemString|GC}
|
||||
*/
|
||||
toStruct (transaction) {
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
if (offset > 0) {
|
||||
changeItemRefOffset(this, offset)
|
||||
this.string = this.string.slice(offset)
|
||||
}
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, this.string.length)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemString(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, transaction, this.left),
|
||||
this.right === null ? null : getItemCleanStart(store, transaction, this.right),
|
||||
// @ts-ignore
|
||||
this.parent === null ? y.get(this.parentYKey) : getItemType(store, this.parent).type,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.string
|
||||
)
|
||||
|
||||
@@ -168,17 +168,32 @@ export class ItemTypeRef extends AbstractItemRef {
|
||||
}
|
||||
/**
|
||||
* @param {Transaction} transaction
|
||||
* @return {ItemType}
|
||||
* @param {number} offset
|
||||
* @return {ItemType|GC}
|
||||
*/
|
||||
toStruct (transaction) {
|
||||
toStruct (transaction, offset) {
|
||||
const y = transaction.y
|
||||
const store = y.store
|
||||
|
||||
let parent
|
||||
if (this.parent !== null) {
|
||||
const parentItem = getItemType(store, this.parent)
|
||||
switch (parentItem.constructor) {
|
||||
case ItemDeleted:
|
||||
case GC:
|
||||
return new GC(this.id, 1)
|
||||
}
|
||||
parent = parentItem.type
|
||||
} else {
|
||||
// @ts-ignore
|
||||
parent = y.get(this.parentYKey)
|
||||
}
|
||||
|
||||
return new ItemType(
|
||||
this.id,
|
||||
this.left === null ? null : getItemCleanEnd(store, transaction, this.left),
|
||||
this.right === null ? null : getItemCleanStart(store, transaction, this.right),
|
||||
// @ts-ignore
|
||||
this.parent === null ? y.get(this.parentYKey) : getItemType(store, this.parent).type,
|
||||
parent,
|
||||
this.parentSub,
|
||||
this.type
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user