new approach for type definitions
This commit is contained in:
parent
ba4f444f32
commit
d79e3102fc
@ -91,7 +91,6 @@ module.exports = function (gulp, helperOptions) {
|
|||||||
var browserify = require('browserify')
|
var browserify = require('browserify')
|
||||||
var source = require('vinyl-source-stream')
|
var source = require('vinyl-source-stream')
|
||||||
var buffer = require('vinyl-buffer')
|
var buffer = require('vinyl-buffer')
|
||||||
|
|
||||||
return browserify({
|
return browserify({
|
||||||
entries: files.specs,
|
entries: files.specs,
|
||||||
debug: true
|
debug: true
|
||||||
|
@ -224,6 +224,9 @@ module.exports = function (Y /* :any */) {
|
|||||||
var o = ops[i]
|
var o = ops[i]
|
||||||
if (o.id == null || o.id[0] !== this.y.connector.userId) {
|
if (o.id == null || o.id[0] !== this.y.connector.userId) {
|
||||||
var required = Y.Struct[o.struct].requiredOps(o)
|
var required = Y.Struct[o.struct].requiredOps(o)
|
||||||
|
if (o.requires != null) {
|
||||||
|
required = required.concat(o.requires)
|
||||||
|
}
|
||||||
this.whenOperationsExist(required, o)
|
this.whenOperationsExist(required, o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,7 +375,7 @@ module.exports = function (Y /* :any */) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// notify parent, if it was instanciated as a custom type
|
// notify parent, if it was instanciated as a custom type
|
||||||
if (t != null) {
|
if (t != null && opIsDeleted) {
|
||||||
yield* t._changed(transaction, Y.utils.copyObject(op))
|
yield* t._changed(transaction, Y.utils.copyObject(op))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ g.g = g
|
|||||||
|
|
||||||
g.YConcurrency_TestingMode = true
|
g.YConcurrency_TestingMode = true
|
||||||
|
|
||||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000
|
||||||
|
|
||||||
g.describeManyTimes = function describeManyTimes (times, name, f) {
|
g.describeManyTimes = function describeManyTimes (times, name, f) {
|
||||||
for (var i = 0; i < times; i++) {
|
for (var i = 0; i < times; i++) {
|
||||||
@ -221,15 +221,18 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
|
|||||||
// TODO: make requestTransaction return a promise..
|
// TODO: make requestTransaction return a promise..
|
||||||
u.db.requestTransaction(function * () {
|
u.db.requestTransaction(function * () {
|
||||||
yield* t2.call(this)
|
yield* t2.call(this)
|
||||||
expect(s1).toEqual(s2)
|
var db2 = []
|
||||||
expect(allDels1).toEqual(allDels2) // inner structure
|
|
||||||
expect(ds1).toEqual(ds2) // exported structure
|
|
||||||
var count = 0
|
|
||||||
yield* this.os.iterate(this, null, null, function * (o) {
|
yield* this.os.iterate(this, null, null, function * (o) {
|
||||||
o = Y.utils.copyObject(o)
|
o = Y.utils.copyObject(o)
|
||||||
delete o.origin
|
delete o.origin
|
||||||
delete o.originOf
|
delete o.originOf
|
||||||
expect(db1[count++]).toEqual(o)
|
db2.push(o)
|
||||||
|
})
|
||||||
|
expect(s1).toEqual(s2)
|
||||||
|
expect(allDels1).toEqual(allDels2) // inner structure
|
||||||
|
expect(ds1).toEqual(ds2) // exported structure
|
||||||
|
db2.forEach((o, i) => {
|
||||||
|
expect(db1[i]).toEqual(o)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -237,7 +240,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
g.createUsers = async(function * createUsers (self, numberOfUsers, database) {
|
g.createUsers = async(function * createUsers (self, numberOfUsers, database, initType) {
|
||||||
if (Y.utils.globalRoom.users[0] != null) {
|
if (Y.utils.globalRoom.users[0] != null) {
|
||||||
yield Y.utils.globalRoom.flushAll()
|
yield Y.utils.globalRoom.flushAll()
|
||||||
}
|
}
|
||||||
@ -246,6 +249,7 @@ g.createUsers = async(function * createUsers (self, numberOfUsers, database) {
|
|||||||
Y.utils.globalRoom.users[u].y.destroy()
|
Y.utils.globalRoom.users[u].y.destroy()
|
||||||
}
|
}
|
||||||
self.users = null
|
self.users = null
|
||||||
|
yield wait()
|
||||||
|
|
||||||
var promises = []
|
var promises = []
|
||||||
for (var i = 0; i < numberOfUsers; i++) {
|
for (var i = 0; i < numberOfUsers; i++) {
|
||||||
@ -261,7 +265,7 @@ g.createUsers = async(function * createUsers (self, numberOfUsers, database) {
|
|||||||
debug: false
|
debug: false
|
||||||
},
|
},
|
||||||
share: {
|
share: {
|
||||||
root: 'Map'
|
root: initType || 'Map'
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -259,11 +259,18 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
encode: function (op) {
|
encode: function (op) {
|
||||||
return {
|
var e = {
|
||||||
struct: 'List',
|
struct: 'List',
|
||||||
id: op.id,
|
id: op.id,
|
||||||
type: op.type
|
type: op.type
|
||||||
}
|
}
|
||||||
|
if (op.requires != null) {
|
||||||
|
e.requires = op.requires
|
||||||
|
}
|
||||||
|
if (op.info != null) {
|
||||||
|
e.info = op.info
|
||||||
|
}
|
||||||
|
return e
|
||||||
},
|
},
|
||||||
requiredOps: function () {
|
requiredOps: function () {
|
||||||
/*
|
/*
|
||||||
@ -332,12 +339,19 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
encode: function (op) {
|
encode: function (op) {
|
||||||
return {
|
var e = {
|
||||||
struct: 'Map',
|
struct: 'Map',
|
||||||
type: op.type,
|
type: op.type,
|
||||||
id: op.id,
|
id: op.id,
|
||||||
map: {} // overwrite map!!
|
map: {} // overwrite map!!
|
||||||
}
|
}
|
||||||
|
if (op.requires != null) {
|
||||||
|
e.requires = op.requires
|
||||||
|
}
|
||||||
|
if (op.info != null) {
|
||||||
|
e.info = op.info
|
||||||
|
}
|
||||||
|
return e
|
||||||
},
|
},
|
||||||
requiredOps: function () {
|
requiredOps: function () {
|
||||||
return []
|
return []
|
||||||
|
@ -87,25 +87,28 @@ module.exports = function (Y/* :any */) {
|
|||||||
If it does not exist yes, create it.
|
If it does not exist yes, create it.
|
||||||
TODO: delete type from store.initializedTypes[id] when corresponding id was deleted!
|
TODO: delete type from store.initializedTypes[id] when corresponding id was deleted!
|
||||||
*/
|
*/
|
||||||
* getType (id) {
|
* getType (id, args) {
|
||||||
var sid = JSON.stringify(id)
|
var sid = JSON.stringify(id)
|
||||||
var t = this.store.initializedTypes[sid]
|
var t = this.store.initializedTypes[sid]
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
var op/* :MapStruct | ListStruct */ = yield* this.getOperation(id)
|
var op/* :MapStruct | ListStruct */ = yield* this.getOperation(id)
|
||||||
if (op != null) {
|
if (op != null) {
|
||||||
t = yield* Y[op.type].initType.call(this, this.store, op)
|
t = yield* Y[op.type].typeDefinition.initType.call(this, this.store, op, args)
|
||||||
this.store.initializedTypes[sid] = t
|
this.store.initializedTypes[sid] = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
* createType (typedefinition, id) {
|
* createType (typedefinition, id) {
|
||||||
var structname = typedefinition.struct
|
var structname = typedefinition[0].struct
|
||||||
id = id || this.store.getNextOpId()
|
id = id || this.store.getNextOpId()
|
||||||
var op = Y.Struct[structname].create(id)
|
var op = Y.Struct[structname].create(id)
|
||||||
op.type = typedefinition.name
|
op.type = typedefinition[0].name
|
||||||
|
if (typedefinition[0].appendAdditionalInfo != null) {
|
||||||
|
yield* typedefinition[0].appendAdditionalInfo.call(this, op, typedefinition[1])
|
||||||
|
}
|
||||||
yield* this.applyCreatedOperations([op])
|
yield* this.applyCreatedOperations([op])
|
||||||
return yield* this.getType(id)
|
return yield* this.getType(id, typedefinition[1])
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Apply operations that this user created (no remote ones!)
|
Apply operations that this user created (no remote ones!)
|
||||||
@ -117,7 +120,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
for (var i = 0; i < ops.length; i++) {
|
for (var i = 0; i < ops.length; i++) {
|
||||||
var op = ops[i]
|
var op = ops[i]
|
||||||
yield* this.store.tryExecute.call(this, op)
|
yield* this.store.tryExecute.call(this, op)
|
||||||
if (op.id == null || op.id[0] !== '_') {
|
if (op.id == null || typeof op.id[1] !== 'string') {
|
||||||
send.push(Y.Struct[op.struct].encode(op))
|
send.push(Y.Struct[op.struct].encode(op))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -643,7 +646,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
* addOperation (op) {
|
* addOperation (op) {
|
||||||
yield* this.os.put(op)
|
yield* this.os.put(op)
|
||||||
if (!this.store.y.connector.isDisconnected() && this.store.forwardAppliedOperations && op.id[0] !== '_') {
|
if (!this.store.y.connector.isDisconnected() && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
|
||||||
// is connected, and this is not going to be send in addOperation
|
// is connected, and this is not going to be send in addOperation
|
||||||
this.store.y.connector.broadcastOps([op])
|
this.store.y.connector.broadcastOps([op])
|
||||||
}
|
}
|
||||||
@ -653,12 +656,13 @@ module.exports = function (Y/* :any */) {
|
|||||||
if (o != null || id[0] !== '_') {
|
if (o != null || id[0] !== '_') {
|
||||||
return o
|
return o
|
||||||
} else {
|
} else {
|
||||||
// generate this operation?
|
/* // generate this operation?
|
||||||
if (typeof id[1] === 'string') {
|
if (typeof id[1] === 'string') {
|
||||||
var comp = id[1].split('_')
|
var comp = id[1].split('_')
|
||||||
if (comp.length > 1) {
|
if (comp.length > 2 || id[0] === '_') {
|
||||||
var struct = comp[0]
|
var struct = comp[0]
|
||||||
var op = Y.Struct[struct].create(id)
|
var op = Y.Struct[struct].create(id)
|
||||||
|
op.type = comp[1]
|
||||||
yield* this.setOperation(op)
|
yield* this.setOperation(op)
|
||||||
return op
|
return op
|
||||||
} else {
|
} else {
|
||||||
@ -668,9 +672,8 @@ module.exports = function (Y/* :any */) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Can only generate one operation at a time
|
*/
|
||||||
return null
|
return null
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
* removeOperation (id) {
|
* removeOperation (id) {
|
||||||
|
79
src/Utils.js
79
src/Utils.js
@ -26,7 +26,40 @@
|
|||||||
module.exports = function (Y /* : any*/) {
|
module.exports = function (Y /* : any*/) {
|
||||||
Y.utils = {}
|
Y.utils = {}
|
||||||
|
|
||||||
class EventHandler {
|
class EventListenerHandler {
|
||||||
|
constructor () {
|
||||||
|
this.eventListeners = []
|
||||||
|
}
|
||||||
|
destroy () {
|
||||||
|
this.eventListeners = null
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Basic event listener boilerplate...
|
||||||
|
*/
|
||||||
|
addEventListener (f) {
|
||||||
|
this.eventListeners.push(f)
|
||||||
|
}
|
||||||
|
removeEventListener (f) {
|
||||||
|
this.eventListeners = this.eventListeners.filter(function (g) {
|
||||||
|
return f !== g
|
||||||
|
})
|
||||||
|
}
|
||||||
|
removeAllEventListeners () {
|
||||||
|
this.eventListeners = []
|
||||||
|
}
|
||||||
|
callEventListeners (event) {
|
||||||
|
for (var i = 0; i < this.eventListeners.length; i++) {
|
||||||
|
try {
|
||||||
|
this.eventListeners[i](event)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('User events must not throw Errors!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Y.utils.EventListenerHandler = EventListenerHandler
|
||||||
|
|
||||||
|
class EventHandler extends EventListenerHandler {
|
||||||
/* ::
|
/* ::
|
||||||
waiting: Array<Insertion | Deletion>;
|
waiting: Array<Insertion | Deletion>;
|
||||||
awaiting: number;
|
awaiting: number;
|
||||||
@ -41,16 +74,16 @@ module.exports = function (Y /* : any*/) {
|
|||||||
all prematurely called operations were executed ("waiting operations")
|
all prematurely called operations were executed ("waiting operations")
|
||||||
*/
|
*/
|
||||||
constructor (onevent /* : Function */) {
|
constructor (onevent /* : Function */) {
|
||||||
|
super()
|
||||||
this.waiting = []
|
this.waiting = []
|
||||||
this.awaiting = 0
|
this.awaiting = 0
|
||||||
this.onevent = onevent
|
this.onevent = onevent
|
||||||
this.eventListeners = []
|
|
||||||
}
|
}
|
||||||
destroy () {
|
destroy () {
|
||||||
|
super.destroy()
|
||||||
this.waiting = null
|
this.waiting = null
|
||||||
this.awaiting = null
|
this.awaiting = null
|
||||||
this.onevent = null
|
this.onevent = null
|
||||||
this.eventListeners = null
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Call this when a new operation arrives. It will be executed right away if
|
Call this when a new operation arrives. It will be executed right away if
|
||||||
@ -72,30 +105,6 @@ module.exports = function (Y /* : any*/) {
|
|||||||
this.awaiting++
|
this.awaiting++
|
||||||
this.onevent(ops)
|
this.onevent(ops)
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Basic event listener boilerplate...
|
|
||||||
TODO: maybe put this in a different type..
|
|
||||||
*/
|
|
||||||
addEventListener (f) {
|
|
||||||
this.eventListeners.push(f)
|
|
||||||
}
|
|
||||||
removeEventListener (f) {
|
|
||||||
this.eventListeners = this.eventListeners.filter(function (g) {
|
|
||||||
return f !== g
|
|
||||||
})
|
|
||||||
}
|
|
||||||
removeAllEventListeners () {
|
|
||||||
this.eventListeners = []
|
|
||||||
}
|
|
||||||
callEventListeners (event) {
|
|
||||||
for (var i = 0; i < this.eventListeners.length; i++) {
|
|
||||||
try {
|
|
||||||
this.eventListeners[i](event)
|
|
||||||
} catch (e) {
|
|
||||||
console.log('User events must not throw Errors!') // eslint-disable-line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
Call this when you successfully awaited the execution of n Insert operations
|
Call this when you successfully awaited the execution of n Insert operations
|
||||||
*/
|
*/
|
||||||
@ -192,10 +201,26 @@ module.exports = function (Y /* : any*/) {
|
|||||||
this.initType = def.initType
|
this.initType = def.initType
|
||||||
this.class = def.class
|
this.class = def.class
|
||||||
this.name = def.name
|
this.name = def.name
|
||||||
|
if (def.appendAdditionalInfo != null) {
|
||||||
|
this.appendAdditionalInfo = def.appendAdditionalInfo
|
||||||
|
}
|
||||||
|
this.parseArguments = (def.parseArguments || function () {
|
||||||
|
return [this]
|
||||||
|
}).bind(this)
|
||||||
|
this.parseArguments.typeDefinition = this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Y.utils.CustomType = CustomType
|
Y.utils.CustomType = CustomType
|
||||||
|
|
||||||
|
Y.utils.isTypeDefinition = function isTypeDefinition (v) {
|
||||||
|
if (v != null) {
|
||||||
|
if (v instanceof Y.utils.CustomType) return [v]
|
||||||
|
else if (v.constructor === Array && v[0] instanceof Y.utils.CustomType) return v
|
||||||
|
else if (v instanceof Function && v.typeDefinition instanceof Y.utils.CustomType) return [v.typeDefinition]
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Make a flat copy of an object
|
Make a flat copy of an object
|
||||||
(just copy properties)
|
(just copy properties)
|
||||||
|
35
src/y.js
35
src/y.js
@ -14,7 +14,11 @@ module.exports = Y
|
|||||||
Y.requiringModules = requiringModules
|
Y.requiringModules = requiringModules
|
||||||
|
|
||||||
Y.extend = function (name, value) {
|
Y.extend = function (name, value) {
|
||||||
Y[name] = value
|
if (value instanceof Y.utils.CustomType) {
|
||||||
|
Y[name] = value.parseArguments
|
||||||
|
} else {
|
||||||
|
Y[name] = value
|
||||||
|
}
|
||||||
if (requiringModules[name] != null) {
|
if (requiringModules[name] != null) {
|
||||||
requiringModules[name].resolve()
|
requiringModules[name].resolve()
|
||||||
delete requiringModules[name]
|
delete requiringModules[name]
|
||||||
@ -29,9 +33,10 @@ function requestModules (modules) {
|
|||||||
var extention = typeof regeneratorRuntime !== 'undefined' ? '.js' : '.es6'
|
var extention = typeof regeneratorRuntime !== 'undefined' ? '.js' : '.es6'
|
||||||
var promises = []
|
var promises = []
|
||||||
for (var i = 0; i < modules.length; i++) {
|
for (var i = 0; i < modules.length; i++) {
|
||||||
var modulename = 'y-' + modules[i].toLowerCase()
|
var module = modules[i].split('(')[0]
|
||||||
if (Y[modules[i]] == null) {
|
var modulename = 'y-' + module.toLowerCase()
|
||||||
if (requiringModules[modules[i]] == null) {
|
if (Y[module] == null) {
|
||||||
|
if (requiringModules[module] == null) {
|
||||||
// module does not exist
|
// module does not exist
|
||||||
if (typeof window !== 'undefined' && window.Y !== 'undefined') {
|
if (typeof window !== 'undefined' && window.Y !== 'undefined') {
|
||||||
var imported = document.createElement('script')
|
var imported = document.createElement('script')
|
||||||
@ -39,7 +44,7 @@ function requestModules (modules) {
|
|||||||
document.head.appendChild(imported)
|
document.head.appendChild(imported)
|
||||||
|
|
||||||
let requireModule = {}
|
let requireModule = {}
|
||||||
requiringModules[modules[i]] = requireModule
|
requiringModules[module] = requireModule
|
||||||
requireModule.promise = new Promise(function (resolve) {
|
requireModule.promise = new Promise(function (resolve) {
|
||||||
requireModule.resolve = resolve
|
requireModule.resolve = resolve
|
||||||
})
|
})
|
||||||
@ -130,15 +135,19 @@ class YConfig {
|
|||||||
this.db.requestTransaction(function * requestTransaction () {
|
this.db.requestTransaction(function * requestTransaction () {
|
||||||
// create shared object
|
// create shared object
|
||||||
for (var propertyname in opts.share) {
|
for (var propertyname in opts.share) {
|
||||||
var typename = opts.share[propertyname]
|
var typeConstructor = opts.share[propertyname].split('(')
|
||||||
var id = ['_', Y[typename].struct + '_' + propertyname]
|
var typeName = typeConstructor.splice(0, 1)
|
||||||
var op = yield* this.getOperation(id)
|
var args = []
|
||||||
if (op.type !== typename) {
|
if (typeConstructor.length === 1) {
|
||||||
// not already in the db
|
try {
|
||||||
op.type = typename
|
args = JSON.parse('[' + typeConstructor[0].split(')')[0] + ']')
|
||||||
yield* this.setOperation(op)
|
} catch (e) {
|
||||||
|
throw new Error('Was not able to parse type definition! (share.' + propertyname + ')')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
share[propertyname] = yield* this.getType(id)
|
var id = ['_', propertyname + '_' + typeConstructor]
|
||||||
|
var type = Y[typeName]
|
||||||
|
share[propertyname] = yield* this.createType(type.apply(type.typeDefinition, args), id)
|
||||||
}
|
}
|
||||||
this.store.whenTransactionsFinished()
|
this.store.whenTransactionsFinished()
|
||||||
.then(callback)
|
.then(callback)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user