Delete all children of ItemType when it is deleted
This commit is contained in:
parent
1d0f9faa91
commit
21d86cd2be
@ -425,6 +425,7 @@ export class AbstractItem extends AbstractStruct {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
gc (transaction, store) {
|
gc (transaction, store) {
|
||||||
|
this.delete(transaction)
|
||||||
let r
|
let r
|
||||||
if (this.parent._item !== null && this.parent._item.deleted) {
|
if (this.parent._item !== null && this.parent._item.deleted) {
|
||||||
r = new GC(this.id, this.length)
|
r = new GC(this.id, this.length)
|
||||||
|
@ -100,9 +100,21 @@ export class ItemType extends AbstractItem {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
delete (transaction) {
|
delete (transaction) {
|
||||||
super.delete(transaction)
|
if (!this.deleted) {
|
||||||
transaction.changed.delete(this.type)
|
super.delete(transaction)
|
||||||
transaction.changedParentTypes.delete(this.type)
|
let item = this.type._start
|
||||||
|
while (item !== null) {
|
||||||
|
if (!item.deleted) {
|
||||||
|
item.delete(transaction)
|
||||||
|
}
|
||||||
|
item = item.right
|
||||||
|
}
|
||||||
|
this.type._map.forEach(item => {
|
||||||
|
item.delete(transaction)
|
||||||
|
})
|
||||||
|
transaction.changed.delete(this.type)
|
||||||
|
transaction.changedParentTypes.delete(this.type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -454,13 +454,10 @@ export const typeArrayDelete = (transaction, parent, index, length) => {
|
|||||||
if (length === 0) { return }
|
if (length === 0) { return }
|
||||||
let n = parent._start
|
let n = parent._start
|
||||||
// compute the first item to be deleted
|
// compute the first item to be deleted
|
||||||
for (; n !== null; n = n.right) {
|
for (; n !== null && index > 0; n = n.right) {
|
||||||
if (!n.deleted && n.countable) {
|
if (!n.deleted && n.countable) {
|
||||||
if (index <= n.length) {
|
if (index < n.length) {
|
||||||
if (index < n.length && index > 0) {
|
getItemCleanStart(transaction, transaction.y.store, createID(n.id.client, n.id.clock + index))
|
||||||
n = getItemCleanStart(transaction, transaction.y.store, createID(n.id.client, n.id.clock + index))
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
index -= n.length
|
index -= n.length
|
||||||
}
|
}
|
||||||
|
@ -165,9 +165,9 @@ export const transact = (y, f) => {
|
|||||||
// transaction cleanup
|
// transaction cleanup
|
||||||
const store = transaction.y.store
|
const store = transaction.y.store
|
||||||
const ds = transaction.deleteSet
|
const ds = transaction.deleteSet
|
||||||
// replace deleted items with ItemDeleted / GC
|
|
||||||
sortAndMergeDeleteSet(ds)
|
sortAndMergeDeleteSet(ds)
|
||||||
y.emit('afterTransaction', [transaction, y])
|
y.emit('afterTransaction', [transaction, y])
|
||||||
|
// replace deleted items with ItemDeleted / GC
|
||||||
for (const [client, deleteItems] of ds.clients) {
|
for (const [client, deleteItems] of ds.clients) {
|
||||||
/**
|
/**
|
||||||
* @type {Array<AbstractStruct>}
|
* @type {Array<AbstractStruct>}
|
||||||
|
@ -270,8 +270,5 @@ export const createAbsolutePositionFromCursor = (cursor, y) => {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const compareCursors = (a, b) => a === b || (
|
export const compareCursors = (a, b) => a === b || (
|
||||||
a !== null && b !== null && a.tname === b.tname && (
|
a !== null && b !== null && a.tname === b.tname && compareIDs(a.item, b.item) && compareIDs(a.type, b.type)
|
||||||
(a.item !== null && b.item !== null && compareIDs(a.item, b.item)) ||
|
|
||||||
(a.type !== null && b.type !== null && compareIDs(a.type, b.type))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
@ -230,11 +230,13 @@ export class TestConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @template T
|
||||||
* @param {t.TestCase} tc
|
* @param {t.TestCase} tc
|
||||||
* @param {{users?:number}} conf
|
* @param {{users?:number}} conf
|
||||||
* @return {{testConnector:TestConnector,users:Array<TestYInstance>,array0:Y.Array<any>,array1:Y.Array<any>,array2:Y.Array<any>,map0:Y.Map<any>,map1:Y.Map<any>,map2:Y.Map<any>,map3:Y.Map<any>,text0:Y.Text,text1:Y.Text,text2:Y.Text,xml0:Y.XmlElement,xml1:Y.XmlElement,xml2:Y.XmlElement}}
|
* @param {InitTestObjectCallback<T>} initTestObject
|
||||||
|
* @return {{testObjects:Array<any>,testConnector:TestConnector,users:Array<TestYInstance>,array0:Y.Array<any>,array1:Y.Array<any>,array2:Y.Array<any>,map0:Y.Map<any>,map1:Y.Map<any>,map2:Y.Map<any>,map3:Y.Map<any>,text0:Y.Text,text1:Y.Text,text2:Y.Text,xml0:Y.XmlElement,xml1:Y.XmlElement,xml2:Y.XmlElement}}
|
||||||
*/
|
*/
|
||||||
export const init = (tc, { users = 5 } = {}) => {
|
export const init = (tc, { users = 5 } = {}, initTestObject) => {
|
||||||
/**
|
/**
|
||||||
* @type {Object<string,any>}
|
* @type {Object<string,any>}
|
||||||
*/
|
*/
|
||||||
@ -254,6 +256,7 @@ export const init = (tc, { users = 5 } = {}) => {
|
|||||||
result['text' + i] = y.get('text', Y.Text)
|
result['text' + i] = y.get('text', Y.Text)
|
||||||
}
|
}
|
||||||
testConnector.syncAll()
|
testConnector.syncAll()
|
||||||
|
result.testObjects = result.users.map(initTestObject)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -365,15 +368,24 @@ export const compareDS = (ds1, ds2) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {t.TestCase} tc
|
* @template T
|
||||||
* @param {Array<function(TestYInstance,prng.PRNG):void>} mods
|
* @callback InitTestObjectCallback
|
||||||
* @param {number} iterations
|
* @param {TestYInstance} y
|
||||||
|
* @return {T}
|
||||||
*/
|
*/
|
||||||
export const applyRandomTests = (tc, mods, iterations) => {
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
* @param {Array<function(TestYInstance,prng.PRNG,T):void>} mods
|
||||||
|
* @param {number} iterations
|
||||||
|
* @param {InitTestObjectCallback<T>} [initTestObject]
|
||||||
|
*/
|
||||||
|
export const applyRandomTests = (tc, mods, iterations, initTestObject) => {
|
||||||
const gen = tc.prng
|
const gen = tc.prng
|
||||||
const result = init(tc, { users: 5 })
|
const result = init(tc, { users: 5 }, initTestObject || (() => null))
|
||||||
const { testConnector, users } = result
|
const { testConnector, users } = result
|
||||||
for (var i = 0; i < iterations; i++) {
|
for (let i = 0; i < iterations; i++) {
|
||||||
if (prng.int31(gen, 0, 100) <= 2) {
|
if (prng.int31(gen, 0, 100) <= 2) {
|
||||||
// 2% chance to disconnect/reconnect a random user
|
// 2% chance to disconnect/reconnect a random user
|
||||||
if (prng.bool(gen)) {
|
if (prng.bool(gen)) {
|
||||||
@ -388,9 +400,9 @@ export const applyRandomTests = (tc, mods, iterations) => {
|
|||||||
// 50% chance to flush a random message
|
// 50% chance to flush a random message
|
||||||
testConnector.flushRandomMessage()
|
testConnector.flushRandomMessage()
|
||||||
}
|
}
|
||||||
let user = prng.oneOf(gen, users)
|
const user = prng.int31(gen, 0, users.length - 1)
|
||||||
var test = prng.oneOf(gen, mods)
|
const test = prng.oneOf(gen, mods)
|
||||||
test(user, gen)
|
test(users[user], gen, result.testObjects[user])
|
||||||
}
|
}
|
||||||
compare(users)
|
compare(users)
|
||||||
return result
|
return result
|
||||||
|
Loading…
x
Reference in New Issue
Block a user