fix all tests
This commit is contained in:
parent
f94653424a
commit
52abcdd043
@ -1,5 +1,5 @@
|
||||
|
||||
import { createMutex } from '../../lib/mutex.js'
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
|
||||
/**
|
||||
* Abstract class for bindings.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* global MutationObserver, getSelection */
|
||||
|
||||
import { fromRelativePosition } from '../../Util/relativePosition.js'
|
||||
import { fromRelativePosition } from '../../src/Util/relativePosition.js'
|
||||
import Binding from '../Binding.js'
|
||||
import { createAssociation, removeAssociation } from './util.js'
|
||||
import { beforeTransactionSelectionFixer, afterTransactionSelectionFixer, getCurrentRelativeSelection } from './selection.js'
|
||||
@ -121,8 +121,15 @@ export default class DomBinding extends Binding {
|
||||
createAssociation(this, target, type)
|
||||
}
|
||||
|
||||
flushDomChanges () {
|
||||
this._domObserver(this._mutationObserver.takeRecords())
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: currently does not apply filter to existing elements!
|
||||
* NOTE:
|
||||
* * does not apply filter to existing elements!
|
||||
* * only guarantees that changes are filtered locally. Remote sites may see different content.
|
||||
*
|
||||
* @param {DomFilter} filter The filter function to use from now on.
|
||||
*/
|
||||
setFilter (filter) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
|
||||
import YXmlHook from '../../Types/YXml/YXmlHook.js'
|
||||
import YXmlHook from '../../src/Types/YXml/YXmlHook.js'
|
||||
import {
|
||||
iterateUntilUndeleted,
|
||||
removeAssociation,
|
||||
insertNodeHelper } from './util.js'
|
||||
import diff from '../../../lib/simpleDiff.js'
|
||||
import YXmlFragment from '../../Types/YXml/YXmlFragment.js'
|
||||
import diff from '../../lib/simpleDiff.js'
|
||||
import YXmlFragment from '../../src/Types/YXml/YXmlFragment.js'
|
||||
|
||||
/**
|
||||
* 1. Check if any of the nodes was deleted
|
||||
|
@ -47,10 +47,12 @@ export function splitHelper (y, a, b, diff) {
|
||||
o = o._right
|
||||
}
|
||||
y.os.put(b)
|
||||
if (y._transaction.newTypes.has(a)) {
|
||||
y._transaction.newTypes.add(b)
|
||||
} else if (y._transaction.deletedStructs.has(a)) {
|
||||
y._transaction.deletedStructs.add(b)
|
||||
if (y._transaction !== null) {
|
||||
if (y._transaction.newTypes.has(a)) {
|
||||
y._transaction.newTypes.add(b)
|
||||
} else if (y._transaction.deletedStructs.has(a)) {
|
||||
y._transaction.deletedStructs.add(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +119,7 @@ export default class Item {
|
||||
*/
|
||||
_copy () {
|
||||
const C = this.constructor
|
||||
return C()
|
||||
return new C()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,7 +54,7 @@ export const stringifyDeleteSet = (decoder) => {
|
||||
const dsLength = decoding.readUint32(decoder)
|
||||
for (let i = 0; i < dsLength; i++) {
|
||||
str += ' -' + decoding.readVarUint(decoder) + ':\n' // decodes user
|
||||
const dvLength = decoding.readVarUint(decoder)
|
||||
const dvLength = decoding.readUint32(decoder)
|
||||
for (let j = 0; j < dvLength; j++) {
|
||||
str += `clock: ${decoding.readVarUint(decoder)}, length: ${decoding.readVarUint(decoder)}, gc: ${decoding.readUint8(decoder) === 1}\n`
|
||||
}
|
||||
@ -192,8 +192,8 @@ export const readDeleteSet = (decoder, y) => {
|
||||
*/
|
||||
export const stringifyStateSet = decoder => {
|
||||
let s = 'State Set: '
|
||||
readStateSet(decoder).forEach((user, userState) => {
|
||||
s += `(${user}: ${userState}), `
|
||||
readStateSet(decoder).forEach((clock, user) => {
|
||||
s += `(${user}: ${clock}), `
|
||||
})
|
||||
return s
|
||||
}
|
||||
@ -209,7 +209,7 @@ export const writeStateSet = (encoder, y) => {
|
||||
// write as fixed-size number to stay consistent with the other encode functions.
|
||||
// => anytime we write the number of objects that follow, encode as fixed-size number.
|
||||
encoding.writeUint32(encoder, state.size)
|
||||
state.forEach((user, clock) => {
|
||||
state.forEach((clock, user) => {
|
||||
encoding.writeVarUint(encoder, user)
|
||||
encoding.writeVarUint(encoder, clock)
|
||||
})
|
||||
@ -317,7 +317,9 @@ export const writeStructs = (encoder, y, ss) => {
|
||||
const overlappingLeft = y.os.findPrev(minBound)
|
||||
const rightID = overlappingLeft === null ? null : overlappingLeft._id
|
||||
if (rightID !== null && rightID.user === user && rightID.clock + overlappingLeft._length > clock) {
|
||||
const struct = overlappingLeft._clonePartial(clock - rightID.clock)
|
||||
// TODO: only write partial content (only missing content)
|
||||
// const struct = overlappingLeft._clonePartial(clock - rightID.clock)
|
||||
const struct = overlappingLeft
|
||||
struct._toBinary(encoder)
|
||||
len++
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ function testEncoding (t, write, read, val) {
|
||||
t.compare(val, result, 'Compare results')
|
||||
}
|
||||
|
||||
const writeVarUint = (encoder, val) => encoder.writeVarUint(val)
|
||||
const readVarUint = decoder => decoder.readVarUint()
|
||||
const writeVarUint = (encoder, val) => encoding.writeVarUint(encoder, val)
|
||||
const readVarUint = decoder => decoding.readVarUint(decoder)
|
||||
|
||||
test('varUint 1 byte', async function varUint1 (t) {
|
||||
testEncoding(t, writeVarUint, readVarUint, 42)
|
||||
@ -46,8 +46,8 @@ test('varUint random user id', async function varUintRandomUserId (t) {
|
||||
testEncoding(t, writeVarUint, readVarUint, generateRandomUint32())
|
||||
})
|
||||
|
||||
const writeVarString = (encoder, val) => encoder.writeVarString(val)
|
||||
const readVarString = decoder => decoder.readVarString()
|
||||
const writeVarString = (encoder, val) => encoding.writeVarString(encoder, val)
|
||||
const readVarString = decoder => decoding.readVarString(decoder)
|
||||
|
||||
test('varString', async function varString (t) {
|
||||
testEncoding(t, writeVarString, readVarString, 'hello')
|
||||
|
@ -65,6 +65,7 @@ test('insertions work in late sync', async function array4 (t) {
|
||||
array2.insert(1, ['user2'])
|
||||
await users[1].connect()
|
||||
await users[2].connect()
|
||||
testConnector.flushAllMessages()
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
@ -215,7 +216,7 @@ function getUniqueNumber () {
|
||||
|
||||
var arrayTransactions = [
|
||||
function insert (t, user, prng) {
|
||||
const yarray = user.get('array', Y.Array)
|
||||
const yarray = user.define('array', Y.Array)
|
||||
var uniqueNumber = getUniqueNumber()
|
||||
var content = []
|
||||
var len = random.int32(prng, 1, 4)
|
||||
@ -226,14 +227,14 @@ var arrayTransactions = [
|
||||
yarray.insert(pos, content)
|
||||
},
|
||||
function insertTypeArray (t, user, prng) {
|
||||
const yarray = user.get('array', Y.Array)
|
||||
const yarray = user.define('array', Y.Array)
|
||||
var pos = random.int32(prng, 0, yarray.length)
|
||||
yarray.insert(pos, [Y.Array])
|
||||
var array2 = yarray.get(pos)
|
||||
array2.insert(0, [1, 2, 3, 4])
|
||||
},
|
||||
function insertTypeMap (t, user, prng) {
|
||||
const yarray = user.get('array', Y.Array)
|
||||
const yarray = user.define('array', Y.Array)
|
||||
var pos = random.int32(prng, 0, yarray.length)
|
||||
yarray.insert(pos, [Y.Map])
|
||||
var map = yarray.get(pos)
|
||||
@ -242,7 +243,7 @@ var arrayTransactions = [
|
||||
map.set('someprop', 44)
|
||||
},
|
||||
function _delete (t, user, prng) {
|
||||
const yarray = user.get('array', Y.Array)
|
||||
const yarray = user.define('array', Y.Array)
|
||||
var length = yarray.length
|
||||
if (length > 0) {
|
||||
var somePos = random.int32(prng, 0, length - 1)
|
||||
|
@ -50,7 +50,7 @@ test('Basic get&set of Map property (converge via sync)', async function map1 (t
|
||||
testConnector.flushAllMessages()
|
||||
|
||||
for (let user of users) {
|
||||
var u = user.get('map', Y.Map)
|
||||
var u = user.define('map', Y.Map)
|
||||
t.compare(u.get('stuff'), 'stuffy')
|
||||
t.assert(u.get('undefined') === undefined, 'undefined')
|
||||
t.compare(u.get('null'), null, 'null')
|
||||
@ -94,7 +94,7 @@ test('Basic get&set of Map property (converge via update)', async function map5
|
||||
testConnector.flushAllMessages()
|
||||
|
||||
for (let user of users) {
|
||||
var u = user.get('map', Y.Map)
|
||||
var u = user.define('map', Y.Map)
|
||||
t.compare(u.get('stuff'), 'stuffy')
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
@ -108,7 +108,7 @@ test('Basic get&set of Map property (handle conflict)', async function map6 (t)
|
||||
testConnector.flushAllMessages()
|
||||
|
||||
for (let user of users) {
|
||||
var u = user.get('map', Y.Map)
|
||||
var u = user.define('map', Y.Map)
|
||||
t.compare(u.get('stuff'), 'c0')
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
@ -121,7 +121,7 @@ test('Basic get&set&delete of Map property (handle conflict)', async function ma
|
||||
map1.set('stuff', 'c1')
|
||||
testConnector.flushAllMessages()
|
||||
for (let user of users) {
|
||||
var u = user.get('map', Y.Map)
|
||||
var u = user.define('map', Y.Map)
|
||||
t.assert(u.get('stuff') === undefined)
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
@ -135,7 +135,7 @@ test('Basic get&set of Map property (handle three conflicts)', async function ma
|
||||
map2.set('stuff', 'c3')
|
||||
testConnector.flushAllMessages()
|
||||
for (let user of users) {
|
||||
var u = user.get('map', Y.Map)
|
||||
var u = user.define('map', Y.Map)
|
||||
t.compare(u.get('stuff'), 'c0')
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
@ -155,7 +155,7 @@ test('Basic get&set&delete of Map property (handle three conflicts)', async func
|
||||
map3.set('stuff', 'c3')
|
||||
testConnector.flushAllMessages()
|
||||
for (let user of users) {
|
||||
var u = user.get('map', Y.Map)
|
||||
var u = user.define('map', Y.Map)
|
||||
t.assert(u.get('stuff') === undefined)
|
||||
}
|
||||
await compareUsers(t, users)
|
||||
@ -303,12 +303,12 @@ var mapTransactions = [
|
||||
function set (t, user, prng) {
|
||||
let key = random.oneOf(prng, ['one', 'two'])
|
||||
var value = random.utf16String(prng)
|
||||
user.get('map', Y.Map).set(key, value)
|
||||
user.define('map', Y.Map).set(key, value)
|
||||
},
|
||||
function setType (t, user, prng) {
|
||||
let key = random.oneOf(prng, ['one', 'two'])
|
||||
var type = random.oneOf(prng, [new Y.Array(), new Y.Map()])
|
||||
user.get('map', Y.Map).set(key, type)
|
||||
user.define('map', Y.Map).set(key, type)
|
||||
if (type instanceof Y.Array) {
|
||||
type.insert(0, [1, 2, 3, 4])
|
||||
} else {
|
||||
@ -317,7 +317,7 @@ var mapTransactions = [
|
||||
},
|
||||
function _delete (t, user, prng) {
|
||||
let key = random.oneOf(prng, ['one', 'two'])
|
||||
user.get('map', Y.Map).delete(key)
|
||||
user.define('map', Y.Map).delete(key)
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -61,20 +61,24 @@ test('attribute modifications (y -> dom)', async function xml2 (t) {
|
||||
})
|
||||
|
||||
test('attribute modifications (dom -> y)', async function xml3 (t) {
|
||||
var { users, xml0, dom0 } = await initArrays(t, { users: 3 })
|
||||
var { users, xml0, dom0, domBinding0 } = await initArrays(t, { users: 3 })
|
||||
dom0.setAttribute('height', '100px')
|
||||
domBinding0.flushDomChanges()
|
||||
t.assert(xml0.getAttribute('height') === '100px', 'setAttribute')
|
||||
dom0.removeAttribute('height')
|
||||
domBinding0.flushDomChanges()
|
||||
t.assert(xml0.getAttribute('height') == null, 'removeAttribute')
|
||||
dom0.setAttribute('class', 'stuffy stuff')
|
||||
domBinding0.flushDomChanges()
|
||||
t.assert(xml0.getAttribute('class') === 'stuffy stuff', 'set class attribute')
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
|
||||
test('element insert (dom -> y)', async function xml4 (t) {
|
||||
var { users, xml0, dom0 } = await initArrays(t, { users: 3 })
|
||||
var { users, xml0, dom0, domBinding0 } = await initArrays(t, { users: 3 })
|
||||
dom0.insertBefore(document.createTextNode('some text'), null)
|
||||
dom0.insertBefore(document.createElement('p'), null)
|
||||
domBinding0.flushDomChanges()
|
||||
t.assert(xml0.get(0).toString() === 'some text', 'Retrieve Text Node')
|
||||
t.assert(xml0.get(1).nodeName === 'P', 'Retrieve Element node')
|
||||
await compareUsers(t, users)
|
||||
@ -90,10 +94,12 @@ test('element insert (y -> dom)', async function xml5 (t) {
|
||||
})
|
||||
|
||||
test('y on insert, then delete (dom -> y)', async function xml6 (t) {
|
||||
var { users, xml0, dom0 } = await initArrays(t, { users: 3 })
|
||||
var { users, xml0, dom0, domBinding0 } = await initArrays(t, { users: 3 })
|
||||
dom0.insertBefore(document.createElement('p'), null)
|
||||
domBinding0.flushDomChanges()
|
||||
t.assert(xml0.length === 1, 'one node present')
|
||||
dom0.childNodes[0].remove()
|
||||
domBinding0.flushDomChanges()
|
||||
t.assert(xml0.length === 0, 'no node present after delete')
|
||||
await compareUsers(t, users)
|
||||
})
|
||||
@ -164,11 +170,13 @@ test('Receive a bunch of elements (with disconnect)', async function xml12 (t) {
|
||||
})
|
||||
|
||||
test('move element to a different position', async function xml13 (t) {
|
||||
var { testConnector, users, dom0, dom1 } = await initArrays(t, { users: 3 })
|
||||
var { testConnector, users, dom0, dom1, domBinding0, domBinding1 } = await initArrays(t, { users: 3 })
|
||||
dom0.append(document.createElement('div'))
|
||||
dom0.append(document.createElement('h1'))
|
||||
domBinding0.flushDomChanges()
|
||||
testConnector.flushAllMessages()
|
||||
dom1.insertBefore(dom1.childNodes[0], null)
|
||||
domBinding1.flushDomChanges()
|
||||
t.assert(dom1.childNodes[0].nodeName === 'H1', 'div was deleted (user 0)')
|
||||
t.assert(dom1.childNodes[1].nodeName === 'DIV', 'div was moved to the correct position (user 0)')
|
||||
t.assert(dom1.childNodes[0].nodeName === 'H1', 'div was deleted (user 1)')
|
||||
@ -189,6 +197,7 @@ test('filter node', async function xml14 (t) {
|
||||
domBinding1.setFilter(domFilter)
|
||||
dom0.append(document.createElement('div'))
|
||||
dom0.append(document.createElement('h1'))
|
||||
domBinding0.flushDomChanges()
|
||||
testConnector.flushAllMessages()
|
||||
t.assert(dom1.childNodes.length === 1, 'Only one node was not transmitted')
|
||||
t.assert(dom1.childNodes[0].nodeName === 'DIV', 'div node was transmitted')
|
||||
@ -206,6 +215,7 @@ test('filter attribute', async function xml15 (t) {
|
||||
dom0.setAttribute('hidden', 'true')
|
||||
dom0.setAttribute('style', 'height: 30px')
|
||||
dom0.setAttribute('data-me', '77')
|
||||
domBinding0.flushDomChanges()
|
||||
testConnector.flushAllMessages()
|
||||
t.assert(dom0.getAttribute('hidden') === 'true', 'User 0 still has the attribute')
|
||||
t.assert(dom1.getAttribute('hidden') == null, 'User 1 did not receive update')
|
||||
@ -215,7 +225,7 @@ test('filter attribute', async function xml15 (t) {
|
||||
})
|
||||
|
||||
test('deep element insert', async function xml16 (t) {
|
||||
var { testConnector, users, dom0, dom1 } = await initArrays(t, { users: 3 })
|
||||
var { testConnector, users, dom0, dom1, domBinding0 } = await initArrays(t, { users: 3 })
|
||||
let deepElement = document.createElement('p')
|
||||
let boldElement = document.createElement('b')
|
||||
let attrElement = document.createElement('img')
|
||||
@ -225,6 +235,7 @@ test('deep element insert', async function xml16 (t) {
|
||||
deepElement.append(attrElement)
|
||||
dom0.append(deepElement)
|
||||
let str0 = dom0.outerHTML
|
||||
domBinding0.flushDomChanges()
|
||||
testConnector.flushAllMessages()
|
||||
let str1 = dom1.outerHTML
|
||||
t.compare(str0, str1, 'Dom string representation matches')
|
||||
@ -253,8 +264,8 @@ test('treeWalker', async function xml17 (t) {
|
||||
* Incoming changes that contain malicious attributes should be deleted.
|
||||
*/
|
||||
test('Filtering remote changes', async function xmlFilteringRemote (t) {
|
||||
var { testConnector, users, xml0, xml1, domBinding0 } = await initArrays(t, { users: 3 })
|
||||
domBinding0.setFilter(function (nodeName, attributes) {
|
||||
var { testConnector, users, xml0, xml1, domBinding0, domBinding1 } = await initArrays(t, { users: 3 })
|
||||
const filter = (nodeName, attributes) => {
|
||||
attributes.delete('malicious')
|
||||
if (nodeName === 'HIDEME') {
|
||||
return null
|
||||
@ -263,7 +274,9 @@ test('Filtering remote changes', async function xmlFilteringRemote (t) {
|
||||
} else {
|
||||
return attributes
|
||||
}
|
||||
})
|
||||
}
|
||||
domBinding0.setFilter(filter)
|
||||
domBinding1.setFilter(filter)
|
||||
let paragraph = new Y.XmlElement('p')
|
||||
let hideMe = new Y.XmlElement('hideMe')
|
||||
let span = new Y.XmlElement('span')
|
||||
@ -275,13 +288,16 @@ test('Filtering remote changes', async function xmlFilteringRemote (t) {
|
||||
let tag2 = new Y.XmlElement('tag')
|
||||
tag2.setAttribute('isHidden', 'true')
|
||||
paragraph.insert(0, [tag2])
|
||||
domBinding0.flushDomChanges()
|
||||
testConnector.flushAllMessages()
|
||||
// check dom
|
||||
domBinding0.typeToDom.get(paragraph).setAttribute('malicious', 'true')
|
||||
domBinding0.typeToDom.get(span).setAttribute('malicious', 'true')
|
||||
domBinding0.flushDomChanges()
|
||||
// check incoming attributes
|
||||
xml1.get(0).get(0).setAttribute('malicious', 'true')
|
||||
xml1.insert(0, [new Y.XmlElement('hideMe')])
|
||||
domBinding0.flushDomChanges()
|
||||
testConnector.flushAllMessages()
|
||||
|
||||
await compareUsers(t, users)
|
||||
@ -292,30 +308,36 @@ var xmlTransactions = [
|
||||
function attributeChange (t, user, prng) {
|
||||
// random.word generates non-empty words. prepend something
|
||||
user.dom.setAttribute('_' + random.word(prng), random.word(prng))
|
||||
user.domBinding.flushDomChanges()
|
||||
},
|
||||
function attributeChangeHidden (t, user, prng) {
|
||||
user.dom.setAttribute('hidden', random.word(prng))
|
||||
user.domBinding.flushDomChanges()
|
||||
},
|
||||
function insertText (t, user, prng) {
|
||||
let dom = user.dom
|
||||
var succ = dom.children.length > 0 ? random.oneOf(prng, dom.children) : null
|
||||
dom.insertBefore(document.createTextNode(random.word(prng)), succ)
|
||||
user.domBinding.flushDomChanges()
|
||||
},
|
||||
function insertHiddenDom (t, user, prng) {
|
||||
let dom = user.dom
|
||||
var succ = dom.children.length > 0 ? random.oneOf(prng, dom.children) : null
|
||||
dom.insertBefore(document.createElement('hidden'), succ)
|
||||
user.domBinding.flushDomChanges()
|
||||
},
|
||||
function insertDom (t, user, prng) {
|
||||
let dom = user.dom
|
||||
var succ = dom.children.length > 0 ? random.oneOf(prng, dom.children) : null
|
||||
dom.insertBefore(document.createElement('my-' + random.word(prng)), succ)
|
||||
user.domBinding.flushDomChanges()
|
||||
},
|
||||
function deleteChild (t, user, prng) {
|
||||
let dom = user.dom
|
||||
if (dom.childNodes.length > 0) {
|
||||
var d = random.oneOf(prng, dom.childNodes)
|
||||
d.remove()
|
||||
user.domBinding.flushDomChanges()
|
||||
}
|
||||
},
|
||||
function insertTextSecondLayer (t, user, prng) {
|
||||
@ -324,6 +346,7 @@ var xmlTransactions = [
|
||||
let dom2 = random.oneOf(prng, dom.children)
|
||||
let succ = dom2.childNodes.length > 0 ? random.oneOf(prng, dom2.childNodes) : null
|
||||
dom2.insertBefore(document.createTextNode(random.word(prng)), succ)
|
||||
user.domBinding.flushDomChanges()
|
||||
}
|
||||
},
|
||||
function insertDomSecondLayer (t, user, prng) {
|
||||
@ -332,6 +355,7 @@ var xmlTransactions = [
|
||||
let dom2 = random.oneOf(prng, dom.children)
|
||||
let succ = dom2.childNodes.length > 0 ? random.oneOf(prng, dom2.childNodes) : null
|
||||
dom2.insertBefore(document.createElement('my-' + random.word(prng)), succ)
|
||||
user.domBinding.flushDomChanges()
|
||||
}
|
||||
},
|
||||
function deleteChildSecondLayer (t, user, prng) {
|
||||
@ -342,6 +366,7 @@ var xmlTransactions = [
|
||||
let d = random.oneOf(prng, dom2.childNodes)
|
||||
d.remove()
|
||||
}
|
||||
user.domBinding.flushDomChanges()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -6,10 +6,12 @@ import { defragmentItemContent } from '../src/Util/defragmentItemContent.js'
|
||||
import Quill from 'quill'
|
||||
import GC from '../src/Struct/GC.js'
|
||||
import * as random from '../lib/random/random.js'
|
||||
import * as message from '../src/message.js'
|
||||
import * as syncProtocol from '../src/protocols/syncProtocol.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
import QuillBinding from '../bindings/QuillBinding/QuillBinding.js'
|
||||
import DomBinding from '../bindings/DomBinding/DomBinding.js'
|
||||
|
||||
export * from '../src/index.js'
|
||||
|
||||
@ -21,7 +23,7 @@ const afterTransaction = (y, transaction) => {
|
||||
y.mMux(() => {
|
||||
if (transaction.encodedStructsLen > 0) {
|
||||
const encoder = encoding.createEncoder()
|
||||
message.writeUpdate(encoder, transaction.encodedStructsLen, transaction.encodedStructs)
|
||||
syncProtocol.writeUpdate(encoder, transaction.encodedStructsLen, transaction.encodedStructs)
|
||||
broadcastMessage(y, encoding.toBuffer(encoder))
|
||||
}
|
||||
})
|
||||
@ -31,8 +33,9 @@ export class TestYInstance extends Y.Y {
|
||||
/**
|
||||
* @param {TestConnector} testConnector
|
||||
*/
|
||||
constructor (testConnector) {
|
||||
constructor (testConnector, clientID) {
|
||||
super()
|
||||
this.userID = clientID // overwriting clientID
|
||||
/**
|
||||
* @type {TestConnector}
|
||||
*/
|
||||
@ -64,17 +67,19 @@ export class TestYInstance extends Y.Y {
|
||||
*/
|
||||
connect () {
|
||||
if (!this.tc.onlineConns.has(this)) {
|
||||
this.tc.onlineConns.add(this)
|
||||
const encoder = encoding.createEncoder()
|
||||
message.writeSyncStep1(encoder, this)
|
||||
syncProtocol.writeSyncStep1(encoder, this)
|
||||
// publish SyncStep1
|
||||
broadcastMessage(this, encoding.toBuffer(encoder))
|
||||
this.tc.onlineConns.forEach(remoteYInstance => {
|
||||
// remote instance sends instance to this instance
|
||||
const encoder = encoding.createEncoder()
|
||||
message.writeSyncStep1(encoder, remoteYInstance)
|
||||
this._receive(encoding.toBuffer(encoder), remoteYInstance)
|
||||
if (remoteYInstance !== this) {
|
||||
// remote instance sends instance to this instance
|
||||
const encoder = encoding.createEncoder()
|
||||
syncProtocol.writeSyncStep1(encoder, remoteYInstance)
|
||||
this._receive(encoding.toBuffer(encoder), remoteYInstance)
|
||||
}
|
||||
})
|
||||
this.tc.onlineConns.add(this)
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -117,9 +122,10 @@ export class TestConnector {
|
||||
}
|
||||
/**
|
||||
* Create a new Y instance and add it to the list of connections
|
||||
* @param {number} clientID
|
||||
*/
|
||||
createY () {
|
||||
return new TestYInstance(this)
|
||||
createY (clientID) {
|
||||
return new TestYInstance(this, clientID)
|
||||
}
|
||||
/**
|
||||
* Choose random connection and flush a random message from a random sender.
|
||||
@ -139,8 +145,9 @@ export class TestConnector {
|
||||
}
|
||||
const encoder = encoding.createEncoder()
|
||||
receiver.mMux(() => {
|
||||
console.log('receive (' + sender.userID + '->' + receiver.userID + '):\n', syncProtocol.stringifySyncMessage(decoding.createDecoder(m), receiver))
|
||||
// do not publish data created when this function is executed (could be ss2 or update message)
|
||||
message.readMessage(decoding.createDecoder(m), encoder, receiver)
|
||||
syncProtocol.readSyncMessage(decoding.createDecoder(m), encoder, receiver)
|
||||
})
|
||||
if (encoding.length(encoder) > 0) {
|
||||
// send reply message
|
||||
@ -202,12 +209,15 @@ export class TestConnector {
|
||||
* @param {TestYInstance} y // publish message created by `y` to all other online clients
|
||||
* @param {ArrayBuffer} m
|
||||
*/
|
||||
const broadcastMessage = (y, m) =>
|
||||
y.tc.onlineConns.forEach(remoteYInstance => {
|
||||
if (remoteYInstance !== y) {
|
||||
remoteYInstance._receive(m, y)
|
||||
}
|
||||
})
|
||||
const broadcastMessage = (y, m) => {
|
||||
if (y.tc.onlineConns.has(y)) {
|
||||
y.tc.onlineConns.forEach(remoteYInstance => {
|
||||
if (remoteYInstance !== y) {
|
||||
remoteYInstance._receive(m, y)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert DS to a proper DeleteSet of Map.
|
||||
@ -295,7 +305,7 @@ export function compareUsers (t, users) {
|
||||
data.os = ops
|
||||
data.ds = getDeleteSet(u)
|
||||
const ss = {}
|
||||
u.ss.state.forEach((user, clock) => {
|
||||
u.ss.state.forEach((clock, user) => {
|
||||
ss[user] = clock
|
||||
})
|
||||
data.ss = ss
|
||||
@ -347,20 +357,20 @@ export function initArrays (t, opts) {
|
||||
const testConnector = new TestConnector(prng)
|
||||
result.testConnector = testConnector
|
||||
for (let i = 0; i < opts.users; i++) {
|
||||
let y = testConnector.createY()
|
||||
let y = testConnector.createY(i)
|
||||
result.users.push(y)
|
||||
result['array' + i] = y.define('array', Y.Array)
|
||||
result['map' + i] = y.define('map', Y.Map)
|
||||
const yxml = y.define('xml', Y.XmlElement)
|
||||
result['xml' + i] = yxml
|
||||
const dom = document.createElement('my-dom')
|
||||
const domBinding = new Y.DomBinding(yxml, dom, { filter })
|
||||
const domBinding = new DomBinding(yxml, dom, { filter })
|
||||
result['domBinding' + i] = domBinding
|
||||
result['dom' + i] = dom
|
||||
const textType = y.define('text', Y.Text)
|
||||
result['text' + i] = textType
|
||||
const quill = new Quill(document.createElement('div'))
|
||||
result['quillBinding' + i] = new Y.QuillBinding(textType, quill)
|
||||
result['quillBinding' + i] = new QuillBinding(textType, quill)
|
||||
result['quill' + i] = quill
|
||||
y.quill = quill // put quill on the y object (so we can use it later)
|
||||
y.dom = dom
|
||||
|
Loading…
x
Reference in New Issue
Block a user