diff --git a/src/ui/map.js b/src/ui/map.js index 8ff6957ac91..e98550acaef 100755 --- a/src/ui/map.js +++ b/src/ui/map.js @@ -1664,6 +1664,10 @@ class Map extends Camera { */ remove() { if (this._hash) this._hash.remove(); + + for (const control of this._controls) control.onRemove(this); + this._controls = []; + if (this._frame) { this._frame.cancel(); this._frame = null; @@ -1675,9 +1679,6 @@ class Map extends Camera { window.removeEventListener('online', this._onWindowOnline, false); } - for (const control of this._controls) control.onRemove(this); - this._controls = []; - const extension = this.painter.context.gl.getExtension('WEBGL_lose_context'); if (extension) extension.loseContext(); removeNode(this._canvasContainer); diff --git a/test/unit/ui/map.test.js b/test/unit/ui/map.test.js index bb8f96fbe0f..f8edc784e28 100755 --- a/test/unit/ui/map.test.js +++ b/test/unit/ui/map.test.js @@ -817,6 +817,30 @@ test('Map', (t) => { t.end(); }); + t.test('#remove calls onRemove on added controls before style is destroyed', (t) => { + const map = createMap(t); + let onRemoveCalled = 0; + let style; + const control = { + onRemove: function(map) { + onRemoveCalled++; + t.deepEqual(map.getStyle(), style); + }, + onAdd: function (_) { + return window.document.createElement('div'); + } + }; + + map.addControl(control); + + map.on('style.load', () => { + style = map.getStyle(); + map.remove(); + t.equal(onRemoveCalled, 1); + t.end(); + }); + }); + t.test('#addControl', (t) => { const map = createMap(t); const control = {