Skip to content

Commit

Permalink
Patch changeListener to better sync self.current.
Browse files Browse the repository at this point in the history
When a cursor updates, any cursors not in the keypath to the updated cursor will become stale. Patch changeListener to better sync self.current when a stale cursor updates, and when a un-stale cursor updates.
  • Loading branch information
dashed committed Dec 17, 2014
1 parent d97662d commit 7f06ee7
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/structure.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,20 @@ Structure.prototype.cursor = function (path) {

var changeListener = function (newRoot, oldRoot, path) {

if(self.current === oldRoot) {
return self.current = newRoot;
}
// Othewise an out-of-sync change occured. We ignore `oldRoot`, and focus on
// changes at path `path`, and sync this to `self.current`.

var inNew = hasIn(newRoot, path);
var inOld = hasIn(oldRoot, path);
var inOld = hasIn(self.current, path);

if(!inNew && inOld) {
return self.current = newRoot;
return self.current = self.current.removeIn(path);
}
if(inNew && !inOld) {
return self.current = self.current.setIn(path, newRoot.getIn(path));
}

return self.current = self.current.updateIn(path, function (data) {
Expand Down
98 changes: 98 additions & 0 deletions tests/structure_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,40 @@ describe('structure', function () {
});
});

it('should resync immutable collection when a stale cursor changed existing property', function() {

var struct = new Structure({
data: { foo: 42, bar: 24 }
});

var foo = struct.cursor('foo');
var bar = struct.cursor('bar');
var original = struct.current;

struct.once('swap', function(newRoot, oldRoot) {
original.should.equal(oldRoot);
foo._rootData.should.equal(original);
});

foo.update(function(val) {
return val + 1;
});
struct.current.toJS().should.eql({ foo: 43, bar: 24 });

original = struct.current;
struct.once('swap', function(newRoot, oldRoot) {
original.should.not.equal(oldRoot);
bar._rootData.should.not.equal(original);
bar._rootData.should.equal(oldRoot);
});

bar.update(function(val) {
return val + 1;
});

struct.current.toJS().should.eql({ foo: 43, bar: 25 });
});

it('should trigger add with data when a new property is added', function (done) {
var structure = new Structure({
data: { 'foo': 'hello' }
Expand Down Expand Up @@ -236,6 +270,40 @@ describe('structure', function () {
structure.cursor().set('3', void 0);
});

it('should resync immutable collection when a stale cursor adds new property', function() {

var struct = new Structure({
data: { foo: {}, bar: {} }
});

var foo = struct.cursor('foo');
var bar = struct.cursor('bar');
var original = struct.current;

struct.once('swap', function(newRoot, oldRoot) {
original.should.equal(oldRoot);
foo._rootData.should.equal(original);
});

foo.update('a', function() {
return 42;
});
struct.current.toJS().should.eql({ foo: {a: 42}, bar: {} });

original = struct.current;
struct.once('swap', function(newRoot, oldRoot) {
original.should.not.equal(oldRoot);
bar._rootData.should.not.equal(original);
bar._rootData.should.equal(oldRoot);
});

bar.update('b', function(val) {
return 24;
});

struct.current.toJS().should.eql({ foo: {a: 42}, bar: {b: 24} });
});

it('should trigger delete with data when existing property is removed', function (done) {
var structure = new Structure({
data: { 'foo': 'hello', 'bar': 'world' }
Expand Down Expand Up @@ -279,6 +347,36 @@ describe('structure', function () {
structure.cursor().delete('subtree');
});

it('should resync immutable collection when a stale cursor deletes existing property', function() {

var struct = new Structure({
data: { foo: { a: 42 }, bar: { b: 24 } }
});

var foo = struct.cursor('foo');
var bar = struct.cursor('bar');
var original = struct.current;

struct.once('swap', function(newRoot, oldRoot) {
original.should.equal(oldRoot);
foo._rootData.should.equal(original);
});

foo.delete('a');
struct.current.toJS().should.eql({ foo: {}, bar: {b: 24} });

original = struct.current;
struct.once('swap', function(newRoot, oldRoot) {
original.should.not.equal(oldRoot);
bar._rootData.should.not.equal(original);
bar._rootData.should.equal(oldRoot);
});

bar.delete('b');

struct.current.toJS().should.eql({ foo: {}, bar: {} });
});

it('should expose immutable.js cursor', function () {
var structure = new Structure({
data: { 'foo': 'hello' }
Expand Down

0 comments on commit 7f06ee7

Please sign in to comment.