code refactoring, and documentation
This commit is contained in:
parent
638c575dfc
commit
8745fd64ca
@ -1,12 +1,8 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
before_install:
|
before_install:
|
||||||
- "npm install -g bower"
|
- "npm install -g bower"
|
||||||
- "bower install"
|
|
||||||
node_js:
|
node_js:
|
||||||
- "0.12"
|
- "0.12"
|
||||||
- "0.11"
|
|
||||||
- "0.10"
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- 0.6
|
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
Specify which specs to use!
|
Specify which specs to use!
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
- build
|
- build:deploy
|
||||||
Build this library
|
Build this library for deployment (es6->es5, minified)
|
||||||
- dev:browser
|
- dev:browser
|
||||||
Watch the ./src directory.
|
Watch the ./src directory.
|
||||||
Builds the library on changes.
|
Builds the library on changes.
|
||||||
|
@ -130,7 +130,7 @@ class AbstractConnector {
|
|||||||
}
|
}
|
||||||
send (uid, message) {
|
send (uid, message) {
|
||||||
if (this.debug) {
|
if (this.debug) {
|
||||||
console.log(`send ${this.userId} -> ${uid}: ${message.type}`, m);// eslint-disable-line
|
console.log(`send ${this.userId} -> ${uid}: ${message.type}`, m) // eslint-disable-line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -141,7 +141,7 @@ class AbstractConnector {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.debug) {
|
if (this.debug) {
|
||||||
console.log(`receive ${sender} -> ${this.userId}: ${m.type}`, m);// eslint-disable-line
|
console.log(`receive ${sender} -> ${this.userId}: ${m.type}`, m) // eslint-disable-line
|
||||||
}
|
}
|
||||||
if (m.type === 'sync step 1') {
|
if (m.type === 'sync step 1') {
|
||||||
// TODO: make transaction, stream the ops
|
// TODO: make transaction, stream the ops
|
||||||
@ -212,17 +212,19 @@ class AbstractConnector {
|
|||||||
this.y.db.apply(m.ops)
|
this.y.db.apply(m.ops)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Currently, the HB encodes operations as JSON. For the moment I want to keep it
|
/*
|
||||||
// that way. Maybe we support encoding in the HB as XML in the future, but for now I don't want
|
Currently, the HB encodes operations as JSON. For the moment I want to keep it
|
||||||
// too much overhead. Y is very likely to get changed a lot in the future
|
that way. Maybe we support encoding in the HB as XML in the future, but for now I don't want
|
||||||
//
|
too much overhead. Y is very likely to get changed a lot in the future
|
||||||
// Because we don't want to encode JSON as string (with character escaping, wich makes it pretty much unreadable)
|
|
||||||
// we encode the JSON as XML.
|
Because we don't want to encode JSON as string (with character escaping, wich makes it pretty much unreadable)
|
||||||
//
|
we encode the JSON as XML.
|
||||||
// When the HB support encoding as XML, the format should look pretty much like this.
|
|
||||||
//
|
When the HB support encoding as XML, the format should look pretty much like this.
|
||||||
// does not support primitive values as array elements
|
|
||||||
// expects an ltx (less than xml) object
|
does not support primitive values as array elements
|
||||||
|
expects an ltx (less than xml) object
|
||||||
|
*/
|
||||||
parseMessageFromXml (m) {
|
parseMessageFromXml (m) {
|
||||||
function parseArray (node) {
|
function parseArray (node) {
|
||||||
for (var n of node.children) {
|
for (var n of node.children) {
|
||||||
@ -256,14 +258,16 @@ class AbstractConnector {
|
|||||||
}
|
}
|
||||||
parseObject(m)
|
parseObject(m)
|
||||||
}
|
}
|
||||||
// encode message in xml
|
/*
|
||||||
// we use string because Strophe only accepts an "xml-string"..
|
encode message in xml
|
||||||
// So {a:4,b:{c:5}} will look like
|
we use string because Strophe only accepts an "xml-string"..
|
||||||
// <y a="4">
|
So {a:4,b:{c:5}} will look like
|
||||||
// <b c="5"></b>
|
<y a="4">
|
||||||
// </y>
|
<b c="5"></b>
|
||||||
// m - ltx element
|
</y>
|
||||||
// json - Object
|
m - ltx element
|
||||||
|
json - Object
|
||||||
|
*/
|
||||||
encodeMessageToXml (msg, obj) {
|
encodeMessageToXml (msg, obj) {
|
||||||
// attributes is optional
|
// attributes is optional
|
||||||
function encodeObject (m, json) {
|
function encodeObject (m, json) {
|
||||||
|
12
src/Notes.md
Normal file
12
src/Notes.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
# Notes
|
||||||
|
|
||||||
|
### Terminology
|
||||||
|
|
||||||
|
* DB: DataBase that holds all the information of the shared object. It is devided into the OS, DS, and SS. This can be a persistent database or an in-memory database. Depending on the type of database, it could make sense to store OS, DS, and SS in different tables, or maybe different databases.
|
||||||
|
* OS: OperationStore holds all the operations. An operation is a js object with a fixed number of name fields.
|
||||||
|
* DS: DeleteStore holds the information about which operations are deleted and which operations were garbage collected (no longer available in the OS).
|
||||||
|
* SS: StateSet holds the current state of the OS. SS.getState(username) refers to the amount of operations that were received by that respective user.
|
||||||
|
* Op: Operation defines an action on a shared type. But it is also the format in which we store the model of a type. This is why it is also called a Struct/Structure.
|
||||||
|
* Type and Structure: We crearly distinguish between type and structure. Short explanation: A type (e.g. Strings, Numbers) have a number of functions that you can apply on them. (+) is well defined on both of them. They are *modeled* by a structure - the functions really change the structure of a type. Types can be implemented differently but still provide the same functionality. In Yjs, almost all types are realized as a doubly linked list (on which Yjs can provide eventual convergence)
|
||||||
|
*
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Partial definition of a transaction
|
Partial definition of a transaction
|
||||||
|
|
||||||
|
A transaction provides all the the async functionality on a database.
|
||||||
|
|
||||||
By convention, a transaction has the following properties:
|
By convention, a transaction has the following properties:
|
||||||
* ss for StateSet
|
* ss for StateSet
|
||||||
* os for OperationStore
|
* os for OperationStore
|
||||||
@ -75,6 +78,10 @@ class AbstractTransaction {
|
|||||||
constructor (store) {
|
constructor (store) {
|
||||||
this.store = store
|
this.store = store
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Get a type based on the id of its model.
|
||||||
|
If it does not exist yes, create it.
|
||||||
|
*/
|
||||||
* getType (id) {
|
* getType (id) {
|
||||||
var sid = JSON.stringify(id)
|
var sid = JSON.stringify(id)
|
||||||
var t = this.store.initializedTypes[sid]
|
var t = this.store.initializedTypes[sid]
|
||||||
@ -87,12 +94,11 @@ class AbstractTransaction {
|
|||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
* createType (model) {
|
/*
|
||||||
var sid = JSON.stringify(model.id)
|
Apply operations that this user created (no remote ones!)
|
||||||
var t = yield* Y[model.type].initType.call(this, this.store, model)
|
* does not check for Struct.*.requiredOps()
|
||||||
this.store.initializedTypes[sid] = t
|
* also broadcasts it through the connector
|
||||||
return t
|
*/
|
||||||
}
|
|
||||||
* applyCreatedOperations (ops) {
|
* applyCreatedOperations (ops) {
|
||||||
var send = []
|
var send = []
|
||||||
for (var i = 0; i < ops.length; i++) {
|
for (var i = 0; i < ops.length; i++) {
|
||||||
@ -108,24 +114,13 @@ class AbstractTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Delete an operation from the OS, and add it to the GC, if necessary.
|
Mark an operation as deleted, and add it to the GC, if possible.
|
||||||
|
|
||||||
Rulez:
|
|
||||||
* The most left element in a list must not be deleted.
|
|
||||||
=> There is at least one element in the list
|
|
||||||
* When an operation o is deleted, then it checks if its right operation
|
|
||||||
can be gc'd (iff it's deleted)
|
|
||||||
*/
|
*/
|
||||||
* deleteOperation (targetId) {
|
* deleteOperation (targetId) {
|
||||||
var target = yield* this.getOperation(targetId)
|
var target = yield* this.getOperation(targetId)
|
||||||
|
|
||||||
if (target == null || !target.deleted) {
|
if (target == null || !target.deleted) {
|
||||||
this.ds.markDeleted(targetId)
|
this.ds.markDeleted(targetId)
|
||||||
var state = yield* this.getState(targetId[0])
|
|
||||||
if (state.clock === targetId[1]) {
|
|
||||||
yield* this.checkDeleteStoreForState(state)
|
|
||||||
yield* this.setState(state)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target != null && target.gc == null) {
|
if (target != null && target.gc == null) {
|
||||||
@ -143,23 +138,16 @@ class AbstractTransaction {
|
|||||||
var left = target.left != null ? yield* this.getOperation(target.left) : null
|
var left = target.left != null ? yield* this.getOperation(target.left) : null
|
||||||
var right = target.right != null ? yield* this.getOperation(target.right) : null
|
var right = target.right != null ? yield* this.getOperation(target.right) : null
|
||||||
|
|
||||||
this.store.addToGarbageCollector(target, left, right)
|
this.store.addToGarbageCollector(target, left)
|
||||||
|
|
||||||
// set here because it was deleted and/or gc'd
|
// set here because it was deleted and/or gc'd
|
||||||
yield* this.setOperation(target)
|
yield* this.setOperation(target)
|
||||||
|
|
||||||
if (
|
// check if it is possible to add right to the gc (this delete can't be responsible for left being gc'd)
|
||||||
left != null &&
|
|
||||||
left.left != null &&
|
|
||||||
this.store.addToGarbageCollector(left, yield* this.getOperation(left.left), target)
|
|
||||||
) {
|
|
||||||
yield* this.setOperation(left)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
right != null &&
|
right != null &&
|
||||||
right.right != null &&
|
right.right != null &&
|
||||||
this.store.addToGarbageCollector(right, target, yield* this.getOperation(right.right))
|
this.store.addToGarbageCollector(right, target)
|
||||||
) {
|
) {
|
||||||
yield* this.setOperation(right)
|
yield* this.setOperation(right)
|
||||||
}
|
}
|
||||||
@ -177,30 +165,44 @@ class AbstractTransaction {
|
|||||||
o = yield* this.getOperation(id)
|
o = yield* this.getOperation(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check to increase the state of the respective user
|
||||||
|
var state = yield* this.getState(id[0])
|
||||||
|
if (state.clock === id[1]) {
|
||||||
|
// also check if more expected operations were gc'd
|
||||||
|
yield* this.checkDeleteStoreForState(state)
|
||||||
|
// then set the state
|
||||||
|
yield* this.setState(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove gc'd op from the left op, if it exists
|
||||||
if (o.left != null) {
|
if (o.left != null) {
|
||||||
var left = yield* this.getOperation(o.left)
|
var left = yield* this.getOperation(o.left)
|
||||||
left.right = o.right
|
left.right = o.right
|
||||||
yield* this.setOperation(left)
|
yield* this.setOperation(left)
|
||||||
}
|
}
|
||||||
|
// remove gc'd op from the right op, if it exists
|
||||||
if (o.right != null) {
|
if (o.right != null) {
|
||||||
var right = yield* this.getOperation(o.right)
|
var right = yield* this.getOperation(o.right)
|
||||||
right.left = o.left
|
right.left = o.left
|
||||||
yield* this.setOperation(right)
|
yield* this.setOperation(right)
|
||||||
}
|
}
|
||||||
|
// remove gc'd op from parent, if it exists
|
||||||
var parent = yield* this.getOperation(o.parent)
|
var parent = yield* this.getOperation(o.parent)
|
||||||
var setParent = false
|
var setParent = false // whether to save parent to the os
|
||||||
if (Y.utils.compareIds(parent.start, o.id)) {
|
if (Y.utils.compareIds(parent.start, o.id)) {
|
||||||
|
// gc'd op is the start
|
||||||
setParent = true
|
setParent = true
|
||||||
parent.start = o.right
|
parent.start = o.right
|
||||||
}
|
}
|
||||||
if (Y.utils.compareIds(parent.end, o.id)) {
|
if (Y.utils.compareIds(parent.end, o.id)) {
|
||||||
|
// gc'd op is the end
|
||||||
setParent = true
|
setParent = true
|
||||||
parent.end = o.left
|
parent.end = o.left
|
||||||
}
|
}
|
||||||
if (setParent) {
|
if (setParent) {
|
||||||
yield* this.setOperation(parent)
|
yield* this.setOperation(parent)
|
||||||
}
|
}
|
||||||
yield* this.removeOperation(o.id)
|
yield* this.removeOperation(o.id) // actually remove it from the os
|
||||||
yield* this.ds.markGarbageCollected(o.id)
|
yield* this.ds.markGarbageCollected(o.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,10 +274,9 @@ class AbstractOperationStore {
|
|||||||
var os = this.os
|
var os = this.os
|
||||||
var self = this
|
var self = this
|
||||||
os.iterate(null, null, function (op) {
|
os.iterate(null, null, function (op) {
|
||||||
if (op.deleted && op.left != null && op.right != null) {
|
if (op.deleted && op.left != null) {
|
||||||
var left = os.find(op.left)
|
var left = os.find(op.left)
|
||||||
var right = os.find(op.right)
|
self.addToGarbageCollector(op, left)
|
||||||
self.addToGarbageCollector(op, left, right)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -284,24 +285,20 @@ class AbstractOperationStore {
|
|||||||
|
|
||||||
TODO: rename this function
|
TODO: rename this function
|
||||||
|
|
||||||
Only gc when
|
Rulez:
|
||||||
* creator of op is online
|
* Only gc if this user is online
|
||||||
* left & right defined and both are from the same creator as op
|
* The most left element in a list must not be gc'd.
|
||||||
|
=> There is at least one element in the list
|
||||||
|
|
||||||
returns true iff op was added to GC
|
returns true iff op was added to GC
|
||||||
*/
|
*/
|
||||||
addToGarbageCollector (op, left, right) {
|
addToGarbageCollector (op, left) {
|
||||||
if (
|
if (
|
||||||
op.gc == null &&
|
op.gc == null &&
|
||||||
op.deleted === true &&
|
op.deleted === true &&
|
||||||
this.y.connector.isSynced &&
|
this.y.connector.isSynced &&
|
||||||
// (this.y.connector.connections[op.id[0]] != null || op.id[0] === this.y.connector.userId) &&
|
|
||||||
left != null &&
|
left != null &&
|
||||||
right != null &&
|
|
||||||
left.deleted &&
|
left.deleted &&
|
||||||
right.deleted &&
|
|
||||||
left.id[0] === op.id[0] &&
|
|
||||||
right.id[0] === op.id[0]
|
|
||||||
) {
|
) {
|
||||||
op.gc = true
|
op.gc = true
|
||||||
this.gc1.push(op.id)
|
this.gc1.push(op.id)
|
||||||
@ -343,23 +340,25 @@ class AbstractOperationStore {
|
|||||||
}
|
}
|
||||||
return [this.userId, this.opClock++]
|
return [this.userId, this.opClock++]
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Apply a list of operations.
|
||||||
|
|
||||||
|
* get a transaction
|
||||||
|
* check whether all Struct.*.requiredOps are in the OS
|
||||||
|
* check if it is an expected op (otherwise wait for it)
|
||||||
|
* check if was deleted, apply a delete operation after op was applied
|
||||||
|
*/
|
||||||
apply (ops) {
|
apply (ops) {
|
||||||
for (var key in ops) {
|
for (var key in ops) {
|
||||||
var o = ops[key]
|
var o = ops[key]
|
||||||
if (o.gc == null) { // TODO: why do i get the same op twice?
|
|
||||||
if (o.deleted == null) {
|
|
||||||
var required = Y.Struct[o.struct].requiredOps(o)
|
var required = Y.Struct[o.struct].requiredOps(o)
|
||||||
this.whenOperationsExist(required, o)
|
this.whenOperationsExist(required, o)
|
||||||
} else {
|
|
||||||
throw new Error('Ops must not contain deleted field!')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Error("Must not receive gc'd ops!")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
/*
|
||||||
// op is executed as soon as every operation requested is available.
|
op is executed as soon as every operation requested is available.
|
||||||
// Note that Transaction can (and should) buffer requests.
|
Note that Transaction can (and should) buffer requests.
|
||||||
|
*/
|
||||||
whenOperationsExist (ids, op) {
|
whenOperationsExist (ids, op) {
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
let listener = {
|
let listener = {
|
||||||
@ -390,7 +389,7 @@ class AbstractOperationStore {
|
|||||||
this.listenersByIdRequestPending = true
|
this.listenersByIdRequestPending = true
|
||||||
var store = this
|
var store = this
|
||||||
|
|
||||||
this.requestTransaction(function *() {
|
this.requestTransaction(function * () {
|
||||||
var exeNow = store.listenersByIdExecuteNow
|
var exeNow = store.listenersByIdExecuteNow
|
||||||
store.listenersByIdExecuteNow = []
|
store.listenersByIdExecuteNow = []
|
||||||
|
|
||||||
@ -421,6 +420,13 @@ class AbstractOperationStore {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Actually execute an operation, when all expected operations are available.
|
||||||
|
If op is not yet expected, add it to the list of waiting operations.
|
||||||
|
|
||||||
|
This will also try to execute waiting operations
|
||||||
|
(ops that were not expected yet), after it was applied
|
||||||
|
*/
|
||||||
* tryExecute (op) {
|
* tryExecute (op) {
|
||||||
if (op.struct === 'Delete') {
|
if (op.struct === 'Delete') {
|
||||||
yield* Y.Struct.Delete.execute.call(this, op)
|
yield* Y.Struct.Delete.execute.call(this, op)
|
||||||
@ -439,6 +445,7 @@ class AbstractOperationStore {
|
|||||||
yield* this.addOperation(op)
|
yield* this.addOperation(op)
|
||||||
yield* this.store.operationAdded(this, op)
|
yield* this.store.operationAdded(this, op)
|
||||||
|
|
||||||
|
// Delete if DS says this is actually deleted
|
||||||
if (this.store.ds.isDeleted(op.id)) {
|
if (this.store.ds.isDeleted(op.id)) {
|
||||||
yield* Y.Struct['Delete'].execute.call(this, {struct: 'Delete', target: op.id})
|
yield* Y.Struct['Delete'].execute.call(this, {struct: 'Delete', target: op.id})
|
||||||
}
|
}
|
||||||
@ -479,21 +486,5 @@ class AbstractOperationStore {
|
|||||||
yield* t._changed(transaction, Y.utils.copyObject(op))
|
yield* t._changed(transaction, Y.utils.copyObject(op))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeParentListener (id, f) {
|
|
||||||
var ls = this.parentListeners[id]
|
|
||||||
if (ls != null) {
|
|
||||||
this.parentListeners[id] = ls.filter(function (g) {
|
|
||||||
return (f !== g)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addParentListener (id, f) {
|
|
||||||
var ls = this.parentListeners[JSON.stringify(id)]
|
|
||||||
if (ls == null) {
|
|
||||||
ls = []
|
|
||||||
this.parentListeners[JSON.stringify(id)] = ls
|
|
||||||
}
|
|
||||||
ls.push(f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Y.AbstractOperationStore = AbstractOperationStore
|
Y.AbstractOperationStore = AbstractOperationStore
|
||||||
|
@ -122,7 +122,7 @@ Y.IndexedDB = (function () { // eslint-disable-line
|
|||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
|
||||||
function handleTransactions (t) { // eslint-disable-line no-unused-vars
|
function handleTransactions (t) {
|
||||||
var request = t.value
|
var request = t.value
|
||||||
if (t.done) {
|
if (t.done) {
|
||||||
return
|
return
|
||||||
|
@ -167,15 +167,16 @@
|
|||||||
Y.Array = new Y.utils.CustomType({
|
Y.Array = new Y.utils.CustomType({
|
||||||
class: YArray,
|
class: YArray,
|
||||||
createType: function * YArrayCreator () {
|
createType: function * YArrayCreator () {
|
||||||
|
var modelid = this.store.getNextOpId()
|
||||||
var model = {
|
var model = {
|
||||||
struct: 'List',
|
struct: 'List',
|
||||||
type: 'Array',
|
type: 'Array',
|
||||||
start: null,
|
start: null,
|
||||||
end: null,
|
end: null,
|
||||||
id: this.store.getNextOpId()
|
id: modelid
|
||||||
}
|
}
|
||||||
yield* this.applyCreatedOperations([model])
|
yield* this.applyCreatedOperations([model])
|
||||||
return yield* this.createType(model)
|
return modelid
|
||||||
},
|
},
|
||||||
initType: function * YArrayInitializer (os, model) {
|
initType: function * YArrayInitializer (os, model) {
|
||||||
var valArray = []
|
var valArray = []
|
||||||
|
@ -134,8 +134,9 @@
|
|||||||
if (value instanceof Y.utils.CustomType) {
|
if (value instanceof Y.utils.CustomType) {
|
||||||
// construct a new type
|
// construct a new type
|
||||||
this.os.requestTransaction(function *() {
|
this.os.requestTransaction(function *() {
|
||||||
var type = yield* value.createType.call(this)
|
var typeid = yield* value.createType.call(this)
|
||||||
insert.opContent = type._model
|
var type = yield* this.getType(typeid)
|
||||||
|
insert.opContent = typeid
|
||||||
insert.id = this.store.getNextOpId()
|
insert.id = this.store.getNextOpId()
|
||||||
yield* this.applyCreatedOperations([insert])
|
yield* this.applyCreatedOperations([insert])
|
||||||
resolve(type)
|
resolve(type)
|
||||||
@ -212,14 +213,15 @@
|
|||||||
Y.Map = new Y.utils.CustomType({
|
Y.Map = new Y.utils.CustomType({
|
||||||
class: YMap,
|
class: YMap,
|
||||||
createType: function * YMapCreator () {
|
createType: function * YMapCreator () {
|
||||||
|
var modelid = this.store.getNextOpId()
|
||||||
var model = {
|
var model = {
|
||||||
map: {},
|
map: {},
|
||||||
struct: 'Map',
|
struct: 'Map',
|
||||||
type: 'Map',
|
type: 'Map',
|
||||||
id: this.store.getNextOpId()
|
id: modelid
|
||||||
}
|
}
|
||||||
yield* this.applyCreatedOperations([model])
|
yield* this.applyCreatedOperations([model])
|
||||||
return yield* this.createType(model)
|
return modelid
|
||||||
},
|
},
|
||||||
initType: function * YMapInitializer (os, model) { // eslint-disable-line
|
initType: function * YMapInitializer (os, model) { // eslint-disable-line
|
||||||
return new YMap(os, model)
|
return new YMap(os, model)
|
||||||
|
@ -267,15 +267,16 @@
|
|||||||
Y.TextBind = new Y.utils.CustomType({
|
Y.TextBind = new Y.utils.CustomType({
|
||||||
class: YTextBind,
|
class: YTextBind,
|
||||||
createType: function * YTextBindCreator () {
|
createType: function * YTextBindCreator () {
|
||||||
|
var modelid = this.store.getNextOpId()
|
||||||
var model = {
|
var model = {
|
||||||
start: null,
|
start: null,
|
||||||
end: null,
|
end: null,
|
||||||
struct: 'List',
|
struct: 'List',
|
||||||
type: 'TextBind',
|
type: 'TextBind',
|
||||||
id: this.store.getNextOpId()
|
id: modelid
|
||||||
}
|
}
|
||||||
yield* this.applyCreatedOperations([model])
|
yield* this.applyCreatedOperations([model])
|
||||||
return yield* this.createType(model)
|
return modelid
|
||||||
},
|
},
|
||||||
initType: function * YTextBindInitializer (os, model) {
|
initType: function * YTextBindInitializer (os, model) {
|
||||||
var valArray = []
|
var valArray = []
|
||||||
|
8
src/y.js
8
src/y.js
@ -37,14 +37,6 @@ class YConfig {
|
|||||||
}
|
}
|
||||||
reconnect () {
|
reconnect () {
|
||||||
this.connector.reconnect()
|
this.connector.reconnect()
|
||||||
/* TODO: maybe do this..
|
|
||||||
Promise.all([
|
|
||||||
this.db.garbageCollect(),
|
|
||||||
this.db.garbageCollect()
|
|
||||||
]).then(() => {
|
|
||||||
this.connector.reconnect()
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
destroy () {
|
destroy () {
|
||||||
this.connector.disconnect()
|
this.connector.disconnect()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user