diff --git a/src/ol/source/Vector.js b/src/ol/source/Vector.js index 5ce5f70029..1defcf3e15 100644 --- a/src/ol/source/Vector.js +++ b/src/ol/source/Vector.js @@ -544,7 +544,10 @@ class VectorSource extends Source { } } else { if (this.featuresRtree_) { - this.featuresRtree_.forEach(this.removeFeatureInternal.bind(this)); + const removeAndIgnoreReturn = function (feature) { + this.removeFeatureInternal(feature); + }.bind(this); + this.featuresRtree_.forEach(removeAndIgnoreReturn); for (const id in this.nullGeometryFeatures_) { this.removeFeatureInternal(this.nullGeometryFeatures_[id]); } @@ -1019,6 +1022,9 @@ class VectorSource extends Source { * @api */ removeFeature(feature) { + if (!feature) { + return; + } const featureKey = getUid(feature); if (featureKey in this.nullGeometryFeatures_) { delete this.nullGeometryFeatures_[featureKey]; @@ -1027,18 +1033,26 @@ class VectorSource extends Source { this.featuresRtree_.remove(feature); } } - this.removeFeatureInternal(feature); - this.changed(); + const result = this.removeFeatureInternal(feature); + if (result) { + this.changed(); + } } /** * Remove feature without firing a `change` event. * @param {import("../Feature.js").default} feature Feature. + * @return {import("../Feature.js").default|undefined} The removed feature + * (or undefined if the feature was not found). * @protected */ removeFeatureInternal(feature) { const featureKey = getUid(feature); - this.featureChangeKeys_[featureKey].forEach(unlistenByKey); + const featureChangeKeys = this.featureChangeKeys_[featureKey]; + if (!featureChangeKeys) { + return; + } + featureChangeKeys.forEach(unlistenByKey); delete this.featureChangeKeys_[featureKey]; const id = feature.getId(); if (id !== undefined) { @@ -1048,6 +1062,7 @@ class VectorSource extends Source { this.dispatchEvent( new VectorSourceEvent(VectorEventType.REMOVEFEATURE, feature) ); + return feature; } /** diff --git a/test/browser/spec/ol/source/vector.test.js b/test/browser/spec/ol/source/vector.test.js index 26159c96e0..1f992d0e31 100644 --- a/test/browser/spec/ol/source/vector.test.js +++ b/test/browser/spec/ol/source/vector.test.js @@ -339,6 +339,19 @@ describe('ol.source.Vector', function () { vectorSource.removeFeature(features[0]); expect(listener.called).to.be(true); }); + + it('accepts features that are not in the source', function () { + const changeListener = sinon.spy(); + listen(vectorSource, 'change', changeListener); + + const removeFeatureListener = sinon.spy(); + listen(vectorSource, 'removefeature', removeFeatureListener); + + const feature = new Feature(new Point([0, 0])); + vectorSource.removeFeature(feature); + expect(changeListener.called).to.be(false); + expect(removeFeatureListener.called).to.be(false); + }); }); describe("modifying a feature's geometry", function () {