prelim gc
This commit is contained in:
parent
32207cbca0
commit
d915c8dd13
@ -13,18 +13,18 @@ export function deleteItemRange (y, user, clock, range) {
|
||||
if (item !== null) {
|
||||
if (!item._deleted) {
|
||||
item._splitAt(y, range)
|
||||
item._delete(y, createDelete)
|
||||
item._delete(y, createDelete, true)
|
||||
}
|
||||
let itemLen = item._length
|
||||
range -= itemLen
|
||||
clock += itemLen
|
||||
if (range > 0) {
|
||||
let node = y.os.findNode(new ID(user, clock))
|
||||
while (node !== null && range > 0 && node.val._id.equals(new ID(user, clock))) {
|
||||
while (node !== null && node.val !== null && range > 0 && node.val._id.equals(new ID(user, clock))) {
|
||||
const nodeVal = node.val
|
||||
if (!nodeVal._deleted) {
|
||||
nodeVal._splitAt(y, range)
|
||||
nodeVal._delete(y, createDelete)
|
||||
nodeVal._delete(y, createDelete, true)
|
||||
}
|
||||
const nodeLen = nodeVal._length
|
||||
range -= nodeLen
|
||||
|
44
src/Struct/GC.js
Normal file
44
src/Struct/GC.js
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
export default class GC {
|
||||
constructor () {
|
||||
this._id = null
|
||||
this._length = 0
|
||||
}
|
||||
|
||||
get _deleted () {
|
||||
return true
|
||||
}
|
||||
|
||||
integrate () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the properties of this type to binary and write it to an
|
||||
* BinaryEncoder.
|
||||
*
|
||||
* This is called when this Item is sent to a remote peer.
|
||||
*
|
||||
* @param {BinaryEncoder} encoder The encoder to write data to.
|
||||
* @private
|
||||
*/
|
||||
_toBinary (encoder) {
|
||||
encoder.writeUint8(getStructReference(this.constructor))
|
||||
encoder.writeID(this._id)
|
||||
encoder.writeVarUint(this._length)
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next Item in a Decoder and fill this Item with the read data.
|
||||
*
|
||||
* This is called when data is received from a remote peer.
|
||||
*
|
||||
* @param {Y} y The Yjs instance that this Item belongs to.
|
||||
* @param {BinaryDecoder} decoder The decoder object to read data from.
|
||||
* @private
|
||||
*/
|
||||
_fromBinary (y, decoder) {
|
||||
this._id = decoder.readID()
|
||||
this._length = decoder.readVarUint()
|
||||
return []
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import ID from '../Util/ID/ID.js'
|
||||
import { RootFakeUserID } from '../Util/ID/RootID.js'
|
||||
import Delete from './Delete.js'
|
||||
import { transactionTypeChanged } from '../Transaction.js'
|
||||
import GC from './GC.js'
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -220,7 +221,7 @@ export default class Item {
|
||||
_delete (y, createDelete = true) {
|
||||
if (!this._deleted) {
|
||||
this._deleted = true
|
||||
y.ds.markDeleted(this._id, this._length)
|
||||
y.ds.mark(this._id, this._length, false)
|
||||
let del = new Delete()
|
||||
del._targetID = this._id
|
||||
del._length = this._length
|
||||
@ -236,6 +237,32 @@ export default class Item {
|
||||
}
|
||||
}
|
||||
|
||||
_gcChildren (y) {}
|
||||
|
||||
_gc (y) {
|
||||
y.ds.mark(this._id, this._length, true)
|
||||
const gc = new GC()
|
||||
gc._id = this._id
|
||||
gc._length = this._length
|
||||
y.os.delete(this._id)
|
||||
let n = y.os.put(gc)
|
||||
const prev = n.prev().val
|
||||
if (prev !== null && prev.constructor === GC && prev._id.user === n.val._id.user && prev._id.clock + prev._length === n.val._id.clock) {
|
||||
// TODO: do merging for all items!
|
||||
prev._length += n.val._length
|
||||
y.os.delete(n.val._id)
|
||||
n = prev
|
||||
}
|
||||
if (n.val) {
|
||||
n = n.val
|
||||
}
|
||||
const next = y.os.findNext(n._id)
|
||||
if (next !== null && next.constructor === GC && next._id.user === n._id.user && next._id.clock === n._id.clock + n._length) {
|
||||
n._length += next._length
|
||||
y.os.delete(n._id)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called right before this Item receives any children.
|
||||
* It can be overwritten to apply pending changes before applying remote changes
|
||||
|
@ -30,6 +30,14 @@ export function getListItemIDByPosition (type, i) {
|
||||
}
|
||||
}
|
||||
|
||||
function gcChildren (y, item) {
|
||||
while (item !== null) {
|
||||
item._delete(y, false, true)
|
||||
item._gc(y)
|
||||
item = item._right
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract Yjs Type class
|
||||
*/
|
||||
@ -184,6 +192,20 @@ export default class Type extends Item {
|
||||
}
|
||||
}
|
||||
|
||||
_gcChildren (y) {
|
||||
gcChildren(y, this._start)
|
||||
this._start = null
|
||||
this._map.forEach(item => {
|
||||
gcChildren(y, item)
|
||||
})
|
||||
this._map = new Map()
|
||||
}
|
||||
|
||||
_gc (y) {
|
||||
this._gcChildren(y)
|
||||
super._gc(y)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Mark this Item as deleted.
|
||||
@ -192,22 +214,25 @@ export default class Type extends Item {
|
||||
* @param {boolean} createDelete Whether to propagate a message that this
|
||||
* Type was deleted.
|
||||
*/
|
||||
_delete (y, createDelete) {
|
||||
super._delete(y, createDelete)
|
||||
_delete (y, createDelete, gcChildren = true) {
|
||||
super._delete(y, createDelete, gcChildren)
|
||||
y._transaction.changedTypes.delete(this)
|
||||
// delete map types
|
||||
for (let value of this._map.values()) {
|
||||
if (value instanceof Item && !value._deleted) {
|
||||
value._delete(y, false)
|
||||
value._delete(y, false, gcChildren)
|
||||
}
|
||||
}
|
||||
// delete array types
|
||||
let t = this._start
|
||||
while (t !== null) {
|
||||
if (!t._deleted) {
|
||||
t._delete(y, false)
|
||||
t._delete(y, false, gcChildren)
|
||||
}
|
||||
t = t._right
|
||||
}
|
||||
if (gcChildren) {
|
||||
this._gcChildren(y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,8 +126,8 @@ export default class YXmlFragment extends YArray {
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_delete (y, createDelete) {
|
||||
super._delete(y, createDelete)
|
||||
_delete (y, createDelete, gcChildren) {
|
||||
super._delete(y, createDelete, gcChildren)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,7 +36,7 @@ export default class YXmlText extends YText {
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_delete (y, createDelete) {
|
||||
super._delete(y, createDelete)
|
||||
_delete (y, createDelete, gcChildren) {
|
||||
super._delete(y, createDelete, gcChildren)
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import ItemJSON from '../Struct/ItemJSON.js'
|
||||
import ItemString from '../Struct/ItemString.js'
|
||||
import ItemFormat from '../Struct/ItemFormat.js'
|
||||
import ItemEmbed from '../Struct/ItemEmbed.js'
|
||||
import GC from '../Struct/GC.js'
|
||||
|
||||
const structs = new Map()
|
||||
const references = new Map()
|
||||
@ -54,3 +55,5 @@ registerStruct(6, YXmlFragment)
|
||||
registerStruct(7, YXmlElement)
|
||||
registerStruct(8, YXmlText)
|
||||
registerStruct(9, YXmlHook)
|
||||
|
||||
registerStruct(12, GC)
|
Loading…
x
Reference in New Issue
Block a user