Skip to content

Commit

Permalink
Return same instance on redundant updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gozala committed Jul 1, 2015
1 parent 48937a8 commit 51a3af8
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 10 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@
"prepublish": "npm run build"
},
"dependencies": {
"immutable": "^3.7.0"
"immutable": "3.7.0"
},
"devDependencies": {
"babel": "^4.7.4",
"immutable": "^3.6.4",
"babel": "4.7.6",
"tap": "~0.4.8",
"tape": "~2.3.2"
}
Expand Down
23 changes: 16 additions & 7 deletions src/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ const $empty = Typed.empty


const change = (list, f) => {
const result = list.__ownerID ? list : construct(list)
const store = f(list[$store])
result[$store] = store
result.size = store.size
return result
if (store === list[$store]) {
return list
} else {
const result = list.__ownerID ? list : construct(list)
result[$store] = store
result.size = store.size
return result
}
}

const clear = target => target.clear()
Expand All @@ -47,6 +51,7 @@ class TypeInferedList extends Immutable.List {
static from(list) {
const result = construct(this.prototype)
result[$store] = list[$store]
result.size = list.size
return result
}
constructor(value) {
Expand Down Expand Up @@ -84,7 +89,9 @@ class TypeInferedList extends Immutable.List {


const list = this[$init]()
Indexed(input).forEach((value, index) => {
const source = Indexed(input)
list.size = source.size
source.forEach((value, index) => {
list.set(index, value)
})

Expand Down Expand Up @@ -207,6 +214,7 @@ class TypeInferedList extends Immutable.List {
result.__ownerID = ownerID
result[$store] = this[$store] ? this[$store].__ensureOwner(ownerID) :
ImmutableList().__ensureOwner(ownerID)
result.size = result[$store].size

return result
}
Expand All @@ -233,6 +241,9 @@ class TypedList extends TypeInferedList {
return this
} else {
const result = TypeInferedList.from(this).map(mapper, context)
if (this[$store] === result[$store]) {
return this
}
if (result[$type] === this[$type]) {
const list = construct(this)
list[$store] = result[$store]
Expand Down Expand Up @@ -298,5 +309,3 @@ export const List = function(descriptor, label) {
List.Type = TypedList
List.prototype = TypedList.prototype
const ListPrototype = TypedList.prototype


4 changes: 4 additions & 0 deletions src/record.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ class TypedRecord extends Iterable.Keyed {
const store = result[$store] ? result[$store].set(key, value) :
new Map([[key, value]])

if (result[$store] === store) {
return result;
}

const record = result.__ownerID ? result : construct(result)
record[$store] = store

Expand Down
27 changes: 27 additions & 0 deletions src/test/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -947,3 +947,30 @@ test('can be efficiently sliced', assert => {
assert.equal(v2.last(), 1899)
assert.equal(v2.butLast().size, 1799)
})

const identity = x => x
test('identity preserved on no redundunt changes', assert => {
const ps = Points([{x: 1}, {y: 20}, {x: 3, y: 5}])


assert.equal(ps, ps.set(0, ps.first()))
assert.equal(ps, ps.set(1, ps.get(1)))
assert.equal(ps, ps.set(2, ps.get(2)))

assert.equal(ps.setIn([0, 'x'], 1), ps)
assert.equal(ps.setIn([0, 'y'], 0), ps)
assert.equal(ps.setIn([1, 'x'], 0), ps)
assert.equal(ps.setIn([1, 'y'], 20), ps)
assert.equal(ps.setIn([2, 'x'], 3), ps)
assert.equal(ps.setIn([2, 'y'], 5), ps)

assert.equal(ps.mergeIn([0], {x: 1}), ps)
assert.equal(ps.mergeIn([0], {y: 0}), ps)
assert.equal(ps.mergeIn([0], {x: 1, y: 0}), ps)
assert.equal(ps.mergeIn([1], {x: 0}), ps)
assert.equal(ps.mergeIn([1], {y: 20}), ps)
assert.equal(ps.mergeIn([1], {x: 0, y: 20}), ps)
assert.equal(ps.mergeIn([2], {x: 3}), ps)
assert.equal(ps.mergeIn([2], {y: 5}), ps)
assert.equal(ps.mergeIn([2], {x: 3, y: 5}), ps)
})
39 changes: 39 additions & 0 deletions src/test/record.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,42 @@ test("reading records", assert => {
assert.deepEqual(v3.toJSON(), {x:0,y:10})
assert.deepEqual(v4.toJSON(), {x:1,y:2})
})


const identity = x => x
test("identical on no change", assert => {
var p1 = Point({x: 5});

assert.equal(p1, p1.set('x', 5));
assert.equal(p1, p1.merge({x: 5}));
assert.equal(p1, p1.merge({y: 0}));
assert.equal(p1, p1.merge({x: 5, y: 0}));
assert.equal(p1, p1.remove('y'));
assert.equal(p1, p1.update('x', identity));
assert.equal(p1, p1.update('y', identity));
})

test("identical no change in deep updates", assert => {
var Line = Record({start: Point, end: Point}, 'Line')

var l1 = Line({start: {x: 5}, end: {x: 7, y: 2}})

assert.equal(l1, l1.set('start', l1.start))
assert.equal(l1, l1.set('end', l1.end))

assert.equal(l1, l1.merge({start: l1.start}))
assert.equal(l1, l1.merge({end: l1.end}))
assert.equal(l1, l1.merge({start: l1.start, end: l1.end}))
assert.equal(l1, l1.removeIn(['start', 'y']))
assert.equal(l1, l1.setIn(['start', 'x'], 5))
assert.equal(l1, l1.setIn(['start', 'x'], 5)
.setIn(['end', 'x'], 7))
assert.equal(l1, l1.mergeIn(['start'], {x: 5}))
assert.equal(l1, l1.mergeIn(['start'], {x: 5, y: 0}))
assert.equal(l1, l1.mergeIn(['start'], {y: 0}))
assert.equal(l1, l1.mergeIn(['end'], {y: 2}))
assert.equal(l1, l1.mergeIn(['end'], {x: 7}))
assert.equal(l1, l1.mergeIn(['end'], {y: 2, x: 7}))

assert.equal(l1, l1.update('start', p => p.set('x', 5)))
})

0 comments on commit 51a3af8

Please sign in to comment.