Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c926ce09f5 | ||
|
|
653a436b88 | ||
|
|
5ab60028ce | ||
|
|
428d825f41 | ||
|
|
b9f9c762eb | ||
|
|
80ab682b0a | ||
|
|
3f60690880 | ||
|
|
e2f93af86e |
19
Examples/Drawing/index.html
Normal file
19
Examples/Drawing/index.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<style>
|
||||||
|
path {
|
||||||
|
fill: none;
|
||||||
|
stroke: blue;
|
||||||
|
stroke-width: 1px;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
stroke-linecap: round;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<button type="button" id="clearDrawingCanvas">Clear Drawing</button>
|
||||||
|
<svg id="drawingCanvas" viewbox="0 0 100 100" width="100%"></svg>
|
||||||
|
<script src="../bower_components/yjs/y.js"></script>
|
||||||
|
<script src="../bower_components/d3/d3.js"></script>
|
||||||
|
<script src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
88
Examples/Drawing/index.js
Normal file
88
Examples/Drawing/index.js
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* globals Y, d3 */
|
||||||
|
'strict mode'
|
||||||
|
|
||||||
|
Y({
|
||||||
|
db: {
|
||||||
|
name: 'memory'
|
||||||
|
},
|
||||||
|
connector: {
|
||||||
|
name: 'websockets-client',
|
||||||
|
room: 'drawing-example'
|
||||||
|
// url: 'localhost:1234'
|
||||||
|
},
|
||||||
|
sourceDir: '/bower_components',
|
||||||
|
share: {
|
||||||
|
drawing: 'Array'
|
||||||
|
}
|
||||||
|
}).then(function (y) {
|
||||||
|
window.yDrawing = y
|
||||||
|
var drawing = y.share.drawing
|
||||||
|
var renderPath = d3.svg.line()
|
||||||
|
.x(function (d) { return d[0] })
|
||||||
|
.y(function (d) { return d[1] })
|
||||||
|
.interpolate('basis')
|
||||||
|
|
||||||
|
var svg = d3.select('#drawingCanvas')
|
||||||
|
.call(d3.behavior.drag()
|
||||||
|
.on('dragstart', dragstart)
|
||||||
|
.on('drag', drag)
|
||||||
|
.on('dragend', dragend))
|
||||||
|
|
||||||
|
// create line from a shared array object and update the line when the array changes
|
||||||
|
function drawLine (yarray) {
|
||||||
|
var line = svg.append('path').datum(yarray.toArray())
|
||||||
|
line.attr('d', renderPath)
|
||||||
|
yarray.observe(function (event) {
|
||||||
|
// we only implement insert events that are appended to the end of the array
|
||||||
|
event.values.forEach(function (value) {
|
||||||
|
line.datum().push(value)
|
||||||
|
})
|
||||||
|
line.attr('d', renderPath)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// call drawLine every time an array is appended
|
||||||
|
y.share.drawing.observe(function (event) {
|
||||||
|
if (event.type === 'insert') {
|
||||||
|
event.values().then(function (values) {
|
||||||
|
values.forEach(drawLine)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// just remove all elements (thats what we do anyway)
|
||||||
|
svg.selectAll('path').remove()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// draw all existing content
|
||||||
|
for (var i = 0; i < drawing.length; i++) {
|
||||||
|
drawing.get(i).then(drawLine)
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear canvas on request
|
||||||
|
document.querySelector('#clearDrawingCanvas').onclick = function () {
|
||||||
|
drawing.delete(0, drawing.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sharedLine = null
|
||||||
|
function dragstart () {
|
||||||
|
drawing.insert(drawing.length, [Y.Array])
|
||||||
|
drawing.get(drawing.length - 1).then(function (array) {
|
||||||
|
sharedLine = array
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// After one dragged event is recognized, we ignore them for 33ms.
|
||||||
|
var ignoreDrag = null
|
||||||
|
function drag () {
|
||||||
|
if (sharedLine != null && ignoreDrag == null) {
|
||||||
|
ignoreDrag = window.setTimeout(function () {
|
||||||
|
ignoreDrag = null
|
||||||
|
}, 33)
|
||||||
|
sharedLine.push([d3.mouse(this)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragend () {
|
||||||
|
sharedLine = null
|
||||||
|
window.clearTimeout(ignoreDrag)
|
||||||
|
ignoreDrag = null
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -2,142 +2,24 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="../bower_components/quill/dist/quill.snow.css" />
|
<link rel="stylesheet" href="../bower_components/quill/dist/quill.snow.css" />
|
||||||
|
<link href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css" rel="stylesheet">
|
||||||
|
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/monokai-sublime.min.css" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
#quill {
|
#quill-container {
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
box-shadow: 0px 0px 10px gray;
|
box-shadow: 0px 0px 10px gray;
|
||||||
}
|
}
|
||||||
#toolbar {
|
|
||||||
border-bottom: 1px solid gray;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="quill">
|
<div id="quill-container">
|
||||||
<!-- Create the toolbar container -->
|
<div id="quill">
|
||||||
<div id="toolbar" class="toolbar">
|
|
||||||
<span class="ql-format-group">
|
|
||||||
<select title="Font" class="ql-font">
|
|
||||||
<option value="sans-serif" selected="">Sans Serif</option>
|
|
||||||
<option value="serif">Serif</option>
|
|
||||||
<option value="monospace">Monospace</option>
|
|
||||||
</select>
|
|
||||||
<select title="Size" class="ql-size">
|
|
||||||
<option value="10px">Small</option>
|
|
||||||
<option value="13px" selected="">Normal</option>
|
|
||||||
<option value="18px">Large</option>
|
|
||||||
<option value="32px">Huge</option>
|
|
||||||
</select>
|
|
||||||
</span>
|
|
||||||
<span class="ql-format-group">
|
|
||||||
<span title="Bold" class="ql-format-button ql-bold"></span>
|
|
||||||
<span class="ql-format-separator"></span>
|
|
||||||
<span title="Italic" class="ql-format-button ql-italic"></span>
|
|
||||||
<span class="ql-format-separator"></span>
|
|
||||||
<span title="Underline" class="ql-format-button ql-underline"></span>
|
|
||||||
<span class="ql-format-separator"></span>
|
|
||||||
<span title="Strikethrough" class="ql-format-button ql-strike"></span>
|
|
||||||
</span>
|
|
||||||
<span class="ql-format-group">
|
|
||||||
<select title="Text Color" class="ql-color">
|
|
||||||
<option value="rgb(0, 0, 0)" label="rgb(0, 0, 0)" selected=""></option>
|
|
||||||
<option value="rgb(230, 0, 0)" label="rgb(230, 0, 0)"></option>
|
|
||||||
<option value="rgb(255, 153, 0)" label="rgb(255, 153, 0)"></option>
|
|
||||||
<option value="rgb(255, 255, 0)" label="rgb(255, 255, 0)"></option>
|
|
||||||
<option value="rgb(0, 138, 0)" label="rgb(0, 138, 0)"></option>
|
|
||||||
<option value="rgb(0, 102, 204)" label="rgb(0, 102, 204)"></option>
|
|
||||||
<option value="rgb(153, 51, 255)" label="rgb(153, 51, 255)"></option>
|
|
||||||
<option value="rgb(255, 255, 255)" label="rgb(255, 255, 255)"></option>
|
|
||||||
<option value="rgb(250, 204, 204)" label="rgb(250, 204, 204)"></option>
|
|
||||||
<option value="rgb(255, 235, 204)" label="rgb(255, 235, 204)"></option>
|
|
||||||
<option value="rgb(255, 255, 204)" label="rgb(255, 255, 204)"></option>
|
|
||||||
<option value="rgb(204, 232, 204)" label="rgb(204, 232, 204)"></option>
|
|
||||||
<option value="rgb(204, 224, 245)" label="rgb(204, 224, 245)"></option>
|
|
||||||
<option value="rgb(235, 214, 255)" label="rgb(235, 214, 255)"></option>
|
|
||||||
<option value="rgb(187, 187, 187)" label="rgb(187, 187, 187)"></option>
|
|
||||||
<option value="rgb(240, 102, 102)" label="rgb(240, 102, 102)"></option>
|
|
||||||
<option value="rgb(255, 194, 102)" label="rgb(255, 194, 102)"></option>
|
|
||||||
<option value="rgb(255, 255, 102)" label="rgb(255, 255, 102)"></option>
|
|
||||||
<option value="rgb(102, 185, 102)" label="rgb(102, 185, 102)"></option>
|
|
||||||
<option value="rgb(102, 163, 224)" label="rgb(102, 163, 224)"></option>
|
|
||||||
<option value="rgb(194, 133, 255)" label="rgb(194, 133, 255)"></option>
|
|
||||||
<option value="rgb(136, 136, 136)" label="rgb(136, 136, 136)"></option>
|
|
||||||
<option value="rgb(161, 0, 0)" label="rgb(161, 0, 0)"></option>
|
|
||||||
<option value="rgb(178, 107, 0)" label="rgb(178, 107, 0)"></option>
|
|
||||||
<option value="rgb(178, 178, 0)" label="rgb(178, 178, 0)"></option>
|
|
||||||
<option value="rgb(0, 97, 0)" label="rgb(0, 97, 0)"></option>
|
|
||||||
<option value="rgb(0, 71, 178)" label="rgb(0, 71, 178)"></option>
|
|
||||||
<option value="rgb(107, 36, 178)" label="rgb(107, 36, 178)"></option>
|
|
||||||
<option value="rgb(68, 68, 68)" label="rgb(68, 68, 68)"></option>
|
|
||||||
<option value="rgb(92, 0, 0)" label="rgb(92, 0, 0)"></option>
|
|
||||||
<option value="rgb(102, 61, 0)" label="rgb(102, 61, 0)"></option>
|
|
||||||
<option value="rgb(102, 102, 0)" label="rgb(102, 102, 0)"></option>
|
|
||||||
<option value="rgb(0, 55, 0)" label="rgb(0, 55, 0)"></option>
|
|
||||||
<option value="rgb(0, 41, 102)" label="rgb(0, 41, 102)"></option>
|
|
||||||
<option value="rgb(61, 20, 102)" label="rgb(61, 20, 102)"></option>
|
|
||||||
</select>
|
|
||||||
<span class="ql-format-separator"></span>
|
|
||||||
<select title="Background Color" class="ql-background">
|
|
||||||
<option value="rgb(0, 0, 0)" label="rgb(0, 0, 0)"></option>
|
|
||||||
<option value="rgb(230, 0, 0)" label="rgb(230, 0, 0)"></option>
|
|
||||||
<option value="rgb(255, 153, 0)" label="rgb(255, 153, 0)"></option>
|
|
||||||
<option value="rgb(255, 255, 0)" label="rgb(255, 255, 0)"></option>
|
|
||||||
<option value="rgb(0, 138, 0)" label="rgb(0, 138, 0)"></option>
|
|
||||||
<option value="rgb(0, 102, 204)" label="rgb(0, 102, 204)"></option>
|
|
||||||
<option value="rgb(153, 51, 255)" label="rgb(153, 51, 255)"></option>
|
|
||||||
<option value="rgb(255, 255, 255)" label="rgb(255, 255, 255)" selected=""></option>
|
|
||||||
<option value="rgb(250, 204, 204)" label="rgb(250, 204, 204)"></option>
|
|
||||||
<option value="rgb(255, 235, 204)" label="rgb(255, 235, 204)"></option>
|
|
||||||
<option value="rgb(255, 255, 204)" label="rgb(255, 255, 204)"></option>
|
|
||||||
<option value="rgb(204, 232, 204)" label="rgb(204, 232, 204)"></option>
|
|
||||||
<option value="rgb(204, 224, 245)" label="rgb(204, 224, 245)"></option>
|
|
||||||
<option value="rgb(235, 214, 255)" label="rgb(235, 214, 255)"></option>
|
|
||||||
<option value="rgb(187, 187, 187)" label="rgb(187, 187, 187)"></option>
|
|
||||||
<option value="rgb(240, 102, 102)" label="rgb(240, 102, 102)"></option>
|
|
||||||
<option value="rgb(255, 194, 102)" label="rgb(255, 194, 102)"></option>
|
|
||||||
<option value="rgb(255, 255, 102)" label="rgb(255, 255, 102)"></option>
|
|
||||||
<option value="rgb(102, 185, 102)" label="rgb(102, 185, 102)"></option>
|
|
||||||
<option value="rgb(102, 163, 224)" label="rgb(102, 163, 224)"></option>
|
|
||||||
<option value="rgb(194, 133, 255)" label="rgb(194, 133, 255)"></option>
|
|
||||||
<option value="rgb(136, 136, 136)" label="rgb(136, 136, 136)"></option>
|
|
||||||
<option value="rgb(161, 0, 0)" label="rgb(161, 0, 0)"></option>
|
|
||||||
<option value="rgb(178, 107, 0)" label="rgb(178, 107, 0)"></option>
|
|
||||||
<option value="rgb(178, 178, 0)" label="rgb(178, 178, 0)"></option>
|
|
||||||
<option value="rgb(0, 97, 0)" label="rgb(0, 97, 0)"></option>
|
|
||||||
<option value="rgb(0, 71, 178)" label="rgb(0, 71, 178)"></option>
|
|
||||||
<option value="rgb(107, 36, 178)" label="rgb(107, 36, 178)"></option>
|
|
||||||
<option value="rgb(68, 68, 68)" label="rgb(68, 68, 68)"></option>
|
|
||||||
<option value="rgb(92, 0, 0)" label="rgb(92, 0, 0)"></option>
|
|
||||||
<option value="rgb(102, 61, 0)" label="rgb(102, 61, 0)"></option>
|
|
||||||
<option value="rgb(102, 102, 0)" label="rgb(102, 102, 0)"></option>
|
|
||||||
<option value="rgb(0, 55, 0)" label="rgb(0, 55, 0)"></option>
|
|
||||||
<option value="rgb(0, 41, 102)" label="rgb(0, 41, 102)"></option>
|
|
||||||
<option value="rgb(61, 20, 102)" label="rgb(61, 20, 102)"></option>
|
|
||||||
</select>
|
|
||||||
</span>
|
|
||||||
<span class="ql-format-group">
|
|
||||||
<span title="List" class="ql-format-button ql-list"></span>
|
|
||||||
<span class="ql-format-separator"></span>
|
|
||||||
<span title="Bullet" class="ql-format-button ql-bullet"></span>
|
|
||||||
<span class="ql-format-separator"></span>
|
|
||||||
<select title="Text Alignment" class="ql-align">
|
|
||||||
<option value="left" label="Left" selected=""></option>
|
|
||||||
<option value="center" label="Center"></option>
|
|
||||||
<option value="right" label="Right"></option>
|
|
||||||
<option value="justify" label="Justify"></option>
|
|
||||||
</select>
|
|
||||||
</span>
|
|
||||||
<span class="ql-format-group">
|
|
||||||
<span title="Link" class="ql-format-button ql-link"></span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Create the editor container -->
|
|
||||||
<div id="editor">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Include the Quill library -->
|
<!-- Include the Quill library -->
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.js" type="text/javascript"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/highlight.min.js" type="text/javascript"></script>
|
||||||
<script src="../bower_components/quill/dist/quill.js"></script>
|
<script src="../bower_components/quill/dist/quill.js"></script>
|
||||||
<script src="../bower_components/yjs/y.es6"></script>
|
<script src="../bower_components/yjs/y.es6"></script>
|
||||||
<script src="./index.js"></script>
|
<script src="./index.js"></script>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ Y({
|
|||||||
name: 'memory'
|
name: 'memory'
|
||||||
},
|
},
|
||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client',
|
name: 'webrtc',
|
||||||
room: 'richtext-example'
|
room: 'richtext-example-quill-beta'
|
||||||
},
|
},
|
||||||
sourceDir: '/bower_components',
|
sourceDir: '/bower_components',
|
||||||
share: {
|
share: {
|
||||||
@@ -18,13 +18,22 @@ Y({
|
|||||||
window.yQuill = y
|
window.yQuill = y
|
||||||
|
|
||||||
// create quill element
|
// create quill element
|
||||||
window.quill = new Quill('#editor', {
|
window.quill = new Quill('#quill', {
|
||||||
modules: {
|
modules: {
|
||||||
'toolbar': { container: '#toolbar' },
|
formula: true,
|
||||||
'link-tooltip': true
|
syntax: true,
|
||||||
|
toolbar: [
|
||||||
|
[{ size: ['small', false, 'large', 'huge'] }],
|
||||||
|
['bold', 'italic', 'underline'],
|
||||||
|
[{ color: [] }, { background: [] }], // Snow theme fills in values
|
||||||
|
[{ script: 'sub' }, { script: 'super' }],
|
||||||
|
['link', 'image'],
|
||||||
|
['link', 'code-block'],
|
||||||
|
[{list: 'ordered' }]
|
||||||
|
]
|
||||||
},
|
},
|
||||||
theme: 'snow'
|
theme: 'snow'
|
||||||
})
|
});
|
||||||
// bind quill to richtext type
|
// bind quill to richtext type
|
||||||
y.share.richtext.bind(window.quill)
|
y.share.richtext.bind(window.quill)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"quill": "~0.20.1",
|
"quill": "~0.20.1",
|
||||||
"ace": "~1.2.3",
|
"ace": "~1.2.3",
|
||||||
"ace-builds": "~1.2.3",
|
"ace-builds": "~1.2.3",
|
||||||
"jquery": "~2.2.2"
|
"jquery": "~2.2.2",
|
||||||
|
"d3": "^3.5.16"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "11.0.3",
|
"version": "11.2.4",
|
||||||
"homepage": "y-js.org",
|
"homepage": "y-js.org",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
||||||
|
|||||||
488
y.es6
488
y.es6
@@ -421,7 +421,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
module.exports = function (Y) {
|
module.exports = function (Y) {
|
||||||
var globalRoom = {
|
var globalRoom = {
|
||||||
users: {},
|
users: {},
|
||||||
buffers: {}, // TODO: reimplement this idea. This does not cover all cases!! Here, you have a queue which is unrealistic (i.e. think about multiple incoming connections)
|
buffers: {},
|
||||||
removeUser: function (user) {
|
removeUser: function (user) {
|
||||||
for (var i in this.users) {
|
for (var i in this.users) {
|
||||||
this.users[i].userLeft(user)
|
this.users[i].userLeft(user)
|
||||||
@@ -498,7 +498,7 @@ module.exports = function (Y) {
|
|||||||
} else {
|
} else {
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
}, 10)
|
}, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
globalRoom.whenTransactionsFinished().then(nextFlush)
|
globalRoom.whenTransactionsFinished().then(nextFlush)
|
||||||
@@ -659,7 +659,7 @@ module.exports = function (Y /* :any */) {
|
|||||||
}
|
}
|
||||||
this.gc1 = [] // first stage
|
this.gc1 = [] // first stage
|
||||||
this.gc2 = [] // second stage -> after that, remove the op
|
this.gc2 = [] // second stage -> after that, remove the op
|
||||||
this.gcTimeout = !opts.gcTimeout ? 50000 : opts.gcTimeoutś
|
this.gcTimeout = !opts.gcTimeout ? 50000 : opts.gcTimeouts
|
||||||
function garbageCollect () {
|
function garbageCollect () {
|
||||||
return os.whenTransactionsFinished().then(function () {
|
return os.whenTransactionsFinished().then(function () {
|
||||||
if (os.gc1.length > 0 || os.gc2.length > 0) {
|
if (os.gc1.length > 0 || os.gc2.length > 0) {
|
||||||
@@ -951,68 +951,89 @@ module.exports = function (Y /* :any */) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (defined == null) {
|
if (defined == null) {
|
||||||
var isGarbageCollected = yield* this.isGarbageCollected(op.id)
|
var opid = op.id
|
||||||
|
var isGarbageCollected = yield* this.isGarbageCollected(opid)
|
||||||
if (!isGarbageCollected) {
|
if (!isGarbageCollected) {
|
||||||
|
// TODO: reduce number of get / put calls for op ..
|
||||||
yield* Y.Struct[op.struct].execute.call(this, op)
|
yield* Y.Struct[op.struct].execute.call(this, op)
|
||||||
yield* this.addOperation(op)
|
yield* this.addOperation(op)
|
||||||
yield* this.store.operationAdded(this, op)
|
yield* this.store.operationAdded(this, op)
|
||||||
|
// operationAdded can change op..
|
||||||
|
op = yield* this.getOperation(opid)
|
||||||
// if insertion, try to combine with left
|
// if insertion, try to combine with left
|
||||||
yield* this.tryCombineWithLeft(op)
|
yield* this.tryCombineWithLeft(op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// called by a transaction when an operation is added
|
/*
|
||||||
|
* Called by a transaction when an operation is added.
|
||||||
|
* This function is especially important for y-indexeddb, where several instances may share a single database.
|
||||||
|
* Every time an operation is created by one instance, it is send to all other instances and operationAdded is called
|
||||||
|
*
|
||||||
|
* If it's not a Delete operation:
|
||||||
|
* * Checks if another operation is executable (listenersById)
|
||||||
|
* * Update state, if possible
|
||||||
|
*
|
||||||
|
* Always:
|
||||||
|
* * Call type
|
||||||
|
*/
|
||||||
* operationAdded (transaction, op) {
|
* operationAdded (transaction, op) {
|
||||||
// increase SS
|
if (op.struct === 'Delete') {
|
||||||
yield* transaction.updateState(op.id[0])
|
var target = yield* transaction.getInsertion(op.target)
|
||||||
|
var type = this.initializedTypes[JSON.stringify(target.parent)]
|
||||||
var opLen = op.content != null ? op.content.length : 1
|
if (type != null) {
|
||||||
for (let i = 0; i < opLen; i++) {
|
yield* type._changed(transaction, op)
|
||||||
// notify whenOperation listeners (by id)
|
}
|
||||||
var sid = JSON.stringify([op.id[0], op.id[1] + i])
|
} else {
|
||||||
var l = this.listenersById[sid]
|
// increase SS
|
||||||
delete this.listenersById[sid]
|
yield* transaction.updateState(op.id[0])
|
||||||
|
var opLen = op.content != null ? op.content.length : 1
|
||||||
if (l != null) {
|
for (let i = 0; i < opLen; i++) {
|
||||||
for (var key in l) {
|
// notify whenOperation listeners (by id)
|
||||||
var listener = l[key]
|
var sid = JSON.stringify([op.id[0], op.id[1] + i])
|
||||||
if (--listener.missing === 0) {
|
var l = this.listenersById[sid]
|
||||||
this.whenOperationsExist([], listener.op)
|
delete this.listenersById[sid]
|
||||||
|
if (l != null) {
|
||||||
|
for (var key in l) {
|
||||||
|
var listener = l[key]
|
||||||
|
if (--listener.missing === 0) {
|
||||||
|
this.whenOperationsExist([], listener.op)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
var t = this.initializedTypes[JSON.stringify(op.parent)]
|
||||||
var t = this.initializedTypes[JSON.stringify(op.parent)]
|
|
||||||
|
|
||||||
// if parent is deleted, mark as gc'd and return
|
// if parent is deleted, mark as gc'd and return
|
||||||
if (op.parent != null) {
|
if (op.parent != null) {
|
||||||
var parentIsDeleted = yield* transaction.isDeleted(op.parent)
|
var parentIsDeleted = yield* transaction.isDeleted(op.parent)
|
||||||
if (parentIsDeleted) {
|
if (parentIsDeleted) {
|
||||||
yield* transaction.deleteList(op.id)
|
yield* transaction.deleteList(op.id)
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
||||||
let o = Y.utils.copyObject(op)
|
let o = Y.utils.copyOperation(op)
|
||||||
yield* t._changed(transaction, o)
|
yield* t._changed(transaction, o)
|
||||||
}
|
}
|
||||||
if (!op.deleted) {
|
if (!op.deleted) {
|
||||||
// Delete if DS says this is actually deleted
|
// Delete if DS says this is actually deleted
|
||||||
var len = op.content != null ? op.content.length : 1
|
var len = op.content != null ? op.content.length : 1
|
||||||
var startId = op.id // You must not use op.id in the following loop, because op will change when deleted
|
var startId = op.id // You must not use op.id in the following loop, because op will change when deleted
|
||||||
for (let i = 0; i < len; i++) {
|
// TODO: !! console.log('TODO: change this before commiting')
|
||||||
var id = [startId[0], startId[1] + i]
|
for (let i = 0; i < len; i++) {
|
||||||
var opIsDeleted = yield* transaction.isDeleted(id)
|
var id = [startId[0], startId[1] + i]
|
||||||
if (opIsDeleted) {
|
var opIsDeleted = yield* transaction.isDeleted(id)
|
||||||
var delop = {
|
if (opIsDeleted) {
|
||||||
struct: 'Delete',
|
var delop = {
|
||||||
target: id
|
struct: 'Delete',
|
||||||
|
target: id
|
||||||
|
}
|
||||||
|
yield* this.tryExecute.call(transaction, delop)
|
||||||
}
|
}
|
||||||
yield* this.tryExecute.call(transaction, delop)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1063,14 +1084,9 @@ module.exports = function (Y /* :any */) {
|
|||||||
this.waitingTransactions.push(makeGen)
|
this.waitingTransactions.push(makeGen)
|
||||||
if (!this.transactionInProgress) {
|
if (!this.transactionInProgress) {
|
||||||
this.transactionInProgress = true
|
this.transactionInProgress = true
|
||||||
if (false || callImmediately) { // TODO: decide whether this is ok or not..
|
setTimeout(() => {
|
||||||
this.transact(this.getNextRequest())
|
this.transact(this.getNextRequest())
|
||||||
} else {
|
}, 0)
|
||||||
var self = this
|
|
||||||
setTimeout(function () {
|
|
||||||
self.transact(self.getNextRequest())
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1746,14 +1762,11 @@ module.exports = function (Y/* :any */) {
|
|||||||
right = null
|
right = null
|
||||||
}
|
}
|
||||||
if (callType && !preventCallType) {
|
if (callType && !preventCallType) {
|
||||||
var type = this.store.initializedTypes[JSON.stringify(target.parent)]
|
yield* this.store.operationAdded(this, {
|
||||||
if (type != null) {
|
struct: 'Delete',
|
||||||
yield* type._changed(this, {
|
target: target.id,
|
||||||
struct: 'Delete',
|
length: targetLength
|
||||||
target: target.id,
|
})
|
||||||
length: targetLength
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// need to gc in the end!
|
// need to gc in the end!
|
||||||
yield* this.store.addToGarbageCollector.call(this, target, left)
|
yield* this.store.addToGarbageCollector.call(this, target, left)
|
||||||
@@ -1997,6 +2010,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
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)
|
||||||
|
|
||||||
if (o.originOf != null && o.originOf.length > 0) {
|
if (o.originOf != null && o.originOf.length > 0) {
|
||||||
// find new origin of right ops
|
// find new origin of right ops
|
||||||
@@ -2063,10 +2077,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
// we don't need to set right here, because
|
// we don't need to set right here, because
|
||||||
// right should be in o.originOf => it is set it the previous for loop
|
// right should be in o.originOf => it is set it the previous for loop
|
||||||
} else {
|
|
||||||
// we didn't need to reset the origin of right
|
|
||||||
// so we have to set right here
|
|
||||||
yield* this.setOperation(right)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// o may originate in another operation.
|
// o may originate in another operation.
|
||||||
@@ -2560,7 +2570,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
/* this is what we used before.. use this as a reference..
|
/* this is what we used before.. use this as a reference..
|
||||||
* makeOperationReady (startSS, op) {
|
* makeOperationReady (startSS, op) {
|
||||||
op = Y.Struct[op.struct].encode(op)
|
op = Y.Struct[op.struct].encode(op)
|
||||||
op = Y.utils.copyObject(op)
|
op = Y.utils.copyObject(op) -- use copyoperation instead now!
|
||||||
var o = op
|
var o = op
|
||||||
var ids = [op.id]
|
var ids = [op.id]
|
||||||
// search for the new op.right
|
// search for the new op.right
|
||||||
@@ -2686,6 +2696,153 @@ module.exports = function (Y /* : any*/) {
|
|||||||
receivedOp (op) {
|
receivedOp (op) {
|
||||||
if (this.awaiting <= 0) {
|
if (this.awaiting <= 0) {
|
||||||
this.onevent(op)
|
this.onevent(op)
|
||||||
|
} else if (op.struct === 'Delete') {
|
||||||
|
var self = this
|
||||||
|
var checkDelete = function checkDelete (d) {
|
||||||
|
if (d.length == null) {
|
||||||
|
throw new Error('This shouldn\'t happen! d.length must be defined!')
|
||||||
|
}
|
||||||
|
// we check if o deletes something in self.waiting
|
||||||
|
// if so, we remove the deleted operation
|
||||||
|
for (var w = 0; w < self.waiting.length; w++) {
|
||||||
|
var i = self.waiting[w]
|
||||||
|
if (i.struct === 'Insert' && i.id[0] === d.target[0]) {
|
||||||
|
var iLength = i.hasOwnProperty('content') ? i.content.length : 1
|
||||||
|
var dStart = d.target[1]
|
||||||
|
var dEnd = d.target[1] + (d.length || 1)
|
||||||
|
var iStart = i.id[1]
|
||||||
|
var iEnd = i.id[1] + iLength
|
||||||
|
// Check if they don't overlap
|
||||||
|
if (iEnd <= dStart || dEnd <= iStart) {
|
||||||
|
// no overlapping
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// we check all overlapping cases. All cases:
|
||||||
|
/*
|
||||||
|
1) iiiii
|
||||||
|
ddddd
|
||||||
|
--> modify i and d
|
||||||
|
2) iiiiiii
|
||||||
|
ddddd
|
||||||
|
--> modify i, remove d
|
||||||
|
3) iiiiiii
|
||||||
|
ddd
|
||||||
|
--> remove d, modify i, and create another i (for the right hand side)
|
||||||
|
4) iiiii
|
||||||
|
ddddddd
|
||||||
|
--> remove i, modify d
|
||||||
|
5) iiiiiii
|
||||||
|
ddddddd
|
||||||
|
--> remove both i and d (**)
|
||||||
|
6) iiiiiii
|
||||||
|
ddddd
|
||||||
|
--> modify i, remove d
|
||||||
|
7) iii
|
||||||
|
ddddddd
|
||||||
|
--> remove i, create and apply two d with checkDelete(d) (**)
|
||||||
|
8) iiiii
|
||||||
|
ddddddd
|
||||||
|
--> remove i, modify d (**)
|
||||||
|
9) iiiii
|
||||||
|
ddddd
|
||||||
|
--> modify i and d
|
||||||
|
(**) (also check if i contains content or type)
|
||||||
|
*/
|
||||||
|
// TODO: I left some debugger statements, because I want to debug all cases once in production. REMEMBER END TODO
|
||||||
|
if (iStart < dStart) {
|
||||||
|
if (dStart < iEnd) {
|
||||||
|
if (iEnd < dEnd) {
|
||||||
|
// Case 1
|
||||||
|
// remove the right part of i's content
|
||||||
|
i.content.splice(dStart - iStart)
|
||||||
|
// remove the start of d's deletion
|
||||||
|
d.length = dEnd - iEnd
|
||||||
|
d.target = [d.target[0], iEnd]
|
||||||
|
continue
|
||||||
|
} else if (iEnd === dEnd) {
|
||||||
|
// Case 2
|
||||||
|
i.content.splice(dStart - iStart)
|
||||||
|
// remove d, we do that by simply ending this function
|
||||||
|
return
|
||||||
|
} else { // (dEnd < iEnd)
|
||||||
|
// Case 3
|
||||||
|
var newI = {
|
||||||
|
id: [i.id[0], dEnd],
|
||||||
|
content: i.content.slice(dEnd - iStart),
|
||||||
|
struct: 'Insert'
|
||||||
|
}
|
||||||
|
self.waiting.push(newI)
|
||||||
|
i.content.splice(dStart - iStart)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (dStart === iStart) {
|
||||||
|
if (iEnd < dEnd) {
|
||||||
|
// Case 4
|
||||||
|
d.length = dEnd - iEnd
|
||||||
|
d.target = [d.target[0], iEnd]
|
||||||
|
i.content = []
|
||||||
|
continue
|
||||||
|
} else if (iEnd === dEnd) {
|
||||||
|
// Case 5
|
||||||
|
self.waiting.splice(w, 1)
|
||||||
|
return
|
||||||
|
} else { // (dEnd < iEnd)
|
||||||
|
// Case 6
|
||||||
|
i.content = i.content.slice(dEnd - iStart)
|
||||||
|
i.id = [i.id[0], dEnd]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else { // (dStart < iStart)
|
||||||
|
if (iStart < dEnd) {
|
||||||
|
// they overlap
|
||||||
|
/*
|
||||||
|
7) iii
|
||||||
|
ddddddd
|
||||||
|
--> remove i, create and apply two d with checkDelete(d) (**)
|
||||||
|
8) iiiii
|
||||||
|
ddddddd
|
||||||
|
--> remove i, modify d (**)
|
||||||
|
9) iiiii
|
||||||
|
ddddd
|
||||||
|
--> modify i and d
|
||||||
|
*/
|
||||||
|
if (iEnd < dEnd) {
|
||||||
|
// Case 7
|
||||||
|
// debugger // TODO: You did not test this case yet!!!! (add the debugger here)
|
||||||
|
self.waiting.splice(w, 1)
|
||||||
|
checkDelete({
|
||||||
|
target: [d.target[0], dStart],
|
||||||
|
length: iStart - dStart,
|
||||||
|
struct: 'Delete'
|
||||||
|
})
|
||||||
|
checkDelete({
|
||||||
|
target: [d.target[0], iEnd],
|
||||||
|
length: iEnd - dEnd,
|
||||||
|
struct: 'Delete'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
} else if (iEnd === dEnd) {
|
||||||
|
// Case 8
|
||||||
|
self.waiting.splice(w, 1)
|
||||||
|
w--
|
||||||
|
d.length -= iLength
|
||||||
|
continue
|
||||||
|
} else { // dEnd < iEnd
|
||||||
|
// Case 9
|
||||||
|
d.length = iStart - dStart
|
||||||
|
i.content.splice(0, dEnd - iStart)
|
||||||
|
i.id = [i.id[0], dEnd]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// finished with remaining operations
|
||||||
|
self.waiting.push(d)
|
||||||
|
}
|
||||||
|
checkDelete(op)
|
||||||
} else {
|
} else {
|
||||||
this.waiting.push(op)
|
this.waiting.push(op)
|
||||||
}
|
}
|
||||||
@@ -2696,9 +2853,106 @@ module.exports = function (Y /* : any*/) {
|
|||||||
prematurely called operations are executed
|
prematurely called operations are executed
|
||||||
*/
|
*/
|
||||||
awaitAndPrematurelyCall (ops) {
|
awaitAndPrematurelyCall (ops) {
|
||||||
this.awaiting += ops.length
|
this.awaiting++
|
||||||
ops.forEach(this.onevent)
|
ops.map(Y.utils.copyOperation).forEach(this.onevent)
|
||||||
}
|
}
|
||||||
|
* awaitOps (transaction, f, args) {
|
||||||
|
function notSoSmartSort (array) {
|
||||||
|
// this function sorts insertions in a executable order
|
||||||
|
var result = []
|
||||||
|
while (array.length > 0) {
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
var independent = true
|
||||||
|
for (var j = 0; j < array.length; j++) {
|
||||||
|
if (Y.utils.matchesId(array[j], array[i].left)) {
|
||||||
|
// array[i] depends on array[j]
|
||||||
|
independent = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (independent) {
|
||||||
|
result.push(array.splice(i, 1)[0])
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
var before = this.waiting.length
|
||||||
|
// somehow create new operations
|
||||||
|
yield* f.apply(transaction, args)
|
||||||
|
// remove all appended ops / awaited ops
|
||||||
|
this.waiting.splice(before)
|
||||||
|
if (this.awaiting > 0) this.awaiting--
|
||||||
|
// if there are no awaited ops anymore, we can update all waiting ops, and send execute them (if there are still no awaited ops)
|
||||||
|
if (this.awaiting === 0 && this.waiting.length > 0) {
|
||||||
|
// update all waiting ops
|
||||||
|
for (let i = 0; i < this.waiting.length; i++) {
|
||||||
|
var o = this.waiting[i]
|
||||||
|
if (o.struct === 'Insert') {
|
||||||
|
var _o = yield* transaction.getInsertion(o.id)
|
||||||
|
if (!Y.utils.compareIds(_o.id, o.id)) {
|
||||||
|
// o got extended
|
||||||
|
o.left = [o.id[0], o.id[1] - 1]
|
||||||
|
} else if (_o.left == null) {
|
||||||
|
o.left = null
|
||||||
|
} else {
|
||||||
|
// find next undeleted op
|
||||||
|
var left = yield* transaction.getInsertion(_o.left)
|
||||||
|
while (left.deleted != null) {
|
||||||
|
if (left.left != null) {
|
||||||
|
left = yield* transaction.getInsertion(left.left)
|
||||||
|
} else {
|
||||||
|
left = null
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o.left = left != null ? Y.utils.getLastId(left) : null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// the previous stuff was async, so we have to check again!
|
||||||
|
// We also pull changes from the bindings, if there exists such a method, this could increase awaiting too
|
||||||
|
if (this._pullChanges != null) {
|
||||||
|
this._pullChanges()
|
||||||
|
}
|
||||||
|
if (this.awaiting === 0) {
|
||||||
|
// sort by type, execute inserts first
|
||||||
|
var ins = []
|
||||||
|
var dels = []
|
||||||
|
this.waiting.forEach(function (o) {
|
||||||
|
if (o.struct === 'Delete') {
|
||||||
|
dels.push(o)
|
||||||
|
} else {
|
||||||
|
ins.push(o)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.waiting = []
|
||||||
|
// put in executable order
|
||||||
|
ins = notSoSmartSort(ins)
|
||||||
|
// this.onevent can trigger the creation of another operation
|
||||||
|
// -> check if this.awaiting increased & stop computation if it does
|
||||||
|
for (var i = 0; i < ins.length; i++) {
|
||||||
|
if (this.awaiting === 0) {
|
||||||
|
this.onevent(ins[i])
|
||||||
|
} else {
|
||||||
|
this.waiting = this.waiting.concat(ins.slice(i))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < dels.length; i++) {
|
||||||
|
if (this.awaiting === 0) {
|
||||||
|
this.onevent(dels[i])
|
||||||
|
} else {
|
||||||
|
this.waiting = this.waiting.concat(dels.slice(i))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Remove awaitedInserts and awaitedDeletes in favor of awaitedOps, as they are deprecated and do not always work
|
||||||
|
// Do this in one of the coming releases that are breaking anyway
|
||||||
/*
|
/*
|
||||||
Call this when you successfully awaited the execution of n Insert operations
|
Call this when you successfully awaited the execution of n Insert operations
|
||||||
*/
|
*/
|
||||||
@@ -2756,12 +3010,42 @@ module.exports = function (Y /* : any*/) {
|
|||||||
/* (private)
|
/* (private)
|
||||||
Try to execute the events for the waiting operations
|
Try to execute the events for the waiting operations
|
||||||
*/
|
*/
|
||||||
_tryCallEvents (n) {
|
_tryCallEvents () {
|
||||||
this.awaiting -= n
|
function notSoSmartSort (array) {
|
||||||
|
var result = []
|
||||||
|
while (array.length > 0) {
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
var independent = true
|
||||||
|
for (var j = 0; j < array.length; j++) {
|
||||||
|
if (Y.utils.matchesId(array[j], array[i].left)) {
|
||||||
|
// array[i] depends on array[j]
|
||||||
|
independent = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (independent) {
|
||||||
|
result.push(array.splice(i, 1)[0])
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
if (this.awaiting > 0) this.awaiting--
|
||||||
if (this.awaiting === 0 && this.waiting.length > 0) {
|
if (this.awaiting === 0 && this.waiting.length > 0) {
|
||||||
var ops = this.waiting
|
var ins = []
|
||||||
|
var dels = []
|
||||||
|
this.waiting.forEach(function (o) {
|
||||||
|
if (o.struct === 'Delete') {
|
||||||
|
dels.push(o)
|
||||||
|
} else {
|
||||||
|
ins.push(o)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ins = notSoSmartSort(ins)
|
||||||
|
ins.forEach(this.onevent)
|
||||||
|
dels.forEach(this.onevent)
|
||||||
this.waiting = []
|
this.waiting = []
|
||||||
ops.forEach(this.onevent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2830,6 +3114,20 @@ module.exports = function (Y /* : any*/) {
|
|||||||
}
|
}
|
||||||
Y.utils.copyObject = copyObject
|
Y.utils.copyObject = copyObject
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copy an operation, so that it can be manipulated.
|
||||||
|
Note: You must not change subproperties (except o.content)!
|
||||||
|
*/
|
||||||
|
function copyOperation (o) {
|
||||||
|
o = copyObject(o)
|
||||||
|
if (o.content != null) {
|
||||||
|
o.content = o.content.map(function (c) { return c })
|
||||||
|
}
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
Y.utils.copyOperation = copyOperation
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Defines a smaller relation on Id's
|
Defines a smaller relation on Id's
|
||||||
*/
|
*/
|
||||||
@@ -2838,6 +3136,11 @@ module.exports = function (Y /* : any*/) {
|
|||||||
}
|
}
|
||||||
Y.utils.smaller = smaller
|
Y.utils.smaller = smaller
|
||||||
|
|
||||||
|
function inDeletionRange (del, ins) {
|
||||||
|
return del.target[0] === ins[0] && del.target[1] <= ins[1] && ins[1] < del.target[1] + (del.length || 1)
|
||||||
|
}
|
||||||
|
Y.utils.inDeletionRange = inDeletionRange
|
||||||
|
|
||||||
function compareIds (id1, id2) {
|
function compareIds (id1, id2) {
|
||||||
if (id1 == null || id2 == null) {
|
if (id1 == null || id2 == null) {
|
||||||
return id1 === id2
|
return id1 === id2
|
||||||
@@ -2894,9 +3197,9 @@ module.exports = function (Y /* : any*/) {
|
|||||||
I tried to optimize this for performance, therefore no highlevel operations.
|
I tried to optimize this for performance, therefore no highlevel operations.
|
||||||
*/
|
*/
|
||||||
class SmallLookupBuffer extends Store {
|
class SmallLookupBuffer extends Store {
|
||||||
constructor (arg) {
|
constructor (arg1, arg2) {
|
||||||
// super(...arguments) -- do this when this is supported by stable nodejs
|
// super(...arguments) -- do this when this is supported by stable nodejs
|
||||||
super(arg)
|
super(arg1, arg2)
|
||||||
this.writeBuffer = createEmptyOpsArray(5)
|
this.writeBuffer = createEmptyOpsArray(5)
|
||||||
this.readBuffer = createEmptyOpsArray(10)
|
this.readBuffer = createEmptyOpsArray(10)
|
||||||
}
|
}
|
||||||
@@ -3089,6 +3392,7 @@ function requestModules (modules) {
|
|||||||
})
|
})
|
||||||
promises.push(requireModule.promise)
|
promises.push(requireModule.promise)
|
||||||
} else {
|
} else {
|
||||||
|
console.info('YJS: Please do not depend on automatic requiring of modules anymore! Extend modules as follows `require(\'y-modulename\')(Y)`')
|
||||||
require(modulename)(Y)
|
require(modulename)(Y)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -3135,23 +3439,25 @@ function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
|
|||||||
modules.push(opts.share[name])
|
modules.push(opts.share[name])
|
||||||
}
|
}
|
||||||
Y.sourceDir = opts.sourceDir
|
Y.sourceDir = opts.sourceDir
|
||||||
return Y.requestModules(modules).then(function () {
|
return new Promise(function (resolve, reject) {
|
||||||
return new Promise(function (resolve, reject) {
|
setTimeout(function () {
|
||||||
if (opts == null) reject('An options object is expected! ')
|
Y.requestModules(modules).then(function () {
|
||||||
else if (opts.connector == null) reject('You must specify a connector! (missing connector property)')
|
if (opts == null) reject('An options object is expected! ')
|
||||||
else if (opts.connector.name == null) reject('You must specify connector name! (missing connector.name property)')
|
else if (opts.connector == null) reject('You must specify a connector! (missing connector property)')
|
||||||
else if (opts.db == null) reject('You must specify a database! (missing db property)')
|
else if (opts.connector.name == null) reject('You must specify connector name! (missing connector.name property)')
|
||||||
else if (opts.connector.name == null) reject('You must specify db name! (missing db.name property)')
|
else if (opts.db == null) reject('You must specify a database! (missing db property)')
|
||||||
else if (opts.share == null) reject('You must specify a set of shared types!')
|
else if (opts.connector.name == null) reject('You must specify db name! (missing db.name property)')
|
||||||
else {
|
else if (opts.share == null) reject('You must specify a set of shared types!')
|
||||||
var yconfig = new YConfig(opts)
|
else {
|
||||||
yconfig.db.whenUserIdSet(function () {
|
var yconfig = new YConfig(opts)
|
||||||
yconfig.init(function () {
|
yconfig.db.whenUserIdSet(function () {
|
||||||
resolve(yconfig)
|
yconfig.init(function () {
|
||||||
|
resolve(yconfig)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
}
|
}).catch(reject)
|
||||||
})
|
}, 0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user