fix compiling issues

This commit is contained in:
Kevin Jahns 2017-10-14 23:03:24 +02:00
parent 82015d5a37
commit 0e426f8928
36 changed files with 192 additions and 309 deletions

View File

@ -5,6 +5,8 @@
[include] [include]
./src/ ./src/
./tests-lib/
./test/
[libs] [libs]
./declarations/ ./declarations/

View File

@ -64,7 +64,6 @@
"tag-dist-files": "^0.1.6" "tag-dist-files": "^0.1.6"
}, },
"dependencies": { "dependencies": {
"debug": "^2.6.8", "debug": "^2.6.8"
"utf-8": "^1.0.0"
} }
} }

View File

@ -5,7 +5,7 @@ import commonjs from 'rollup-plugin-commonjs'
var pkg = require('./package.json') var pkg = require('./package.json')
export default { export default {
entry: 'src/y.js', entry: 'src/Y.js',
moduleName: 'Y', moduleName: 'Y',
format: 'umd', format: 'umd',
plugins: [ plugins: [

View File

@ -3,7 +3,7 @@ import commonjs from 'rollup-plugin-commonjs'
var pkg = require('./package.json') var pkg = require('./package.json')
export default { export default {
entry: 'src/y.js', entry: 'src/Y.js',
moduleName: 'Y', moduleName: 'Y',
format: 'umd', format: 'umd',
plugins: [ plugins: [

View File

@ -1,4 +1,4 @@
import utf8 from 'utf-8' import '../../node_modules/utf8/utf8.js'
export default class BinaryDecoder { export default class BinaryDecoder {
constructor (buffer) { constructor (buffer) {
@ -11,25 +11,36 @@ export default class BinaryDecoder {
} }
this.pos = 0 this.pos = 0
} }
/**
* Clone this decoder instance
* Optionally set a new position parameter
*/
clone (newPos = this.pos) { clone (newPos = this.pos) {
let decoder = new BinaryDecoder(this.uint8arr) let decoder = new BinaryDecoder(this.uint8arr)
decoder.pos = newPos decoder.pos = newPos
return decoder return decoder
} }
/**
* Number of bytes
*/
get length () { get length () {
return this.uint8arr.length return this.uint8arr.length
} }
/**
* Skip one byte, jump to the next position
*/
skip8 () { skip8 () {
this.pos++ this.pos++
} }
/**
* Read one byte as unsigned integer
*/
readUint8 () { readUint8 () {
return this.uint8arr[this.pos++] return this.uint8arr[this.pos++]
} }
/**
* Read 4 bytes as unsigned integer
*/
readUint32 () { readUint32 () {
let uint = let uint =
this.uint8arr[this.pos] + this.uint8arr[this.pos] +
@ -39,11 +50,20 @@ export default class BinaryDecoder {
this.pos += 4 this.pos += 4
return uint return uint
} }
/**
* Look ahead without incrementing position
* to the next byte and read it as unsigned integer
*/
peekUint8 () { peekUint8 () {
return this.uint8arr[this.pos] return this.uint8arr[this.pos]
} }
/**
* Read unsigned integer (32bit) with variable length
* 1/8th of the storage is used as encoding overhead
* - numbers < 2^7 is stored in one byte
* - numbers < 2^14 is stored in two bytes
* ..
*/
readVarUint () { readVarUint () {
let num = 0 let num = 0
let len = 0 let len = 0
@ -59,7 +79,10 @@ export default class BinaryDecoder {
} }
} }
} }
/**
* Read string of variable length
* - varUint is used to store the length of the string
*/
readVarString () { readVarString () {
let len = this.readVarUint() let len = this.readVarUint()
let bytes = new Array(len) let bytes = new Array(len)
@ -68,20 +91,26 @@ export default class BinaryDecoder {
} }
return utf8.getStringFromBytes(bytes) return utf8.getStringFromBytes(bytes)
} }
/**
* Look ahead and read varString without incrementing position
*/
peekVarString () { peekVarString () {
let pos = this.pos let pos = this.pos
let s = this.readVarString() let s = this.readVarString()
this.pos = pos this.pos = pos
return s return s
} }
/**
readOpID () { * Read ID
* - If first varUint read is 0xFFFFFF a RootID is returned
* - Otherwise an ID is returned
*/
readID () {
let user = this.readVarUint() let user = this.readVarUint()
if (user !== 0xFFFFFF) { if (user === 0xFFFFFF) {
return [user, this.readVarUint()] // read property name and type id
} else { return new RootID(this.readVarString(), this.readVarUint())
return [user, this.readVarString()]
} }
return new ID(user, this.readVarUint())
} }
} }

View File

@ -1,4 +1,4 @@
import utf8 from 'utf-8' import '../../node_modules/utf8/utf8.js'
const bits7 = 0b1111111 const bits7 = 0b1111111
const bits8 = 0b11111111 const bits8 = 0b11111111

View File

@ -1,10 +1,11 @@
import { BinaryEncoder, BinaryDecoder } from './Encoding.js' import BinaryEncoder from './Binary/Encoder.js'
import BinaryDecoder from './Binary/Decoder.js'
import { sendSyncStep1, readSyncStep1 } from './MessageHandler/syncStep1' import { sendSyncStep1, readSyncStep1 } from './MessageHandler/syncStep1.js'
import { readSyncStep2 } from './MessageHandler/syncStep2' import { readSyncStep2 } from './MessageHandler/syncStep2.js'
import { readUpdate } from './MessageHandler/update.js' import { readUpdate } from './MessageHandler/update.js'
import debug from 'debug' import { debug } from './Y.js'
export default class AbstractConnector { export default class AbstractConnector {
constructor (y, opts) { constructor (y, opts) {

View File

@ -1,5 +1,5 @@
import { getStruct } from '../Util/StructReferences' import { getStruct } from '../Util/StructReferences.js'
import BinaryDecoder from '../Util/Binary/Decoder' import BinaryDecoder from '../Binary/Decoder.js'
class MissingEntry { class MissingEntry {
constructor (decoder, missing, struct) { constructor (decoder, missing, struct) {
@ -39,7 +39,7 @@ function _integrateRemoteStructHelper (y, struct) {
} }
} }
export default function integrateRemoteStructs (decoder, encoder, y) { export function integrateRemoteStructs (decoder, encoder, y) {
while (decoder.length !== decoder.pos) { while (decoder.length !== decoder.pos) {
let decoderPos = decoder.pos let decoderPos = decoder.pos
let reference = decoder.readVarUint() let reference = decoder.readVarUint()

View File

@ -1,7 +1,7 @@
import BinaryDecoder from '../Utily/Binary/Decoder' import BinaryDecoder from '../Binary/Decoder.js'
import { stringifyUpdate } from './update' import { stringifyUpdate } from './update.js'
import { stringifySyncStep1 } from './syncStep1' import { stringifySyncStep1 } from './syncStep1.js'
import { stringifySyncStep2 } from './syncStep2' import { stringifySyncStep2 } from './syncStep2.js'
export function messageToString (buffer) { export function messageToString (buffer) {
let decoder = new BinaryDecoder(buffer) let decoder = new BinaryDecoder(buffer)

View File

@ -1,4 +1,4 @@
import BinaryEncoder from './Util/Binary/Encoder.js' import BinaryEncoder from '../Binary/Encoder.js'
export function stringifySyncStep1 (decoder, strBuilder) { export function stringifySyncStep1 (decoder, strBuilder) {
let auth = decoder.readVarString() let auth = decoder.readVarString()

View File

@ -1,6 +1,6 @@
import integrateRemoteStructs from './integrateRemoteStructs' import { integrateRemoteStructs } from './integrateRemoteStructs.js'
import { stringifyUpdate } from './update.js' import { stringifyUpdate } from './update.js'
import ID from '../Util/ID' import ID from '../Util/ID.js'
export function stringifySyncStep2 (decoder, strBuilder) { export function stringifySyncStep2 (decoder, strBuilder) {
strBuilder.push(' - auth: ' + decoder.readVarString() + '\n') strBuilder.push(' - auth: ' + decoder.readVarString() + '\n')

View File

@ -1,5 +1,5 @@
import { getStruct } from '../Util/StructReferences' import { getStruct } from '../Util/StructReferences.js'
export function stringifyUpdate (decoder, strBuilder) { export function stringifyUpdate (decoder, strBuilder) {
while (decoder.length !== decoder.pos) { while (decoder.length !== decoder.pos) {
@ -16,4 +16,4 @@ export function stringifyUpdate (decoder, strBuilder) {
} }
} }
export { integrateRemoteStructs as readUpdate } from './integrateRemoteStructs' export { integrateRemoteStructs as readUpdate } from './integrateRemoteStructs.js'

View File

@ -1,4 +1,4 @@
import { BinaryEncoder } from './Encoding.js' import BinaryEncoder from './Binary/Encoder.js'
export default function extendPersistence (Y) { export default function extendPersistence (Y) {
class AbstractPersistence { class AbstractPersistence {

View File

@ -1,5 +1,5 @@
import Tree from '../Util/Tree' import Tree from '../Util/Tree.js'
import ID from '../Util/ID' import ID from '../Util/ID.js'
class DSNode { class DSNode {
constructor (id, len, gc) { constructor (id, len, gc) {

View File

@ -1,11 +1,8 @@
import Tree from '../Util/Tree' import Tree from '../Util/Tree.js'
import RootID from '../Util/ID' import RootID from '../Util/ID.js'
import { getStruct } from '../Util/structReferences' import { getStruct } from '../Util/structReferences.js'
export default class OperationStore extends Tree { export default class OperationStore extends Tree {
constructor () {
}
get (id) { get (id) {
let struct = this.find(id) let struct = this.find(id)
if (struct === null && id instanceof RootID) { if (struct === null && id instanceof RootID) {
@ -27,7 +24,7 @@ export default class OperationStore extends Tree {
} else { } else {
return null return null
} }
} }
// Return an insertion such that id is the first element of content // Return an insertion such that id is the first element of content
// This function manipulates an operation, if necessary // This function manipulates an operation, if necessary

View File

@ -1,4 +1,4 @@
import ID from '../Util/ID' import ID from '../Util/ID.js'
export default class StateStore { export default class StateStore {
constructor (y) { constructor (y) {

View File

@ -1,4 +1,4 @@
import StructManager from '../Util/StructManager' import StructManager from '../Util/StructManager.js'
export default class Delete { export default class Delete {
constructor () { constructor () {

View File

@ -1,4 +1,3 @@
import StructManager from '../Util/StructManager'
export default class Item { export default class Item {
constructor () { constructor () {

View File

@ -1,4 +1,4 @@
import Item from './Item' import Item from './Item.js'
export default class ItemJSON extends Item { export default class ItemJSON extends Item {
constructor () { constructor () {

View File

@ -1,4 +1,4 @@
import Item from './Item' import Item from './Item.js'
export default class ItemString extends Item { export default class ItemString extends Item {
constructor () { constructor () {

View File

@ -1,4 +1,4 @@
import Item from './Item' import Item from './Item.js'
export default class Type extends Item { export default class Type extends Item {
constructor () { constructor () {

View File

@ -1,5 +1,5 @@
import Type from '../Struct/Type' import Type from '../Struct/Type.js'
import ItemJSON from '../Struct/ItemJSON' import ItemJSON from '../Struct/ItemJSON.js'
export default class YArray extends Type { export default class YArray extends Type {
forEach (f) { forEach (f) {

View File

@ -1,6 +1,6 @@
import Type from '../Struct/Type' import Type from '../Struct/Type.js'
import Item from '../Struct/Item' import Item from '../Struct/Item.js'
import ItemJSON from '../Struct/ItemJSON' import ItemJSON from '../Struct/ItemJSON.js'
export default class YMap extends Type { export default class YMap extends Type {
set (key, value) { set (key, value) {

View File

@ -0,0 +1,4 @@
import YArray from './YArray.js'
export default class YText extends YArray {
}

View File

@ -0,0 +1,4 @@
import YArray from './YArray.js'
export default class YXml extends YArray {
}

View File

@ -1,7 +1,7 @@
import StructManager from './StructManager' import { getReference } from './structReferences.js'
export class ID { export default class ID {
constructor (user, clock) { constructor (user, clock) {
this.user = user this.user = user
this.clock = clock this.clock = clock
@ -16,17 +16,3 @@ export class ID {
return this.user < id.user || (this.user === id.user && this.clock < id.clock) return this.user < id.user || (this.user === id.user && this.clock < id.clock)
} }
} }
export class RootID {
constructor (name, typeConstructor) {
this.user = -1
this.name = name
this.type = StructManager.getReference(typeConstructor)
}
equals (id) {
return id !== null && id.user === this.user && id.name === this.name && id.type === this.type
}
lessThan (id) {
return this.user < id.user || (this.user === id.user && (this.name < id.name || (this.name === id.name && this.type < id.type)))
}
}

14
src/Util/RootID.js Normal file
View File

@ -0,0 +1,14 @@
export default class RootID {
constructor (name, typeConstructor) {
this.user = -1
this.name = name
this.type = StructManager.getReference(typeConstructor)
}
equals (id) {
return id !== null && id.user === this.user && id.name === this.name && id.type === this.type
}
lessThan (id) {
return this.user < id.user || (this.user === id.user && (this.name < id.name || (this.name === id.name && this.type < id.type)))
}
}

View File

@ -1,7 +1,7 @@
import Delete from '../Struct/Delete' import Delete from '../Struct/Delete'
import ID from './ID' import ID from './ID'
export default function deleteItemRange (y, user, clock, length) { export function deleteItemRange (y, user, clock, length) {
let del = new Delete() let del = new Delete()
del._target = new ID(user, clock) del._target = new ID(user, clock)
del._length = length del._length = length

View File

@ -1,6 +1,6 @@
/* global crypto */ /* global crypto */
export default function generateUserID () { export function generateUserID () {
if (typeof crypto !== 'undefined' && crypto.getRandomValue != null) { if (typeof crypto !== 'undefined' && crypto.getRandomValue != null) {
// browser // browser
let arr = new Uint32Array(1) let arr = new Uint32Array(1)

View File

@ -1,10 +1,10 @@
import YArray from '../Type/YArray' import YArray from '../Type/YArray.js'
import YMap from '../Type/YMap' import YMap from '../Type/YMap.js'
import YText from '../Type/YText' import YText from '../Type/YText.js'
import YXml from '../Type/YXml' import YXml from '../Type/YXml.js'
import ItemJSON from '../Struct/ItemJSON' import ItemJSON from '../Struct/ItemJSON.js'
import ItemString from '../Struct/ItemString' import ItemString from '../Struct/ItemString.js'
const structs = new Map() const structs = new Map()
const references = new Map() const references = new Map()

View File

@ -1,20 +1,25 @@
import debug from 'debug' // import debug from 'debug'
export function debug (namespace) {
return function log (message) {
console.log(namespace, message)
}
}
import DeleteStore from './Store/DeleteStore' import DeleteStore from './Store/DeleteStore.js'
import OperationStore from './Store/OperationStore' import OperationStore from './Store/OperationStore.js'
import StateStore from './Store/StateStore' import StateStore from './Store/StateStore.js'
import generateUserID from './Function/generateUserID' import { generateUserID } from './Util/generateUserID.js'
import { RootID } from './Util/ID.js' import RootID from './Util/RootID.js'
import { formatYjsMessage, formatYjsMessageType } from './MessageHandler' import { messageToString, messageToRoomname } from './MessageHandler/messageToString.js'
import Connector from './Connector' import Connector from './Connector.js'
import Persistence from './Persistence' import Persistence from './Persistence.js'
import YArray from './Type/YArray' import YArray from './Type/YArray.js'
import YMap from './Type/YMap' import YMap from './Type/YMap.js'
import YText from './Type/YText' import YText from './Type/YText.js'
import YXml from './Type/YXml' import YXml from './Type/YXml.js'
export default class Y { export default class Y {
constructor (opts) { constructor (opts) {
@ -97,5 +102,5 @@ Y.Text = YText
Y.Xml = YXml Y.Xml = YXml
Y.debug = debug Y.debug = debug
debug.formatters.Y = formatYjsMessage debug.formatters.Y = messageToString
debug.formatters.y = formatYjsMessageType debug.formatters.y = messageToRoomname

View File

@ -1,7 +1,9 @@
import { test } from 'cutest' import { test } from '../node_modules/cutest/cutest.js'
import Chance from 'chance' import '../node_modules/chance/chance.js'
import Y from '../src/y.js' import Y from '../src/y.js'
import { BinaryEncoder, BinaryDecoder } from '../src/Encoding.js' import BinaryEncoder from '../src/Binary/Encoder.js'
import BinaryDecoder from '../src/Binary/Decoder.js'
import { generateUserID } from '../src/Util/generateUserID.js'
function testEncoding (t, write, read, val) { function testEncoding (t, write, read, val) {
let encoder = new BinaryEncoder() let encoder = new BinaryEncoder()
@ -42,7 +44,7 @@ test('varUint random', async function varUintRandom (t) {
test('varUint random user id', async function varUintRandomUserId (t) { test('varUint random user id', async function varUintRandomUserId (t) {
t.getSeed() // enforces that this test is repeated t.getSeed() // enforces that this test is repeated
testEncoding(t, writeVarUint, readVarUint, Y.utils.generateUserId()) testEncoding(t, writeVarUint, readVarUint, generateUserID())
}) })
const writeVarString = (encoder, val) => encoder.writeVarString(val) const writeVarString = (encoder, val) => encoder.writeVarString(val)
@ -59,122 +61,3 @@ test('varString random', async function varStringRandom (t) {
const chance = new Chance(t.getSeed() * 1000000000) const chance = new Chance(t.getSeed() * 1000000000)
testEncoding(t, writeVarString, readVarString, chance.string()) testEncoding(t, writeVarString, readVarString, chance.string())
}) })
const writeDelete = Y.Struct.Delete.binaryEncode
const readDelete = Y.Struct.Delete.binaryDecode
test('encode/decode Delete operation', async function binDelete (t) {
let op = {
target: [10, 3000],
length: 40000,
struct: 'Delete'
}
testEncoding(t, writeDelete, readDelete, op)
})
const writeInsert = Y.Struct.Insert.binaryEncode
const readInsert = Y.Struct.Insert.binaryDecode
test('encode/decode Insert operations', async function binInsert (t) {
testEncoding(t, writeInsert, readInsert, {
id: [1, 2],
right: [5, 6],
left: [3, 4],
origin: [7, 8],
parent: [9, 10],
struct: 'Insert',
content: ['a']
})
t.log('left === origin')
testEncoding(t, writeInsert, readInsert, {
id: [1, 2],
right: [5, 6],
left: [3, 4],
origin: [3, 4],
parent: [9, 10],
struct: 'Insert',
content: ['a']
})
t.log('parentsub')
testEncoding(t, writeInsert, readInsert, {
id: [1, 2],
right: [5, 6],
left: [3, 4],
origin: [3, 4],
parent: [9, 10],
parentSub: 'sub',
struct: 'Insert',
content: ['a']
})
t.log('opContent')
testEncoding(t, writeInsert, readInsert, {
id: [1, 2],
right: [5, 6],
left: [3, 4],
origin: [3, 4],
parent: [9, 10],
struct: 'Insert',
opContent: [1000, 10000]
})
t.log('mixed content')
testEncoding(t, writeInsert, readInsert, {
id: [1, 2],
right: [5, 6],
left: [3, 4],
origin: [3, 4],
parent: [9, 10],
struct: 'Insert',
content: ['a', 1]
})
t.log('origin is null')
testEncoding(t, writeInsert, readInsert, {
id: [1, 2],
right: [5, 6],
left: [3, 4],
origin: null,
parent: [9, 10],
struct: 'Insert',
content: ['a']
})
t.log('left = origin = right = null')
testEncoding(t, writeInsert, readInsert, {
id: [1, 2],
right: null,
left: null,
origin: null,
parent: [9, 10],
struct: 'Insert',
content: ['a']
})
})
const writeList = Y.Struct.List.binaryEncode
const readList = Y.Struct.List.binaryDecode
test('encode/decode List operations', async function binList (t) {
testEncoding(t, writeList, readList, {
struct: 'List',
id: [100, 33],
type: 'Array',
start: null,
end: null
})
})
const writeMap = Y.Struct.Map.binaryEncode
const readMap = Y.Struct.Map.binaryDecode
test('encode/decode Map operations', async function binMap (t) {
testEncoding(t, writeMap, readMap, {
struct: 'Map',
id: [100, 33],
type: 'Map',
map: {}
})
})

8
test/index.html Normal file
View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="module" src="./encode-decode.js"></script>
</body>
</html>

View File

@ -1,4 +1,4 @@
import { wait, initArrays, compareUsers, Y, flushAll, garbageCollectUsers, applyRandomTests } from '../tests-lib/helper.js' import { wait, initArrays, compareUsers, Y, flushAll, applyRandomTests } from '../tests-lib/helper.js'
import { test, proxyConsole } from 'cutest' import { test, proxyConsole } from 'cutest'
proxyConsole() proxyConsole()
@ -38,7 +38,6 @@ test('concurrent insert (handle three conflicts)', async function array2 (t) {
array0.insert(0, [0]) array0.insert(0, [0])
array1.insert(0, [1]) array1.insert(0, [1])
array2.insert(0, [2]) array2.insert(0, [2])
await compareUsers(t, users) await compareUsers(t, users)
}) })
@ -213,7 +212,6 @@ test('garbage collector', async function gc1 (t) {
await wait() await wait()
await users[0].reconnect() await users[0].reconnect()
await flushAll(t, users) await flushAll(t, users)
await garbageCollectUsers(t, users)
await compareUsers(t, users) await compareUsers(t, users)
}) })

View File

@ -1,34 +1,25 @@
import _Y from '../../yjs/src/y.js' import _Y from '../../yjs/src/y.js'
import yArray from '../../y-array/src/y-array.js'
import yText from '../../y-text/src/y-text.js'
import yMap from '../../y-map/src/y-map.js'
import yXml from '../../y-xml/src/y-xml.js'
import yTest from './test-connector.js' import yTest from './test-connector.js'
import Chance from 'chance' import Chance from 'chance'
export let Y = _Y export let Y = _Y
Y.extend(yArray, yText, yMap, yTest, yXml)
export var database = { name: 'memory' } export var database = { name: 'memory' }
export var connector = { name: 'test', url: 'http://localhost:1234' } export var connector = { name: 'test', url: 'http://localhost:1234' }
function getStateSet () { function getStateSet (y) {
var ss = {} let ss = {}
this.ss.iterate(this, null, null, function (n) { for (let [user, clock] of y.ss.state) {
var user = n.id[0]
var clock = n.clock
ss[user] = clock ss[user] = clock
}) }
return ss return ss
} }
function getDeleteSet () { function getDeleteSet (y) {
var ds = {} var ds = {}
this.ds.iterate(this, null, null, function (n) { y.ds.iterate(this, null, null, function (n) {
var user = n.id[0] var user = n.id[0]
var counter = n.id[1] var counter = n.id[1]
var len = n.len var len = n.len
@ -43,11 +34,6 @@ function getDeleteSet () {
return ds return ds
} }
export async function garbageCollectUsers (t, users) {
await flushAll(t, users)
await Promise.all(users.map(u => u.db.emptyGarbageCollector()))
}
export function attrsObject (dom) { export function attrsObject (dom) {
let keys = [] let keys = []
let yxml = dom.__yxml let yxml = dom.__yxml
@ -67,7 +53,7 @@ export function domToJson (dom) {
if (dom.nodeType === document.TEXT_NODE) { if (dom.nodeType === document.TEXT_NODE) {
return dom.textContent return dom.textContent
} else if (dom.nodeType === document.ELEMENT_NODE) { } else if (dom.nodeType === document.ELEMENT_NODE) {
let attributes = attrsObject(dom, dom.__yxml) let attributes = attrsObject(dom)
let children = Array.from(dom.childNodes.values()) let children = Array.from(dom.childNodes.values())
.filter(d => d.__yxml !== false) .filter(d => d.__yxml !== false)
.map(domToJson) .map(domToJson)
@ -97,20 +83,9 @@ export async function compareUsers (t, users) {
await wait() await wait()
await flushAll(t, users) await flushAll(t, users)
var userArrayValues = users.map(u => u.share.array._content.map(c => c.val || JSON.stringify(c.type))) var userArrayValues = users.map(u => u.get('array', Y.Array).toJSON())
function valueToComparable (v) { var userMapValues = users.map(u => u.get('map', Y.Map).toJSON())
if (v != null && v._model != null) { var userXmlValues = users.map(u => u.get('xml', Y.Xml).getDom().toString())
return v._model
} else {
return v || null
}
}
var userMapOneValues = users.map(u => u.share.map.get('one')).map(valueToComparable)
var userMapTwoValues = users.map(u => u.share.map.get('two')).map(valueToComparable)
var userXmlValues = users.map(u => u.share.xml.getDom()).map(domToJson)
await users[0].db.garbageCollect()
await users[0].db.garbageCollect()
// disconnect all except user 0 // disconnect all except user 0
await Promise.all(users.slice(1).map(async u => await Promise.all(users.slice(1).map(async u =>
@ -130,39 +105,30 @@ export async function compareUsers (t, users) {
u.connector.whenSynced(resolve) u.connector.whenSynced(resolve)
}) })
)) ))
let filterDeletedOps = users.every(u => u.db.gc === false) var data = users.forEach(u => {
var data = await Promise.all(users.map(async (u) => {
var data = {} var data = {}
u.db.requestTransaction(function () { let ops = []
let ops = [] y.os.iterate(null, null, function (op) {
this.os.iterate(this, null, null, function (op) { if (!op._deleted) {
ops.push(Y.Struct[op.struct].encode(op)) ops.push({
}) left: op._left,
right: op._right,
data.os = {} deleted: op._deleted
for (let i = 0; i < ops.length; i++) { })
let op = ops[i]
op = Y.Struct[op.struct].encode(op)
delete op.origin
/*
If gc = false, it is necessary to filter deleted ops
as they might have been split up differently..
*/
if (filterDeletedOps) {
let opIsDeleted = this.isDeleted(op.id)
if (!opIsDeleted) {
data.os[JSON.stringify(op.id)] = op
}
} else {
data.os[JSON.stringify(op.id)] = op
}
} }
data.ds = getDeleteSet.apply(this)
data.ss = getStateSet.apply(this)
}) })
await u.db.whenTransactionsFinished()
data.os = {}
for (let i = 0; i < ops.length; i++) {
let op = ops[i]
op = Y.Struct[op.struct].encode(op)
delete op.origin
data.os[JSON.stringify(op.id)] = op
}
data.ds = getDeleteSet.apply(this)
data.ss = getStateSet.apply(this)
return data return data
})) })
for (var i = 0; i < data.length - 1; i++) { for (var i = 0; i < data.length - 1; i++) {
await t.asyncGroup(async () => { await t.asyncGroup(async () => {
t.compare(userArrayValues[i], userArrayValues[i + 1], 'array types') t.compare(userArrayValues[i], userArrayValues[i + 1], 'array types')
@ -174,39 +140,27 @@ export async function compareUsers (t, users) {
t.compare(data[i].ss, data[i + 1].ss, 'ss') t.compare(data[i].ss, data[i + 1].ss, 'ss')
}, `Compare user${i} with user${i + 1}`) }, `Compare user${i} with user${i + 1}`)
} }
await Promise.all(users.map(async (u) => { users.map(u => u.close())
await u.close()
}))
} }
export async function initArrays (t, opts) { export async function initArrays (t, opts) {
var result = { var result = {
users: [] users: []
} }
var share = Object.assign({ flushHelper: 'Map', array: 'Array', map: 'Map', xml: 'XmlElement("div")' }, opts.share)
var chance = opts.chance || new Chance(t.getSeed() * 1000000000) var chance = opts.chance || new Chance(t.getSeed() * 1000000000)
var conn = Object.assign({ room: 'debugging_' + t.name, generateUserId: false, testContext: t, chance }, connector) var conn = Object.assign({ room: 'debugging_' + t.name, generateUserId: false, testContext: t, chance }, connector)
for (let i = 0; i < opts.users; i++) { for (let i = 0; i < opts.users; i++) {
let dbOpts
let connOpts let connOpts
if (i === 0) { if (i === 0) {
// Only one instance can gc!
dbOpts = Object.assign({ gc: false }, database)
connOpts = Object.assign({ role: 'master' }, conn) connOpts = Object.assign({ role: 'master' }, conn)
} else { } else {
dbOpts = Object.assign({ gc: false }, database)
connOpts = Object.assign({ role: 'slave' }, conn) connOpts = Object.assign({ role: 'slave' }, conn)
} }
let y = await Y({ let y = new Y({
connector: connOpts, connector: connOpts
db: dbOpts,
share: share
}) })
result.users.push(y) result.users.push(y)
for (let name in share) { y.get('xml', Y.Xml).setDomFilter(function (d, attrs) {
result[name + i] = y.share[name]
}
y.share.xml.setDomFilter(function (d, attrs) {
if (d.nodeName === 'HIDDEN') { if (d.nodeName === 'HIDDEN') {
return null return null
} else { } else {
@ -241,7 +195,7 @@ export async function flushAll (t, users) {
// flush for any connector // flush for any connector
await Promise.all(users.map(u => { return u.db.whenTransactionsFinished() })) await Promise.all(users.map(u => { return u.db.whenTransactionsFinished() }))
var flushCounter = users[0].share.flushHelper.get('0') || 0 var flushCounter = users[0].get('flushHelper', Y.Map).get('0') || 0
flushCounter++ flushCounter++
await Promise.all(users.map(async (u, i) => { await Promise.all(users.map(async (u, i) => {
// wait for all users to set the flush counter to the same value // wait for all users to set the flush counter to the same value
@ -249,7 +203,7 @@ export async function flushAll (t, users) {
function observer () { function observer () {
var allUsersReceivedUpdate = true var allUsersReceivedUpdate = true
for (var i = 0; i < users.length; i++) { for (var i = 0; i < users.length; i++) {
if (u.share.flushHelper.get(i + '') !== flushCounter) { if (u.get('flushHelper', Y.Map).get(i + '') !== flushCounter) {
allUsersReceivedUpdate = false allUsersReceivedUpdate = false
break break
} }
@ -258,8 +212,8 @@ export async function flushAll (t, users) {
resolve() resolve()
} }
} }
u.share.flushHelper.observe(observer) u.get('flushHelper', Y.Map).observe(observer)
u.share.flushHelper.set(i + '', flushCounter) u.get('flushHelper').set(i + '', flushCounter)
}) })
})) }))
} }

View File

@ -1,6 +1,6 @@
/* global Y */ /* global Y */
import { wait } from './helper.js' import { wait } from './helper'
import { formatYjsMessage } from '../src/MessageHandler.js' import { messageToString, messageToRoomname } from '../src/MessageHandler/messageToString'
var rooms = {} var rooms = {}