Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5350b26cb3 | ||
|
|
4feaf6c6fb | ||
|
|
c5b47e88ac | ||
|
|
dc3c6a5d42 | ||
|
|
a9c2ec6ba0 | ||
|
|
f166b9efc5 | ||
|
|
0441b83f74 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "0.5.0",
|
"version": "0.5.2",
|
||||||
"homepage": "https://github.com/DadaMonad/yjs",
|
"homepage": "https://github.com/DadaMonad/yjs",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -8,16 +8,6 @@ adaptConnector = function(connector, engine, HB, execution_listener) {
|
|||||||
f = ConnectorClass[name];
|
f = ConnectorClass[name];
|
||||||
connector[name] = f;
|
connector[name] = f;
|
||||||
}
|
}
|
||||||
connector.setIsBoundToY();
|
|
||||||
send_ = function(o) {
|
|
||||||
if ((o.uid.creator === HB.getUserId()) && (typeof o.uid.op_number !== "string") && (HB.getUserId() !== "_temp")) {
|
|
||||||
return connector.broadcast(o);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (connector.invokeSync != null) {
|
|
||||||
HB.setInvokeSyncHandler(connector.invokeSync);
|
|
||||||
}
|
|
||||||
execution_listener.push(send_);
|
|
||||||
encode_state_vector = function(v) {
|
encode_state_vector = function(v) {
|
||||||
var results, value;
|
var results, value;
|
||||||
results = [];
|
results = [];
|
||||||
@@ -61,11 +51,21 @@ adaptConnector = function(connector, engine, HB, execution_listener) {
|
|||||||
if (connector.receive_handlers == null) {
|
if (connector.receive_handlers == null) {
|
||||||
connector.receive_handlers = [];
|
connector.receive_handlers = [];
|
||||||
}
|
}
|
||||||
return connector.receive_handlers.push(function(sender, op) {
|
connector.receive_handlers.push(function(sender, op) {
|
||||||
if (op.uid.creator !== HB.getUserId()) {
|
if (op.uid.creator !== HB.getUserId()) {
|
||||||
return engine.applyOp(op);
|
return engine.applyOp(op);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
connector.setIsBoundToY();
|
||||||
|
send_ = function(o) {
|
||||||
|
if ((o.uid.creator === HB.getUserId()) && (typeof o.uid.op_number !== "string") && (HB.getUserId() !== "_temp")) {
|
||||||
|
return connector.broadcast(o);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (connector.invokeSync != null) {
|
||||||
|
HB.setInvokeSyncHandler(connector.invokeSync);
|
||||||
|
}
|
||||||
|
return execution_listener.push(send_);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = adaptConnector;
|
module.exports = adaptConnector;
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
whenSynced: function(args) {
|
whenSynced: function(args) {
|
||||||
if (args.constructore === Function) {
|
if (args.constructor === Function) {
|
||||||
args = [args];
|
args = [args];
|
||||||
}
|
}
|
||||||
if (this.is_synced) {
|
if (this.is_synced) {
|
||||||
@@ -154,7 +154,7 @@ module.exports = {
|
|||||||
this.send(user, {
|
this.send(user, {
|
||||||
sync_step: "getHB",
|
sync_step: "getHB",
|
||||||
send_again: "true",
|
send_again: "true",
|
||||||
data: []
|
data: this.getStateVector()
|
||||||
});
|
});
|
||||||
if (!this.sent_hb_to_all_users) {
|
if (!this.sent_hb_to_all_users) {
|
||||||
this.sent_hb_to_all_users = true;
|
this.sent_hb_to_all_users = true;
|
||||||
@@ -184,7 +184,7 @@ module.exports = {
|
|||||||
this.send(user, {
|
this.send(user, {
|
||||||
sync_step: "getHB",
|
sync_step: "getHB",
|
||||||
send_again: "true",
|
send_again: "true",
|
||||||
data: []
|
data: this.getStateVector()
|
||||||
});
|
});
|
||||||
hb = this.getHB([]).hb;
|
hb = this.getHB([]).hb;
|
||||||
_hb = [];
|
_hb = [];
|
||||||
@@ -205,22 +205,30 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
setStateSynced: function() {
|
setStateSynced: function() {
|
||||||
var f, i, len, ref;
|
var args, el, f, i, len, ref;
|
||||||
if (!this.is_synced) {
|
if (!this.is_synced) {
|
||||||
this.is_synced = true;
|
this.is_synced = true;
|
||||||
if (this.compute_when_synced != null) {
|
if (this.compute_when_synced != null) {
|
||||||
ref = this.compute_when_synced;
|
ref = this.compute_when_synced;
|
||||||
for (i = 0, len = ref.length; i < len; i++) {
|
for (i = 0, len = ref.length; i < len; i++) {
|
||||||
f = ref[i];
|
el = ref[i];
|
||||||
f();
|
f = el[0];
|
||||||
|
args = el.slice(1);
|
||||||
|
f.apply(args);
|
||||||
}
|
}
|
||||||
delete this.compute_when_synced;
|
delete this.compute_when_synced;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
whenReceivedStateVector: function(f) {
|
||||||
|
if (this.when_received_state_vector_listeners == null) {
|
||||||
|
this.when_received_state_vector_listeners = [];
|
||||||
|
}
|
||||||
|
return this.when_received_state_vector_listeners.push(f);
|
||||||
|
},
|
||||||
receiveMessage: function(sender, res) {
|
receiveMessage: function(sender, res) {
|
||||||
var _hb, data, f, hb, i, j, len, len1, o, ref, results, sendApplyHB, send_again;
|
var _hb, data, f, hb, i, j, k, len, len1, len2, o, ref, ref1, results, sendApplyHB, send_again;
|
||||||
if (res.sync_step == null) {
|
if (res.sync_step == null) {
|
||||||
ref = this.receive_handlers;
|
ref = this.receive_handlers;
|
||||||
results = [];
|
results = [];
|
||||||
@@ -234,6 +242,14 @@ module.exports = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (res.sync_step === "getHB") {
|
if (res.sync_step === "getHB") {
|
||||||
|
if (this.when_received_state_vector_listeners != null) {
|
||||||
|
ref1 = this.when_received_state_vector_listeners;
|
||||||
|
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||||
|
f = ref1[j];
|
||||||
|
f.call(this, res.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete this.when_received_state_vector_listeners;
|
||||||
data = this.getHB(res.data);
|
data = this.getHB(res.data);
|
||||||
hb = data.hb;
|
hb = data.hb;
|
||||||
_hb = [];
|
_hb = [];
|
||||||
@@ -250,8 +266,8 @@ module.exports = {
|
|||||||
};
|
};
|
||||||
})(this);
|
})(this);
|
||||||
}
|
}
|
||||||
for (j = 0, len1 = hb.length; j < len1; j++) {
|
for (k = 0, len2 = hb.length; k < len2; k++) {
|
||||||
o = hb[j];
|
o = hb[k];
|
||||||
_hb.push(o);
|
_hb.push(o);
|
||||||
if (_hb.length > 10) {
|
if (_hb.length > 10) {
|
||||||
sendApplyHB({
|
sendApplyHB({
|
||||||
@@ -269,10 +285,10 @@ module.exports = {
|
|||||||
send_again = (function(_this) {
|
send_again = (function(_this) {
|
||||||
return function(sv) {
|
return function(sv) {
|
||||||
return function() {
|
return function() {
|
||||||
var k, len2;
|
var l, len3;
|
||||||
hb = _this.getHB(sv).hb;
|
hb = _this.getHB(sv).hb;
|
||||||
for (k = 0, len2 = hb.length; k < len2; k++) {
|
for (l = 0, len3 = hb.length; l < len3; l++) {
|
||||||
o = hb[k];
|
o = hb[l];
|
||||||
_hb.push(o);
|
_hb.push(o);
|
||||||
if (_hb.length > 10) {
|
if (_hb.length > 10) {
|
||||||
_this.send(sender, {
|
_this.send(sender, {
|
||||||
|
|||||||
@@ -16,30 +16,26 @@ HistoryBuffer = (function() {
|
|||||||
setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
|
setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryBuffer.prototype.resetUserId = function(id) {
|
HistoryBuffer.prototype.setUserId = function(user_id1, state_vector) {
|
||||||
var o, o_name, own;
|
var base, buff, counter_diff, name, o, o_name, ref;
|
||||||
own = this.buffer[this.user_id];
|
this.user_id = user_id1;
|
||||||
if (own != null) {
|
if ((base = this.buffer)[name = this.user_id] == null) {
|
||||||
for (o_name in own) {
|
base[name] = [];
|
||||||
o = own[o_name];
|
|
||||||
if (o.uid.creator != null) {
|
|
||||||
o.uid.creator = id;
|
|
||||||
}
|
|
||||||
if (o.uid.alt != null) {
|
|
||||||
o.uid.alt.creator = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.buffer[id] != null) {
|
|
||||||
throw new Error("You are re-assigning an old user id - this is not (yet) possible!");
|
|
||||||
}
|
|
||||||
this.buffer[id] = own;
|
|
||||||
delete this.buffer[this.user_id];
|
|
||||||
}
|
}
|
||||||
if (this.operation_counter[this.user_id] != null) {
|
buff = this.buffer[this.user_id];
|
||||||
this.operation_counter[id] = this.operation_counter[this.user_id];
|
counter_diff = state_vector[this.user_id] || 0;
|
||||||
delete this.operation_counter[this.user_id];
|
if (this.buffer._temp != null) {
|
||||||
|
ref = this.buffer._temp;
|
||||||
|
for (o_name in ref) {
|
||||||
|
o = ref[o_name];
|
||||||
|
o.uid.creator = this.user_id;
|
||||||
|
o.uid.op_number += counter_diff;
|
||||||
|
buff[o.uid.op_number] = o;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this.user_id = id;
|
this.operation_counter[this.user_id] = (this.operation_counter._temp || 0) + counter_diff;
|
||||||
|
delete this.operation_counter._temp;
|
||||||
|
return delete this.buffer._temp;
|
||||||
};
|
};
|
||||||
|
|
||||||
HistoryBuffer.prototype.emptyGarbage = function() {
|
HistoryBuffer.prototype.emptyGarbage = function() {
|
||||||
@@ -243,15 +239,13 @@ HistoryBuffer = (function() {
|
|||||||
if ((base = this.operation_counter)[name = o.uid.creator] == null) {
|
if ((base = this.operation_counter)[name = o.uid.creator] == null) {
|
||||||
base[name] = 0;
|
base[name] = 0;
|
||||||
}
|
}
|
||||||
if (o.uid.creator !== this.getUserId()) {
|
if (o.uid.op_number === this.operation_counter[o.uid.creator]) {
|
||||||
if (o.uid.op_number === this.operation_counter[o.uid.creator]) {
|
this.operation_counter[o.uid.creator]++;
|
||||||
this.operation_counter[o.uid.creator]++;
|
|
||||||
}
|
|
||||||
while (this.buffer[o.uid.creator][this.operation_counter[o.uid.creator]] != null) {
|
|
||||||
this.operation_counter[o.uid.creator]++;
|
|
||||||
}
|
|
||||||
return void 0;
|
|
||||||
}
|
}
|
||||||
|
while (this.buffer[o.uid.creator][this.operation_counter[o.uid.creator]] != null) {
|
||||||
|
this.operation_counter[o.uid.creator]++;
|
||||||
|
}
|
||||||
|
return void 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
return HistoryBuffer;
|
return HistoryBuffer;
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ module.exports = function() {
|
|||||||
if (callLater) {
|
if (callLater) {
|
||||||
this.parent.callOperationSpecificDeleteEvents(this, o);
|
this.parent.callOperationSpecificDeleteEvents(this, o);
|
||||||
}
|
}
|
||||||
if ((this.prev_cl != null) && this.prev_cl.isDeleted()) {
|
if ((this.prev_cl != null) && this.prev_cl.isDeleted() && this.prev_cl.garbage_collected !== true) {
|
||||||
return this.prev_cl.applyDelete();
|
return this.prev_cl.applyDelete();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ adaptConnector = require("./ConnectorAdapter");
|
|||||||
|
|
||||||
createY = function(connector) {
|
createY = function(connector) {
|
||||||
var HB, ct, engine, model, ops, ops_manager, user_id;
|
var HB, ct, engine, model, ops, ops_manager, user_id;
|
||||||
user_id = null;
|
|
||||||
if (connector.user_id != null) {
|
if (connector.user_id != null) {
|
||||||
user_id = connector.user_id;
|
user_id = connector.user_id;
|
||||||
} else {
|
} else {
|
||||||
user_id = "_temp";
|
user_id = "_temp";
|
||||||
connector.on_user_id_set = function(id) {
|
connector.when_received_state_vector_listeners = [
|
||||||
user_id = id;
|
function(state_vector) {
|
||||||
return HB.resetUserId(id);
|
return HB.setUserId(this.user_id, state_vector);
|
||||||
};
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
HB = new HistoryBuffer(user_id);
|
HB = new HistoryBuffer(user_id);
|
||||||
ops_manager = structured_ops_uninitialized(HB, this.constructor);
|
ops_manager = structured_ops_uninitialized(HB, this.constructor);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
20152
build/test/selections-test.js
Normal file
20152
build/test/selections-test.js
Normal file
File diff suppressed because one or more lines are too long
18741
build/test/text-test.js
Normal file
18741
build/test/text-test.js
Normal file
File diff suppressed because one or more lines are too long
35262
build/test/xml-test.js
Normal file
35262
build/test/xml-test.js
Normal file
File diff suppressed because one or more lines are too long
@@ -10,18 +10,6 @@ adaptConnector = (connector, engine, HB, execution_listener)->
|
|||||||
for name, f of ConnectorClass
|
for name, f of ConnectorClass
|
||||||
connector[name] = f
|
connector[name] = f
|
||||||
|
|
||||||
connector.setIsBoundToY()
|
|
||||||
|
|
||||||
send_ = (o)->
|
|
||||||
if (o.uid.creator is HB.getUserId()) and
|
|
||||||
(typeof o.uid.op_number isnt "string") and # TODO: i don't think that we need this anymore..
|
|
||||||
(HB.getUserId() isnt "_temp")
|
|
||||||
connector.broadcast o
|
|
||||||
|
|
||||||
if connector.invokeSync?
|
|
||||||
HB.setInvokeSyncHandler connector.invokeSync
|
|
||||||
|
|
||||||
execution_listener.push send_
|
|
||||||
# For the XMPPConnector: lets send it as an array
|
# For the XMPPConnector: lets send it as an array
|
||||||
# therefore, we have to restructure it later
|
# therefore, we have to restructure it later
|
||||||
encode_state_vector = (v)->
|
encode_state_vector = (v)->
|
||||||
@@ -57,5 +45,17 @@ adaptConnector = (connector, engine, HB, execution_listener)->
|
|||||||
if op.uid.creator isnt HB.getUserId()
|
if op.uid.creator isnt HB.getUserId()
|
||||||
engine.applyOp op
|
engine.applyOp op
|
||||||
|
|
||||||
|
connector.setIsBoundToY()
|
||||||
|
|
||||||
|
send_ = (o)->
|
||||||
|
if (o.uid.creator is HB.getUserId()) and
|
||||||
|
(typeof o.uid.op_number isnt "string") and # TODO: i don't think that we need this anymore..
|
||||||
|
(HB.getUserId() isnt "_temp")
|
||||||
|
connector.broadcast o
|
||||||
|
|
||||||
|
if connector.invokeSync?
|
||||||
|
HB.setInvokeSyncHandler connector.invokeSync
|
||||||
|
|
||||||
|
execution_listener.push send_
|
||||||
|
|
||||||
module.exports = adaptConnector
|
module.exports = adaptConnector
|
||||||
|
|||||||
@@ -102,10 +102,10 @@ module.exports =
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Execute a function _when_ we are connected. If not connected, wait until connected.
|
# Execute a function _when_ we are connected. If not connected, wait until connected.
|
||||||
# @param f {Function} Will be executed on the PeerJs-Connector context.
|
# @param f {Function} Will be executed on the Connector context.
|
||||||
#
|
#
|
||||||
whenSynced: (args)->
|
whenSynced: (args)->
|
||||||
if args.constructore is Function
|
if args.constructor is Function
|
||||||
args = [args]
|
args = [args]
|
||||||
if @is_synced
|
if @is_synced
|
||||||
args[0].apply this, args[1..]
|
args[0].apply this, args[1..]
|
||||||
@@ -143,7 +143,7 @@ module.exports =
|
|||||||
@send user,
|
@send user,
|
||||||
sync_step: "getHB"
|
sync_step: "getHB"
|
||||||
send_again: "true"
|
send_again: "true"
|
||||||
data: [] # @getStateVector()
|
data: @getStateVector()
|
||||||
if not @sent_hb_to_all_users
|
if not @sent_hb_to_all_users
|
||||||
@sent_hb_to_all_users = true
|
@sent_hb_to_all_users = true
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ module.exports =
|
|||||||
@send user,
|
@send user,
|
||||||
sync_step: "getHB"
|
sync_step: "getHB"
|
||||||
send_again: "true"
|
send_again: "true"
|
||||||
data: []
|
data: @getStateVector()
|
||||||
hb = @getHB([]).hb
|
hb = @getHB([]).hb
|
||||||
_hb = []
|
_hb = []
|
||||||
for o in hb
|
for o in hb
|
||||||
@@ -192,11 +192,19 @@ module.exports =
|
|||||||
if not @is_synced
|
if not @is_synced
|
||||||
@is_synced = true
|
@is_synced = true
|
||||||
if @compute_when_synced?
|
if @compute_when_synced?
|
||||||
for f in @compute_when_synced
|
for el in @compute_when_synced
|
||||||
f()
|
f = el[0]
|
||||||
|
args = el[1..]
|
||||||
|
f.apply(args)
|
||||||
delete @compute_when_synced
|
delete @compute_when_synced
|
||||||
null
|
null
|
||||||
|
|
||||||
|
# executed when the a state_vector is received. listener will be called only once!
|
||||||
|
whenReceivedStateVector: (f)->
|
||||||
|
@when_received_state_vector_listeners ?= []
|
||||||
|
@when_received_state_vector_listeners.push f
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# You received a raw message, and you know that it is intended for to Yjs. Then call this function.
|
# You received a raw message, and you know that it is intended for to Yjs. Then call this function.
|
||||||
#
|
#
|
||||||
@@ -208,6 +216,12 @@ module.exports =
|
|||||||
if sender is @user_id
|
if sender is @user_id
|
||||||
return
|
return
|
||||||
if res.sync_step is "getHB"
|
if res.sync_step is "getHB"
|
||||||
|
# call listeners
|
||||||
|
if @when_received_state_vector_listeners?
|
||||||
|
for f in @when_received_state_vector_listeners
|
||||||
|
f.call this, res.data
|
||||||
|
delete @when_received_state_vector_listeners
|
||||||
|
|
||||||
data = @getHB(res.data)
|
data = @getHB(res.data)
|
||||||
hb = data.hb
|
hb = data.hb
|
||||||
_hb = []
|
_hb = []
|
||||||
|
|||||||
@@ -22,22 +22,32 @@ class HistoryBuffer
|
|||||||
@reserved_identifier_counter = 0
|
@reserved_identifier_counter = 0
|
||||||
setTimeout @emptyGarbage, @garbageCollectTimeout
|
setTimeout @emptyGarbage, @garbageCollectTimeout
|
||||||
|
|
||||||
resetUserId: (id)->
|
# At the beginning (when the user id was not assigned yet),
|
||||||
own = @buffer[@user_id]
|
# the operations are added to buffer._temp. When you finally get your user id,
|
||||||
if own?
|
# the operations are copies from buffer._temp to buffer[id]. Furthermore, when buffer[id] does already contain operations
|
||||||
for o_name,o of own
|
# (because of a previous session), the uid.op_numbers of the operations have to be reassigned.
|
||||||
if o.uid.creator?
|
# This is what this function does. It adds them to buffer[id],
|
||||||
o.uid.creator = id
|
# and assigns them the correct uid.op_number and uid.creator
|
||||||
if o.uid.alt?
|
setUserId: (@user_id, state_vector)->
|
||||||
o.uid.alt.creator = id
|
@buffer[@user_id] ?= []
|
||||||
if @buffer[id]?
|
buff = @buffer[@user_id]
|
||||||
throw new Error "You are re-assigning an old user id - this is not (yet) possible!"
|
|
||||||
@buffer[id] = own
|
# we assumed that we started with counter = 0.
|
||||||
delete @buffer[@user_id]
|
# when we receive tha state_vector, and actually have
|
||||||
if @operation_counter[@user_id]?
|
# counter = 10. Then we have to add 10 to every op_counter
|
||||||
@operation_counter[id] = @operation_counter[@user_id]
|
counter_diff = state_vector[@user_id] or 0
|
||||||
delete @operation_counter[@user_id]
|
|
||||||
@user_id = id
|
if @buffer._temp?
|
||||||
|
for o_name,o of @buffer._temp
|
||||||
|
o.uid.creator = @user_id
|
||||||
|
o.uid.op_number += counter_diff
|
||||||
|
buff[o.uid.op_number] = o
|
||||||
|
|
||||||
|
@operation_counter[@user_id] = (@operation_counter._temp or 0) + counter_diff
|
||||||
|
|
||||||
|
delete @operation_counter._temp
|
||||||
|
delete @buffer._temp
|
||||||
|
|
||||||
|
|
||||||
emptyGarbage: ()=>
|
emptyGarbage: ()=>
|
||||||
for o in @garbage
|
for o in @garbage
|
||||||
@@ -207,17 +217,11 @@ class HistoryBuffer
|
|||||||
#
|
#
|
||||||
addToCounter: (o)->
|
addToCounter: (o)->
|
||||||
@operation_counter[o.uid.creator] ?= 0
|
@operation_counter[o.uid.creator] ?= 0
|
||||||
if o.uid.creator isnt @getUserId()
|
# TODO: check if operations are send in order
|
||||||
# TODO: check if operations are send in order
|
if o.uid.op_number is @operation_counter[o.uid.creator]
|
||||||
if o.uid.op_number is @operation_counter[o.uid.creator]
|
@operation_counter[o.uid.creator]++
|
||||||
@operation_counter[o.uid.creator]++
|
while @buffer[o.uid.creator][@operation_counter[o.uid.creator]]?
|
||||||
while @buffer[o.uid.creator][@operation_counter[o.uid.creator]]?
|
@operation_counter[o.uid.creator]++
|
||||||
@operation_counter[o.uid.creator]++
|
undefined
|
||||||
undefined
|
|
||||||
|
|
||||||
#if @operation_counter[o.uid.creator] isnt (o.uid.op_number + 1)
|
|
||||||
#console.log (@operation_counter[o.uid.creator] - (o.uid.op_number + 1))
|
|
||||||
#console.log o
|
|
||||||
#throw new Error "You don't receive operations in the proper order. Try counting like this 0,1,2,3,4,.. ;)"
|
|
||||||
|
|
||||||
module.exports = HistoryBuffer
|
module.exports = HistoryBuffer
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ module.exports = ()->
|
|||||||
super garbagecollect
|
super garbagecollect
|
||||||
if callLater
|
if callLater
|
||||||
@parent.callOperationSpecificDeleteEvents(this, o)
|
@parent.callOperationSpecificDeleteEvents(this, o)
|
||||||
if @prev_cl? and @prev_cl.isDeleted()
|
if @prev_cl? and @prev_cl.isDeleted() and @prev_cl.garbage_collected isnt true
|
||||||
# garbage collect prev_cl
|
# garbage collect prev_cl
|
||||||
@prev_cl.applyDelete()
|
@prev_cl.applyDelete()
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ Engine = require "./Engine"
|
|||||||
adaptConnector = require "./ConnectorAdapter"
|
adaptConnector = require "./ConnectorAdapter"
|
||||||
|
|
||||||
createY = (connector)->
|
createY = (connector)->
|
||||||
user_id = null
|
|
||||||
if connector.user_id?
|
if connector.user_id?
|
||||||
user_id = connector.user_id # TODO: change to getUniqueId()
|
user_id = connector.user_id # TODO: change to getUniqueId()
|
||||||
else
|
else
|
||||||
user_id = "_temp"
|
user_id = "_temp"
|
||||||
connector.on_user_id_set = (id)->
|
connector.when_received_state_vector_listeners = [(state_vector)->
|
||||||
user_id = id
|
HB.setUserId this.user_id, state_vector
|
||||||
HB.resetUserId id
|
]
|
||||||
HB = new HistoryBuffer user_id
|
HB = new HistoryBuffer user_id
|
||||||
ops_manager = structured_ops_uninitialized HB, this.constructor
|
ops_manager = structured_ops_uninitialized HB, this.constructor
|
||||||
ops = ops_manager.operations
|
ops = ops_manager.operations
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "0.5.1",
|
"version": "0.5.2",
|
||||||
"description": "A Framework that enables Real-Time Collaboration on arbitrary data structures.",
|
"description": "A Framework that enables Real-Time Collaboration on arbitrary data structures.",
|
||||||
"main": "./build/node/y.js",
|
"main": "./build/node/y.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user