separate dom binding
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
|
||||
import _Y from '../src/Y.js'
|
||||
import yTest from './test-connector.js'
|
||||
import _Y from '../src/Y.dist.js'
|
||||
import { DomBinding } from '../src/Y.js'
|
||||
import TestConnector from './test-connector.js'
|
||||
|
||||
import Chance from 'chance'
|
||||
import ItemJSON from '../src/Struct/ItemJSON.js'
|
||||
@@ -10,11 +11,11 @@ import Quill from 'quill'
|
||||
|
||||
export const Y = _Y
|
||||
|
||||
Y.extend(yTest)
|
||||
|
||||
export const database = { name: 'memory' }
|
||||
export const connector = { name: 'test', url: 'http://localhost:1234' }
|
||||
|
||||
Y.test = TestConnector
|
||||
|
||||
function getStateSet (y) {
|
||||
let ss = {}
|
||||
for (let [user, clock] of y.ss.state) {
|
||||
@@ -40,6 +41,7 @@ function getDeleteSet (y) {
|
||||
return ds
|
||||
}
|
||||
|
||||
// TODO: remove?
|
||||
export function attrsObject (dom) {
|
||||
let keys = []
|
||||
let yxml = dom._yxml
|
||||
@@ -55,6 +57,7 @@ export function attrsObject (dom) {
|
||||
return obj
|
||||
}
|
||||
|
||||
// TODO: remove?
|
||||
export function domToJson (dom) {
|
||||
if (dom.nodeType === document.TEXT_NODE) {
|
||||
return dom.textContent
|
||||
@@ -140,6 +143,14 @@ export async function compareUsers (t, users) {
|
||||
users.map(u => u.destroy())
|
||||
}
|
||||
|
||||
function domFilter (nodeName, attrs) {
|
||||
if (nodeName === 'HIDDEN') {
|
||||
return null
|
||||
}
|
||||
attrs.delete('hidden')
|
||||
return attrs
|
||||
}
|
||||
|
||||
export async function initArrays (t, opts) {
|
||||
var result = {
|
||||
users: []
|
||||
@@ -154,27 +165,25 @@ export async function initArrays (t, opts) {
|
||||
connOpts = Object.assign({ role: 'slave' }, conn)
|
||||
}
|
||||
let y = new Y(connOpts.room, {
|
||||
_userID: i, // evil hackery, don't try this at home
|
||||
userID: i, // evil hackery, don't try this at home
|
||||
connector: connOpts
|
||||
})
|
||||
result.users.push(y)
|
||||
result['array' + i] = y.define('array', Y.Array)
|
||||
result['map' + i] = y.define('map', Y.Map)
|
||||
result['xml' + i] = y.define('xml', Y.XmlElement)
|
||||
const yxml = y.define('xml', Y.XmlElement)
|
||||
result['xml' + i] = yxml
|
||||
const dom = document.createElement('my-dom')
|
||||
const domBinding = new DomBinding(yxml, dom, { domFilter })
|
||||
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'))
|
||||
const quillBinding = new Y.QuillBinding(textType, quill)
|
||||
result['quillBinding' + i] = new Y.QuillBinding(textType, quill)
|
||||
result['quill' + i] = quill
|
||||
result['quillBinding' + i] = quillBinding
|
||||
y.quill = quill // put quill on the y object (so we can use it later)
|
||||
y.get('xml').setDomFilter(function (nodeName, attrs) {
|
||||
if (nodeName === 'HIDDEN') {
|
||||
return null
|
||||
}
|
||||
attrs.delete('hidden')
|
||||
return attrs
|
||||
})
|
||||
y.dom = dom
|
||||
y.on('afterTransaction', function () {
|
||||
for (let missing of y._missingStructs.values()) {
|
||||
if (Array.from(missing.values()).length > 0) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* global Y */
|
||||
import { wait } from './helper'
|
||||
import { messageToString } from '../src/MessageHandler/messageToString'
|
||||
import AbstractConnector from '../src/Connector.js'
|
||||
|
||||
var rooms = {}
|
||||
|
||||
@@ -64,107 +65,99 @@ function getTestRoom (roomname) {
|
||||
return rooms[roomname]
|
||||
}
|
||||
|
||||
export default function extendTestConnector (Y) {
|
||||
class TestConnector extends Y.AbstractConnector {
|
||||
constructor (y, options) {
|
||||
if (options === undefined) {
|
||||
throw new Error('Options must not be undefined!')
|
||||
}
|
||||
if (options.room == null) {
|
||||
throw new Error('You must define a room name!')
|
||||
}
|
||||
options.forwardAppliedOperations = options.role === 'master'
|
||||
super(y, options)
|
||||
this.options = options
|
||||
this.room = options.room
|
||||
this.chance = options.chance
|
||||
this.testRoom = getTestRoom(this.room)
|
||||
this.testRoom.join(this)
|
||||
export default class TestConnector extends AbstractConnector {
|
||||
constructor (y, options) {
|
||||
if (options === undefined) {
|
||||
throw new Error('Options must not be undefined!')
|
||||
}
|
||||
disconnect () {
|
||||
this.testRoom.leave(this)
|
||||
return super.disconnect()
|
||||
if (options.room == null) {
|
||||
throw new Error('You must define a room name!')
|
||||
}
|
||||
logBufferParsed () {
|
||||
console.log(' === Logging buffer of user ' + this.y.userID + ' === ')
|
||||
for (let [user, conn] of this.connections) {
|
||||
console.log(` ${user}:`)
|
||||
for (let i = 0; i < conn.buffer.length; i++) {
|
||||
console.log(messageToString(conn.buffer[i]))
|
||||
}
|
||||
options.forwardAppliedOperations = options.role === 'master'
|
||||
super(y, options)
|
||||
this.options = options
|
||||
this.room = options.room
|
||||
this.chance = options.chance
|
||||
this.testRoom = getTestRoom(this.room)
|
||||
this.testRoom.join(this)
|
||||
}
|
||||
disconnect () {
|
||||
this.testRoom.leave(this)
|
||||
return super.disconnect()
|
||||
}
|
||||
logBufferParsed () {
|
||||
console.log(' === Logging buffer of user ' + this.y.userID + ' === ')
|
||||
for (let [user, conn] of this.connections) {
|
||||
console.log(` ${user}:`)
|
||||
for (let i = 0; i < conn.buffer.length; i++) {
|
||||
console.log(messageToString(conn.buffer[i]))
|
||||
}
|
||||
}
|
||||
reconnect () {
|
||||
this.testRoom.join(this)
|
||||
super.reconnect()
|
||||
return new Promise(resolve => {
|
||||
this.whenSynced(resolve)
|
||||
})
|
||||
}
|
||||
send (uid, message) {
|
||||
super.send(uid, message)
|
||||
this.testRoom.send(this.y.userID, uid, message)
|
||||
}
|
||||
broadcast (message) {
|
||||
super.broadcast(message)
|
||||
this.testRoom.broadcast(this.y.userID, message)
|
||||
}
|
||||
async whenSynced (f) {
|
||||
var synced = false
|
||||
var periodicFlushTillSync = () => {
|
||||
if (synced) {
|
||||
f()
|
||||
} else {
|
||||
this.testRoom.flushAll([this.y]).then(function () {
|
||||
setTimeout(periodicFlushTillSync, 10)
|
||||
})
|
||||
}
|
||||
}
|
||||
periodicFlushTillSync()
|
||||
return super.whenSynced(function () {
|
||||
synced = true
|
||||
})
|
||||
}
|
||||
receiveMessage (sender, m) {
|
||||
if (this.y.userID !== sender && this.connections.has(sender)) {
|
||||
var buffer = this.connections.get(sender).buffer
|
||||
if (buffer == null) {
|
||||
buffer = this.connections.get(sender).buffer = []
|
||||
}
|
||||
buffer.push(m)
|
||||
if (this.chance.bool({likelihood: 30})) {
|
||||
// flush 1/2 with 30% chance
|
||||
var flushLength = Math.round(buffer.length / 2)
|
||||
buffer.splice(0, flushLength).forEach(m => {
|
||||
super.receiveMessage(sender, m)
|
||||
})
|
||||
}
|
||||
}
|
||||
reconnect () {
|
||||
this.testRoom.join(this)
|
||||
super.reconnect()
|
||||
return new Promise(resolve => {
|
||||
this.whenSynced(resolve)
|
||||
})
|
||||
}
|
||||
send (uid, message) {
|
||||
super.send(uid, message)
|
||||
this.testRoom.send(this.y.userID, uid, message)
|
||||
}
|
||||
broadcast (message) {
|
||||
super.broadcast(message)
|
||||
this.testRoom.broadcast(this.y.userID, message)
|
||||
}
|
||||
async whenSynced (f) {
|
||||
var synced = false
|
||||
var periodicFlushTillSync = () => {
|
||||
if (synced) {
|
||||
f()
|
||||
} else {
|
||||
this.testRoom.flushAll([this.y]).then(function () {
|
||||
setTimeout(periodicFlushTillSync, 10)
|
||||
})
|
||||
}
|
||||
}
|
||||
async _flushAll (flushUsers) {
|
||||
if (flushUsers.some(u => u.connector.y.userID === this.y.userID)) {
|
||||
// this one needs to sync with every other user
|
||||
flushUsers = Array.from(this.connections.keys()).map(uid => this.testRoom.users.get(uid).y)
|
||||
periodicFlushTillSync()
|
||||
return super.whenSynced(function () {
|
||||
synced = true
|
||||
})
|
||||
}
|
||||
receiveMessage (sender, m) {
|
||||
if (this.y.userID !== sender && this.connections.has(sender)) {
|
||||
var buffer = this.connections.get(sender).buffer
|
||||
if (buffer == null) {
|
||||
buffer = this.connections.get(sender).buffer = []
|
||||
}
|
||||
for (let i = 0; i < flushUsers.length; i++) {
|
||||
let userID = flushUsers[i].connector.y.userID
|
||||
if (userID !== this.y.userID && this.connections.has(userID)) {
|
||||
let buffer = this.connections.get(userID).buffer
|
||||
if (buffer != null) {
|
||||
var messages = buffer.splice(0)
|
||||
for (let j = 0; j < messages.length; j++) {
|
||||
super.receiveMessage(userID, messages[j])
|
||||
}
|
||||
buffer.push(m)
|
||||
if (this.chance.bool({likelihood: 30})) {
|
||||
// flush 1/2 with 30% chance
|
||||
var flushLength = Math.round(buffer.length / 2)
|
||||
buffer.splice(0, flushLength).forEach(m => {
|
||||
super.receiveMessage(sender, m)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
async _flushAll (flushUsers) {
|
||||
if (flushUsers.some(u => u.connector.y.userID === this.y.userID)) {
|
||||
// this one needs to sync with every other user
|
||||
flushUsers = Array.from(this.connections.keys()).map(uid => this.testRoom.users.get(uid).y)
|
||||
}
|
||||
for (let i = 0; i < flushUsers.length; i++) {
|
||||
let userID = flushUsers[i].connector.y.userID
|
||||
if (userID !== this.y.userID && this.connections.has(userID)) {
|
||||
let buffer = this.connections.get(userID).buffer
|
||||
if (buffer != null) {
|
||||
var messages = buffer.splice(0)
|
||||
for (let j = 0; j < messages.length; j++) {
|
||||
super.receiveMessage(userID, messages[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
return 'done'
|
||||
}
|
||||
return 'done'
|
||||
}
|
||||
// TODO: this should be moved to a separate module (dont work on Y)
|
||||
Y.test = TestConnector
|
||||
}
|
||||
|
||||
if (typeof Y !== 'undefined') {
|
||||
extendTestConnector(Y)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user