diff --git a/js/id/graph/graph.js b/js/id/graph/graph.js index f2525daf5..5ef0f54b1 100644 --- a/js/id/graph/graph.js +++ b/js/id/graph/graph.js @@ -88,25 +88,39 @@ iD.Graph.prototype = { // data into each state. To external consumers, it should appear as if the // graph always contained the newly downloaded data. rebase: function(entities) { - var i, keys; + var base = this.base(), + i, k, child, id, keys; // Merging of data only needed if graph is the base graph if (!this.inherited) { - _.defaults(this.base().entities, entities); for (i in entities) { - this._updateCalculated(undefined, entities[i], this.base().parentWays, this.base().parentRels); + if (!base.entities[i]) { + base.entities[i] = entities[i]; + this._updateCalculated(undefined, entities[i], + base.parentWays, base.parentRels); + } } } keys = Object.keys(this._parentWays); for (i = 0; i < keys.length; i++) { - this._parentWays[keys[i]] = _.unique((this._parentWays[keys[i]] || []) - .concat(this.base().parentWays[keys[i]] || [])); + child = keys[i]; + for (k = 0; k < base.parentWays[child].length; k++) { + id = base.parentWays[child][k]; + if (this.entity(id) && !_.contains(this._parentWays[child], id)) { + this._parentWays[child].push(id); + } + } } keys = Object.keys(this._parentRels); for (i = 0; i < keys.length; i++) { - this._parentRels[keys[i]] = _.unique((this._parentRels[keys[i]] || []) - .concat(this.base().parentRels[keys[i]] || [])); + child = keys[i]; + for (k = 0; k < base.parentRels[child].length; k++) { + id = base.parentRels[child][k]; + if (this.entity(id) && !_.contains(this._parentRels[child], id)) { + this._parentRels[child].push(id); + } + } } }, diff --git a/test/spec/graph/graph.js b/test/spec/graph/graph.js index 9d918ae04..667cfe149 100644 --- a/test/spec/graph/graph.js +++ b/test/spec/graph/graph.js @@ -105,6 +105,16 @@ describe('iD.Graph', function() { expect(graph2.parentWays(n)).to.eql([w1, w2, w3]); }); + it("avoids re-adding removed parentWays", function() { + var n = iD.Node({id: 'n'}), + w1 = iD.Way({id: 'w1', nodes: ['n']}), + graph = iD.Graph([n, w1]), + graph2 = graph.remove(w1); + graph.rebase({ 'w1': w1 }); + graph2.rebase({ 'w1': w1 }); + expect(graph2.parentWays(n)).to.eql([]); + }); + it("updates parentRelations", function () { var n = iD.Node({id: 'n'}), r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}), @@ -117,7 +127,17 @@ describe('iD.Graph', function() { expect(graph._parentRels.hasOwnProperty('n')).to.be.false; }); - it("updates parentWays for nodes with modified parentWays", function () { + it("avoids re-adding removed parentRels", function() { + var n = iD.Node({id: 'n'}), + r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}), + graph = iD.Graph([n, r1]), + graph2 = graph.remove(r1); + graph.rebase({ 'w1': r1 }); + graph2.rebase({ 'w1': r1 }); + expect(graph2.parentWays(n)).to.eql([]); + }); + + it("updates parentRels for nodes with modified parentWays", function () { var n = iD.Node({id: 'n'}), r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}), r2 = iD.Relation({id: 'r2', members: [{id: 'n'}]}), @@ -129,6 +149,7 @@ describe('iD.Graph', function() { graph2.rebase({'r3': r3}); expect(graph2.parentRelations(n)).to.eql([r1, r2, r3]); }); + }); describe("#remove", function () {