fix(core): always remove DOM listeners and stream subscriptions
This is needed to prevent memory leaks. The DOM listeners don’t need to be removed for simple examples, but a big internal app shows memory leaks because of them. BREAKING CHANGE: - `Renderer.listen` now has to return a function that removes the event listener.
This commit is contained in:
@ -66,12 +66,12 @@ export class MessageBasedRenderer {
|
||||
bind(this._invokeElementMethod, this));
|
||||
broker.registerMethod("setText", [RenderStoreObject, RenderStoreObject, PRIMITIVE],
|
||||
bind(this._setText, this));
|
||||
broker.registerMethod("listen", [RenderStoreObject, RenderStoreObject, PRIMITIVE],
|
||||
broker.registerMethod("listen", [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
bind(this._listen, this));
|
||||
broker.registerMethod("listenGlobal", [RenderStoreObject, PRIMITIVE, PRIMITIVE, PRIMITIVE],
|
||||
bind(this._listenGlobal, this));
|
||||
broker.registerMethod("listenGlobalDone", [RenderStoreObject, RenderStoreObject],
|
||||
bind(this._listenGlobalDone, this));
|
||||
broker.registerMethod("listenDone", [RenderStoreObject, RenderStoreObject],
|
||||
bind(this._listenDone, this));
|
||||
}
|
||||
|
||||
private _renderComponent(renderComponentType: RenderComponentType, rendererId: number) {
|
||||
@ -155,9 +155,11 @@ export class MessageBasedRenderer {
|
||||
renderer.setText(renderNode, text);
|
||||
}
|
||||
|
||||
private _listen(renderer: Renderer, renderElement: any, eventName: string) {
|
||||
renderer.listen(renderElement, eventName, (event) => this._eventDispatcher.dispatchRenderEvent(
|
||||
renderElement, null, eventName, event));
|
||||
private _listen(renderer: Renderer, renderElement: any, eventName: string, unlistenId: number) {
|
||||
var unregisterCallback = renderer.listen(renderElement, eventName,
|
||||
(event) => this._eventDispatcher.dispatchRenderEvent(
|
||||
renderElement, null, eventName, event));
|
||||
this._renderStore.store(unregisterCallback, unlistenId);
|
||||
}
|
||||
|
||||
private _listenGlobal(renderer: Renderer, eventTarget: string, eventName: string,
|
||||
@ -168,5 +170,5 @@ export class MessageBasedRenderer {
|
||||
this._renderStore.store(unregisterCallback, unlistenId);
|
||||
}
|
||||
|
||||
private _listenGlobalDone(renderer: Renderer, unlistenCallback: Function) { unlistenCallback(); }
|
||||
private _listenDone(renderer: Renderer, unlistenCallback: Function) { unlistenCallback(); }
|
||||
}
|
||||
|
@ -215,10 +215,18 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
|
||||
[new FnArg(renderNode, RenderStoreObject), new FnArg(text, null)]);
|
||||
}
|
||||
|
||||
listen(renderElement: WebWorkerRenderNode, name: string, callback: Function) {
|
||||
listen(renderElement: WebWorkerRenderNode, name: string, callback: Function): Function {
|
||||
renderElement.events.listen(name, callback);
|
||||
this._runOnService('listen',
|
||||
[new FnArg(renderElement, RenderStoreObject), new FnArg(name, null)]);
|
||||
var unlistenCallbackId = this._rootRenderer.allocateId();
|
||||
this._runOnService('listen', [
|
||||
new FnArg(renderElement, RenderStoreObject),
|
||||
new FnArg(name, null),
|
||||
new FnArg(unlistenCallbackId, null)
|
||||
]);
|
||||
return () => {
|
||||
renderElement.events.unlisten(name, callback);
|
||||
this._runOnService('listenDone', [new FnArg(unlistenCallbackId, null)]);
|
||||
};
|
||||
}
|
||||
|
||||
listenGlobal(target: string, name: string, callback: Function): Function {
|
||||
@ -229,7 +237,7 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
|
||||
[new FnArg(target, null), new FnArg(name, null), new FnArg(unlistenCallbackId, null)]);
|
||||
return () => {
|
||||
this._rootRenderer.globalEvents.unlisten(eventNameWithTarget(target, name), callback);
|
||||
this._runOnService('listenGlobalDone', [new FnArg(unlistenCallbackId, null)]);
|
||||
this._runOnService('listenDone', [new FnArg(unlistenCallbackId, null)]);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user