* starting flow integration
* found a bug in EventHelper * reduce wait() calls
This commit is contained in:
parent
940a44bb7c
commit
bd9c3813fd
12
.flowconfig
Normal file
12
.flowconfig
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[ignore]
|
||||||
|
.*/node_modules/.*
|
||||||
|
.*/dist/.*
|
||||||
|
.*/build/.*
|
||||||
|
|
||||||
|
[include]
|
||||||
|
./src/
|
||||||
|
|
||||||
|
[libs]
|
||||||
|
./declarations/
|
||||||
|
|
||||||
|
[options]
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -1,3 +1,5 @@
|
|||||||
// Place your settings in this file to overwrite default and user settings.
|
// Place your settings in this file to overwrite default and user settings.
|
||||||
{
|
{
|
||||||
|
"standard.enable": true,
|
||||||
|
"javascript.validate.enable": false
|
||||||
}
|
}
|
26
declarations/Structs.js
Normal file
26
declarations/Structs.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
type UserId = string
|
||||||
|
type Id = [UserId, number]
|
||||||
|
|
||||||
|
/*
|
||||||
|
type Struct = {
|
||||||
|
id: Id,
|
||||||
|
left?: Id,
|
||||||
|
right?: Id,
|
||||||
|
target?: Id,
|
||||||
|
struct: 'Insert' | 'Delete'
|
||||||
|
}*/
|
||||||
|
type Struct = Insertion | Deletion
|
||||||
|
|
||||||
|
type Insertion = {
|
||||||
|
id: Id,
|
||||||
|
left: Id,
|
||||||
|
right: Id,
|
||||||
|
struct: 'Insert'
|
||||||
|
}
|
||||||
|
|
||||||
|
type Deletion = {
|
||||||
|
target: Id,
|
||||||
|
struct: 'Delete'
|
||||||
|
}
|
17
declarations/Y.js
Normal file
17
declarations/Y.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
type YGlobal = {
|
||||||
|
utils: Object;
|
||||||
|
Struct: Object;
|
||||||
|
AbstractDatabase: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
type YInstance = {
|
||||||
|
db: Object,
|
||||||
|
connector: Object,
|
||||||
|
root: Object
|
||||||
|
}
|
||||||
|
|
||||||
|
declare var YConcurrency_TestingMode : boolean
|
||||||
|
|
||||||
|
type Transaction<A> = Generator<any, A, any>
|
@ -16,6 +16,7 @@
|
|||||||
"ignore": [
|
"ignore": [
|
||||||
"build/**",
|
"build/**",
|
||||||
"dist/**",
|
"dist/**",
|
||||||
|
"declarations/**",
|
||||||
"./y.js",
|
"./y.js",
|
||||||
"./y.js.map"
|
"./y.js.map"
|
||||||
]
|
]
|
||||||
|
@ -24,16 +24,11 @@ module.exports = function (Y) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
whenTransactionsFinished: function () {
|
whenTransactionsFinished: function () {
|
||||||
var self = this
|
var ps = []
|
||||||
return new Promise (function (resolve) {
|
for (var name in this.users) {
|
||||||
wait().then(function () {
|
ps.push(this.users[name].y.db.whenTransactionsFinished())
|
||||||
var ps = []
|
}
|
||||||
for (var name in self.users) {
|
return Promise.all(ps)
|
||||||
ps.push(self.users[name].y.db.whenTransactionsFinished())
|
|
||||||
}
|
|
||||||
Promise.all(ps).then(resolve)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
flushOne: function flushOne () {
|
flushOne: function flushOne () {
|
||||||
var bufs = []
|
var bufs = []
|
||||||
@ -59,7 +54,8 @@ module.exports = function (Y) {
|
|||||||
function nextFlush () {
|
function nextFlush () {
|
||||||
var c = globalRoom.flushOne()
|
var c = globalRoom.flushOne()
|
||||||
if (c) {
|
if (c) {
|
||||||
while (c = globalRoom.flushOne()) {
|
while (c) {
|
||||||
|
c = globalRoom.flushOne()
|
||||||
}
|
}
|
||||||
globalRoom.whenTransactionsFinished().then(nextFlush)
|
globalRoom.whenTransactionsFinished().then(nextFlush)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
/* @flow */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
module.exports = function (Y) {
|
module.exports = function (Y /* : YGlobal */) {
|
||||||
/*
|
/*
|
||||||
Partial definition of an OperationStore.
|
Partial definition of an OperationStore.
|
||||||
TODO: name it Database, operation store only holds operations.
|
TODO: name it Database, operation store only holds operations.
|
||||||
@ -14,6 +15,28 @@ module.exports = function (Y) {
|
|||||||
- destroy the database
|
- destroy the database
|
||||||
*/
|
*/
|
||||||
class AbstractDatabase {
|
class AbstractDatabase {
|
||||||
|
/* ::
|
||||||
|
y: YInstance;
|
||||||
|
forwardAppliedOperations: boolean;
|
||||||
|
listenersById: Object;
|
||||||
|
listenersByIdExecuteNow: Array<Object>;
|
||||||
|
listenersByIdRequestPending: boolean;
|
||||||
|
initializedTypes: Object;
|
||||||
|
whenUserIdSetListener: ?Function;
|
||||||
|
waitingTransactions: Array<Transaction>;
|
||||||
|
transactionInProgress: boolean;
|
||||||
|
executeOrder: Array<Object>;
|
||||||
|
gc1: Array<Struct>;
|
||||||
|
gc2: Array<Struct>;
|
||||||
|
gcTimeout: number;
|
||||||
|
gcInterval: any;
|
||||||
|
garbageCollect: Function;
|
||||||
|
executeOrder: Array<any>; // for debugging only
|
||||||
|
userId: UserId;
|
||||||
|
opClock: number;
|
||||||
|
transactionsFinished: ?{promise: Promise, resolve: any};
|
||||||
|
transact: (x: ?Generator) => any;
|
||||||
|
*/
|
||||||
constructor (y, opts) {
|
constructor (y, opts) {
|
||||||
this.y = y
|
this.y = y
|
||||||
// whether to broadcast all applied operations (insert & delete hook)
|
// whether to broadcast all applied operations (insert & delete hook)
|
||||||
@ -51,7 +74,7 @@ module.exports = function (Y) {
|
|||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
os.requestTransaction(function * () {
|
os.requestTransaction(function * () {
|
||||||
if (os.y.connector != null && os.y.connector.isSynced) {
|
if (os.y.connector != null && os.y.connector.isSynced) {
|
||||||
for (var i in os.gc2) {
|
for (var i = 0; i < os.gc2.length; i++) {
|
||||||
var oid = os.gc2[i]
|
var oid = os.gc2[i]
|
||||||
yield* this.garbageCollectOperation(oid)
|
yield* this.garbageCollectOperation(oid)
|
||||||
}
|
}
|
||||||
@ -72,7 +95,7 @@ module.exports = function (Y) {
|
|||||||
}
|
}
|
||||||
addToDebug () {
|
addToDebug () {
|
||||||
if (typeof YConcurrency_TestingMode !== 'undefined') {
|
if (typeof YConcurrency_TestingMode !== 'undefined') {
|
||||||
var command = Array.prototype.map.call(arguments, function (s) {
|
var command /* :string */ = Array.prototype.map.call(arguments, function (s) {
|
||||||
if (typeof s === 'string') {
|
if (typeof s === 'string') {
|
||||||
return s
|
return s
|
||||||
} else {
|
} else {
|
||||||
@ -89,10 +112,10 @@ module.exports = function (Y) {
|
|||||||
var self = this
|
var self = this
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
self.requestTransaction(function * () {
|
self.requestTransaction(function * () {
|
||||||
var ungc = self.gc1.concat(self.gc2)
|
var ungc /* :Array<Struct> */ = self.gc1.concat(self.gc2)
|
||||||
self.gc1 = []
|
self.gc1 = []
|
||||||
self.gc2 = []
|
self.gc2 = []
|
||||||
for (var i in ungc) {
|
for (var i = 0; i < ungc.length; i++) {
|
||||||
var op = yield* this.getOperation(ungc[i])
|
var op = yield* this.getOperation(ungc[i])
|
||||||
delete op.gc
|
delete op.gc
|
||||||
yield* this.setOperation(op)
|
yield* this.setOperation(op)
|
||||||
@ -145,7 +168,8 @@ module.exports = function (Y) {
|
|||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
self.requestTransaction(function * () {
|
self.requestTransaction(function * () {
|
||||||
self.userId = userId
|
self.userId = userId
|
||||||
self.opClock = (yield* this.getState(userId)).clock
|
var state = yield* this.getState(userId)
|
||||||
|
self.opClock = state.clock
|
||||||
if (self.whenUserIdSetListener != null) {
|
if (self.whenUserIdSetListener != null) {
|
||||||
self.whenUserIdSetListener()
|
self.whenUserIdSetListener()
|
||||||
self.whenUserIdSetListener = null
|
self.whenUserIdSetListener = null
|
||||||
@ -225,7 +249,7 @@ module.exports = function (Y) {
|
|||||||
|
|
||||||
store.listenersByIdRequestPending = false
|
store.listenersByIdRequestPending = false
|
||||||
|
|
||||||
for (let key in exeNow) {
|
for (let key = 0; key < exeNow.length; key++) {
|
||||||
let o = exeNow[key].op
|
let o = exeNow[key].op
|
||||||
yield* store.tryExecute.call(this, o)
|
yield* store.tryExecute.call(this, o)
|
||||||
}
|
}
|
||||||
@ -233,7 +257,8 @@ module.exports = function (Y) {
|
|||||||
for (var sid in ls) {
|
for (var sid in ls) {
|
||||||
var l = ls[sid]
|
var l = ls[sid]
|
||||||
var id = JSON.parse(sid)
|
var id = JSON.parse(sid)
|
||||||
if ((yield* this.getOperation(id)) == null) {
|
var op = yield* this.getOperation(id)
|
||||||
|
if (op == null) {
|
||||||
store.listenersById[sid] = l
|
store.listenersById[sid] = l
|
||||||
} else {
|
} else {
|
||||||
for (let key in l) {
|
for (let key in l) {
|
||||||
@ -250,15 +275,28 @@ module.exports = function (Y) {
|
|||||||
/*
|
/*
|
||||||
Actually execute an operation, when all expected operations are available.
|
Actually execute an operation, when all expected operations are available.
|
||||||
*/
|
*/
|
||||||
|
/* :: // TODO: this belongs somehow to transaction
|
||||||
|
store: Object;
|
||||||
|
getOperation: any;
|
||||||
|
isGarbageCollected: any;
|
||||||
|
addOperation: any;
|
||||||
|
whenOperationsExist: any;
|
||||||
|
*/
|
||||||
* tryExecute (op) {
|
* tryExecute (op) {
|
||||||
this.store.addToDebug('yield* this.store.tryExecute.call(this, ', JSON.stringify(op), ')')
|
this.store.addToDebug('yield* this.store.tryExecute.call(this, ', JSON.stringify(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)
|
||||||
yield* this.store.operationAdded(this, op)
|
yield* this.store.operationAdded(this, op)
|
||||||
} else if ((yield* this.getOperation(op.id)) == null && !(yield* this.isGarbageCollected(op.id))) {
|
} else {
|
||||||
yield* Y.Struct[op.struct].execute.call(this, op)
|
var defined = yield* this.getOperation(op.id)
|
||||||
yield* this.addOperation(op)
|
if (defined == null) {
|
||||||
yield* this.store.operationAdded(this, op)
|
var isGarbageCollected = yield* this.isGarbageCollected(op.id)
|
||||||
|
if (!isGarbageCollected) {
|
||||||
|
yield* Y.Struct[op.struct].execute.call(this, op)
|
||||||
|
yield* this.addOperation(op)
|
||||||
|
yield* this.store.operationAdded(this, op)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// called by a transaction when an operation is added
|
// called by a transaction when an operation is added
|
||||||
@ -300,30 +338,38 @@ module.exports = function (Y) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var t = this.initializedTypes[JSON.stringify(op.parent)]
|
var t = this.initializedTypes[JSON.stringify(op.parent)]
|
||||||
// notify parent, if it has been initialized as a custom type
|
|
||||||
if (t != null) {
|
|
||||||
yield* t._changed(transaction, Y.utils.copyObject(op))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete if DS says this is actually deleted
|
// Delete if DS says this is actually deleted
|
||||||
if (!op.deleted && (yield* transaction.isDeleted(op.id))) {
|
var opIsDeleted = yield* transaction.isDeleted(op.id)
|
||||||
|
if (!op.deleted && opIsDeleted) {
|
||||||
var delop = {
|
var delop = {
|
||||||
struct: 'Delete',
|
struct: 'Delete',
|
||||||
target: op.id
|
target: op.id
|
||||||
}
|
}
|
||||||
yield* Y.Struct['Delete'].execute.call(transaction, delop)
|
yield* Y.Struct['Delete'].execute.call(transaction, delop)
|
||||||
if (t != null) {
|
}
|
||||||
yield* t._changed(transaction, delop)
|
|
||||||
}
|
// notify parent, if it has been initialized as a custom type
|
||||||
|
if (t != null) {
|
||||||
|
yield* t._changed(transaction, Y.utils.copyObject(op))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
whenTransactionsFinished () {
|
whenTransactionsFinished () {
|
||||||
if (this.transactionInProgress) {
|
if (this.transactionInProgress) {
|
||||||
if (this.transactionsFinished == null) {
|
if (this.transactionsFinished == null) {
|
||||||
this.transactionsFinished = Promise.defer()
|
var resolve
|
||||||
|
var promise = new Promise(function (r) {
|
||||||
|
resolve = r
|
||||||
|
})
|
||||||
|
this.transactionsFinished = {
|
||||||
|
resolve: resolve,
|
||||||
|
promise: promise
|
||||||
|
}
|
||||||
|
return promise
|
||||||
|
} else {
|
||||||
|
return this.transactionsFinished.promise
|
||||||
}
|
}
|
||||||
return this.transactionsFinished.promise
|
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
@ -340,8 +386,8 @@ module.exports = function (Y) {
|
|||||||
return this.waitingTransactions.shift()
|
return this.waitingTransactions.shift()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
requestTransaction (makeGen, callImmediately) {
|
requestTransaction (makeGen/* :any */, callImmediately) {
|
||||||
if (callImmediately || true) {
|
if (callImmediately) {
|
||||||
this.waitingTransactions.push(makeGen)
|
this.waitingTransactions.push(makeGen)
|
||||||
if (!this.transactionInProgress) {
|
if (!this.transactionInProgress) {
|
||||||
this.transactionInProgress = true
|
this.transactionInProgress = true
|
||||||
|
@ -37,12 +37,12 @@ g.describeManyTimes = function describeManyTimes (times, name, f) {
|
|||||||
*/
|
*/
|
||||||
function wait (t) {
|
function wait (t) {
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
t = 5
|
t = 0
|
||||||
}
|
}
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
resolve()
|
resolve()
|
||||||
}, t * 3)
|
}, t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
g.wait = wait
|
g.wait = wait
|
||||||
@ -162,7 +162,8 @@ g.compareAllUsers = async(function * compareAllUsers (users) {
|
|||||||
var buffer = Y.utils.globalRoom.buffers
|
var buffer = Y.utils.globalRoom.buffers
|
||||||
for (var name in buffer) {
|
for (var name in buffer) {
|
||||||
if (buffer[name].length > 0) {
|
if (buffer[name].length > 0) {
|
||||||
debugger // not all ops were transmitted..
|
// not all ops were transmitted..
|
||||||
|
debugger // eslint-disable-line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +157,6 @@ module.exports = function (Y) {
|
|||||||
insert.id = this.os.getNextOpId()
|
insert.id = this.os.getNextOpId()
|
||||||
var eventHandler = this.eventHandler
|
var eventHandler = this.eventHandler
|
||||||
eventHandler.awaitAndPrematurelyCall([insert])
|
eventHandler.awaitAndPrematurelyCall([insert])
|
||||||
|
|
||||||
this.os.requestTransaction(function *() {
|
this.os.requestTransaction(function *() {
|
||||||
yield* this.applyCreatedOperations([insert])
|
yield* this.applyCreatedOperations([insert])
|
||||||
eventHandler.awaitedInserts(1)
|
eventHandler.awaitedInserts(1)
|
||||||
@ -258,7 +257,8 @@ module.exports = function (Y) {
|
|||||||
}
|
}
|
||||||
* _changed (transaction, op) {
|
* _changed (transaction, op) {
|
||||||
if (op.struct === 'Delete') {
|
if (op.struct === 'Delete') {
|
||||||
op.key = (yield* transaction.getOperation(op.target)).parentSub
|
var target = yield* transaction.getOperation(op.target)
|
||||||
|
op.key = target.parentSub
|
||||||
}
|
}
|
||||||
this.eventHandler.receivedOp(op)
|
this.eventHandler.receivedOp(op)
|
||||||
}
|
}
|
||||||
|
84
src/Utils.js
84
src/Utils.js
@ -1,3 +1,4 @@
|
|||||||
|
/* @flow */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6,24 +7,32 @@
|
|||||||
Why: When constructing custom types, you sometimes want your types to work
|
Why: When constructing custom types, you sometimes want your types to work
|
||||||
synchronous: E.g.
|
synchronous: E.g.
|
||||||
``` Synchronous
|
``` Synchronous
|
||||||
mytype.setSomething("yay")
|
mytype.setSomething("yay")
|
||||||
mytype.getSomething() === "yay"
|
|
||||||
```
|
|
||||||
``` Asynchronous
|
|
||||||
mytype.setSomething("yay")
|
|
||||||
mytype.getSomething() === undefined
|
|
||||||
mytype.waitForSomething().then(function(){
|
|
||||||
mytype.getSomething() === "yay"
|
mytype.getSomething() === "yay"
|
||||||
})
|
```
|
||||||
|
versus
|
||||||
|
``` Asynchronous
|
||||||
|
mytype.setSomething("yay")
|
||||||
|
mytype.getSomething() === undefined
|
||||||
|
mytype.waitForSomething().then(function(){
|
||||||
|
mytype.getSomething() === "yay"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
The structures usually work asynchronously (you have to wait for the
|
The structures usually work asynchronously (you have to wait for the
|
||||||
database request to finish). EventHandler will help you to make your type
|
database request to finish). EventHandler will help you to make your type
|
||||||
synchronously.
|
synchronous.
|
||||||
*/
|
*/
|
||||||
module.exports = function (Y) {
|
module.exports = function (Y /* : YGlobal*/) {
|
||||||
Y.utils = {}
|
Y.utils = {}
|
||||||
|
|
||||||
class EventHandler {
|
class EventHandler {
|
||||||
|
/* ::
|
||||||
|
waiting: Array<Insertion | Deletion>;
|
||||||
|
awaiting: number;
|
||||||
|
onevent: Function;
|
||||||
|
eventListeners: Array<Function>;
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
onevent: is called when the structure changes.
|
onevent: is called when the structure changes.
|
||||||
|
|
||||||
@ -31,7 +40,7 @@ module.exports = function (Y) {
|
|||||||
prematurely called. Events for received operations can not be executed until
|
prematurely called. Events for received operations can not be executed until
|
||||||
all prematurely called operations were executed ("waiting operations")
|
all prematurely called operations were executed ("waiting operations")
|
||||||
*/
|
*/
|
||||||
constructor (onevent) {
|
constructor (onevent /* : Function */) {
|
||||||
this.waiting = []
|
this.waiting = []
|
||||||
this.awaiting = 0
|
this.awaiting = 0
|
||||||
this.onevent = onevent
|
this.onevent = onevent
|
||||||
@ -73,7 +82,7 @@ module.exports = function (Y) {
|
|||||||
this.eventListeners = []
|
this.eventListeners = []
|
||||||
}
|
}
|
||||||
callEventListeners (event) {
|
callEventListeners (event) {
|
||||||
for (var i in this.eventListeners) {
|
for (var i = 0; i < this.eventListeners.length; i++) {
|
||||||
try {
|
try {
|
||||||
this.eventListeners[i](event)
|
this.eventListeners[i](event)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -88,18 +97,24 @@ module.exports = function (Y) {
|
|||||||
var ops = this.waiting.splice(this.waiting.length - n)
|
var ops = this.waiting.splice(this.waiting.length - n)
|
||||||
for (var oid = 0; oid < ops.length; oid++) {
|
for (var oid = 0; oid < ops.length; oid++) {
|
||||||
var op = ops[oid]
|
var op = ops[oid]
|
||||||
for (var i = this.waiting.length - 1; i >= 0; i--) {
|
if (op.struct === 'Insert') {
|
||||||
let w = this.waiting[i]
|
for (var i = this.waiting.length - 1; i >= 0; i--) {
|
||||||
if (Y.utils.compareIds(op.left, w.id)) {
|
let w = this.waiting[i]
|
||||||
// include the effect of op in w
|
if (w.struct === 'Insert') {
|
||||||
w.right = op.id
|
if (Y.utils.compareIds(op.left, w.id)) {
|
||||||
// exclude the effect of w in op
|
// include the effect of op in w
|
||||||
op.left = w.left
|
w.right = op.id
|
||||||
} else if (Y.utils.compareIds(op.right, w.id)) {
|
// exclude the effect of w in op
|
||||||
// similar..
|
op.left = w.left
|
||||||
w.left = op.id
|
} else if (Y.utils.compareIds(op.right, w.id)) {
|
||||||
op.right = w.right
|
// similar..
|
||||||
|
w.left = op.id
|
||||||
|
op.right = w.right
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('Expected Insert Operation!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._tryCallEvents()
|
this._tryCallEvents()
|
||||||
@ -109,16 +124,20 @@ module.exports = function (Y) {
|
|||||||
*/
|
*/
|
||||||
awaitedDeletes (n, newLeft) {
|
awaitedDeletes (n, newLeft) {
|
||||||
var ops = this.waiting.splice(this.waiting.length - n)
|
var ops = this.waiting.splice(this.waiting.length - n)
|
||||||
for (var j in ops) {
|
for (var j = 0; j < ops.length; j++) {
|
||||||
var del = ops[j]
|
var del = ops[j]
|
||||||
if (newLeft != null) {
|
if (del.struct === 'Delete') {
|
||||||
for (var i in this.waiting) {
|
if (newLeft != null) {
|
||||||
let w = this.waiting[i]
|
for (var i = 0; i < this.waiting.length; i++) {
|
||||||
// We will just care about w.left
|
let w = this.waiting[i]
|
||||||
if (Y.utils.compareIds(del.target, w.left)) {
|
// We will just care about w.left
|
||||||
del.left = newLeft
|
if (w.struct === 'Insert' && Y.utils.compareIds(del.target, w.left)) {
|
||||||
|
w.left = newLeft
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('Expected Delete Operation!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._tryCallEvents()
|
this._tryCallEvents()
|
||||||
@ -149,6 +168,11 @@ module.exports = function (Y) {
|
|||||||
- the constructor of the custom type (e.g. in order to inherit from a type)
|
- the constructor of the custom type (e.g. in order to inherit from a type)
|
||||||
*/
|
*/
|
||||||
class CustomType { // eslint-disable-line
|
class CustomType { // eslint-disable-line
|
||||||
|
/* ::
|
||||||
|
createType: any;
|
||||||
|
initType: any;
|
||||||
|
class: Function;
|
||||||
|
*/
|
||||||
constructor (def) {
|
constructor (def) {
|
||||||
if (def.createType == null ||
|
if (def.createType == null ||
|
||||||
def.initType == null ||
|
def.initType == null ||
|
||||||
|
4
src/y.js
4
src/y.js
@ -1,4 +1,3 @@
|
|||||||
/* @flow */
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
require('./Connector.js')(Y)
|
require('./Connector.js')(Y)
|
||||||
@ -20,7 +19,8 @@ Y.extend = function (name, value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Y.requestModules = function (modules) {
|
Y.requestModules = requestModules
|
||||||
|
function requestModules (modules) {
|
||||||
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 modulename = 'y-' + modules[i].toLowerCase()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user