Scrubbing of detached DOM elements, prevents memory leaks (#5265)
* Scrubbing of detached DOM elements, prevents memory leaks and fixes #5263 * Make linter happy
This commit is contained in:
parent
5603a87c70
commit
14c5f1602c
@ -161,6 +161,11 @@ Map.include({
|
||||
},
|
||||
|
||||
_clearControlPos: function () {
|
||||
for (var i in this._controlCorners) {
|
||||
DomUtil.remove(this._controlCorners[i]);
|
||||
}
|
||||
DomUtil.remove(this._controlContainer);
|
||||
delete this._controlCorners;
|
||||
delete this._controlContainer;
|
||||
}
|
||||
});
|
||||
|
@ -23,7 +23,6 @@ export var _pointersCount = 0;
|
||||
// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
|
||||
|
||||
export function addPointerListener(obj, type, handler, id) {
|
||||
|
||||
if (type === 'touchstart') {
|
||||
_addPointerStart(obj, handler, id);
|
||||
|
||||
|
@ -37,6 +37,8 @@ export function on(obj, types, fn, context) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var eventsKey = '_leaflet_events';
|
||||
|
||||
// @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this
|
||||
// Removes a previously added listener function. If no function is specified,
|
||||
// it will remove all the listeners of that particular DOM event from the element.
|
||||
@ -46,25 +48,30 @@ export function on(obj, types, fn, context) {
|
||||
// @alternative
|
||||
// @function off(el: HTMLElement, eventMap: Object, context?: Object): this
|
||||
// Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
|
||||
|
||||
// @alternative
|
||||
// @function off(el: HTMLElement): this
|
||||
// Removes all known event listeners
|
||||
export function off(obj, types, fn, context) {
|
||||
|
||||
if (typeof types === 'object') {
|
||||
for (var type in types) {
|
||||
removeOne(obj, type, types[type], fn);
|
||||
}
|
||||
} else {
|
||||
} else if (types) {
|
||||
types = Util.splitWords(types);
|
||||
|
||||
for (var i = 0, len = types.length; i < len; i++) {
|
||||
removeOne(obj, types[i], fn, context);
|
||||
}
|
||||
} else {
|
||||
for (var j in obj[eventsKey]) {
|
||||
removeOne(obj, j, obj[eventsKey][j]);
|
||||
}
|
||||
delete obj[eventsKey];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
var eventsKey = '_leaflet_events';
|
||||
|
||||
function addOne(obj, type, fn, context) {
|
||||
var id = type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : '');
|
||||
|
||||
|
@ -67,6 +67,13 @@ export var Canvas = Renderer.extend({
|
||||
this._ctx = container.getContext('2d');
|
||||
},
|
||||
|
||||
_destroyContainer: function () {
|
||||
delete this._ctx;
|
||||
L.DomUtil.remove(this._container);
|
||||
L.DomEvent.off(this._container);
|
||||
delete this._container;
|
||||
},
|
||||
|
||||
_updatePaths: function () {
|
||||
if (this._postponeUpdatePaths) { return; }
|
||||
|
||||
|
@ -58,8 +58,8 @@ export var Renderer = Layer.extend({
|
||||
},
|
||||
|
||||
onRemove: function () {
|
||||
DomUtil.remove(this._container);
|
||||
this.off('update', this._updatePaths, this);
|
||||
this._destroyContainer();
|
||||
},
|
||||
|
||||
getEvents: function () {
|
||||
|
@ -61,6 +61,13 @@ export var SVG = Renderer.extend({
|
||||
this._container.appendChild(this._rootGroup);
|
||||
},
|
||||
|
||||
_destroyContainer: function () {
|
||||
L.DomUtil.remove(this._container);
|
||||
L.DomEvent.off(this._container);
|
||||
delete this._container;
|
||||
delete this._rootGroup;
|
||||
},
|
||||
|
||||
_onZoomStart: function () {
|
||||
// Drag-then-pinch interactions might mess up the center and zoom.
|
||||
// In this case, the easiest way to prevent this is re-do the renderer
|
||||
|
@ -716,9 +716,18 @@ export var Map = Evented.extend({
|
||||
this.fire('unload');
|
||||
}
|
||||
|
||||
for (var i in this._layers) {
|
||||
var i;
|
||||
for (i in this._layers) {
|
||||
this._layers[i].remove();
|
||||
}
|
||||
for (i in this._panes) {
|
||||
L.DomUtil.remove(this._panes[i]);
|
||||
}
|
||||
|
||||
this._layers = [];
|
||||
this._panes = [];
|
||||
delete this._mapPane;
|
||||
delete this._renderer;
|
||||
|
||||
return this;
|
||||
},
|
||||
@ -1507,12 +1516,12 @@ export var Map = Evented.extend({
|
||||
|
||||
this.on('zoomanim', function (e) {
|
||||
var prop = DomUtil.TRANSFORM,
|
||||
transform = proxy.style[prop];
|
||||
transform = this._proxy.style[prop];
|
||||
|
||||
DomUtil.setTransform(proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));
|
||||
DomUtil.setTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));
|
||||
|
||||
// workaround for case when transform is the same and so transitionend event is not fired
|
||||
if (transform === proxy.style[prop] && this._animatingZoom) {
|
||||
if (transform === this._proxy.style[prop] && this._animatingZoom) {
|
||||
this._onZoomTransitionEnd();
|
||||
}
|
||||
}, this);
|
||||
@ -1520,8 +1529,15 @@ export var Map = Evented.extend({
|
||||
this.on('load moveend', function () {
|
||||
var c = this.getCenter(),
|
||||
z = this.getZoom();
|
||||
DomUtil.setTransform(proxy, this.project(c, z), this.getZoomScale(z, 1));
|
||||
DomUtil.setTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1));
|
||||
}, this);
|
||||
|
||||
this._on('unload', this._destroyAnimProxy, this);
|
||||
},
|
||||
|
||||
_destroyAnimProxy: function () {
|
||||
L.DomUtil.remove(this._proxy);
|
||||
delete this._proxy;
|
||||
},
|
||||
|
||||
_catchTransitionEnd: function (e) {
|
||||
|
@ -25,6 +25,7 @@ export var BoxZoom = Handler.extend({
|
||||
this._map = map;
|
||||
this._container = map._container;
|
||||
this._pane = map._panes.overlayPane;
|
||||
map.on('unload', this._destroy, this);
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
@ -39,6 +40,11 @@ export var BoxZoom = Handler.extend({
|
||||
return this._moved;
|
||||
},
|
||||
|
||||
_destroy: function () {
|
||||
L.DomUtil.remove(this._pane);
|
||||
delete this._pane;
|
||||
},
|
||||
|
||||
_resetState: function () {
|
||||
this._moved = false;
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user