Fix some angular (#16615)

* fix(angular): platform types

fixes #16535

* fix(angular): memory leak in lifecycle events

fixes #16285

* fix ci

* single core
This commit is contained in:
Manu MA
2018-12-06 22:19:35 +01:00
committed by GitHub
parent 119e0c1fd2
commit edf3659949
4 changed files with 44 additions and 28 deletions

View File

@ -1,5 +1,5 @@
import { ApplicationRef, ComponentFactoryResolver, Injectable, InjectionToken, Injector, NgZone, ViewContainerRef } from '@angular/core';
import { FrameworkDelegate, ViewLifecycle } from '@ionic/core';
import { FrameworkDelegate } from '@ionic/core';
import { NavParams } from '../directives/navigation/nav-params';
@ -24,6 +24,7 @@ export class AngularDelegate {
export class AngularFrameworkDelegate implements FrameworkDelegate {
private elRefMap = new WeakMap<HTMLElement, any>();
private elEventsMap = new WeakMap<HTMLElement, () => void>();
constructor(
private resolver: ComponentFactoryResolver,
@ -37,7 +38,8 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
return new Promise(resolve => {
this.zone.run(() => {
const el = attachView(
this.resolver, this.injector, this.location, this.appRef, this.elRefMap,
this.resolver, this.injector, this.location, this.appRef,
this.elRefMap, this.elEventsMap,
container, component, params, cssClasses
);
resolve(el);
@ -52,6 +54,11 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
if (componentRef) {
componentRef.destroy();
this.elRefMap.delete(component);
const unbindEvents = this.elEventsMap.get(component);
if (unbindEvents) {
unbindEvents();
this.elEventsMap.delete(component);
}
}
resolve();
});
@ -65,6 +72,7 @@ export function attachView(
location: ViewContainerRef | undefined,
appRef: ApplicationRef,
elRefMap: WeakMap<HTMLElement, any>,
elEventsMap: WeakMap<HTMLElement, () => void>,
container: any, component: any, params: any, cssClasses: string[] | undefined
) {
const factory = resolver.resolveComponentFactory(component);
@ -86,34 +94,41 @@ export function attachView(
hostElement.classList.add(clazz);
}
}
bindLifecycleEvents(instance, hostElement);
const unbindEvents = bindLifecycleEvents(instance, hostElement);
container.appendChild(hostElement);
if (!location) {
appRef.attachView(componentRef.hostView);
}
componentRef.changeDetectorRef.reattach();
elRefMap.set(hostElement, componentRef);
elEventsMap.set(hostElement, unbindEvents);
return hostElement;
}
const LIFECYCLES = [
ViewLifecycle.WillEnter,
ViewLifecycle.DidEnter,
ViewLifecycle.WillLeave,
ViewLifecycle.DidLeave,
ViewLifecycle.WillUnload
'ionViewWillEnter',
'ionViewDidEnter',
'ionViewWillLeave',
'ionViewDidLeave',
'ionViewWillUnload'
];
export function bindLifecycleEvents(instance: any, element: HTMLElement) {
LIFECYCLES.forEach(eventName => {
element.addEventListener(eventName, (ev: any) => {
const unregisters = LIFECYCLES.map(eventName => {
const handler = (ev: any) => {
if (typeof instance[eventName] === 'function') {
instance[eventName](ev.detail);
}
});
};
element.addEventListener(eventName, handler);
return () => {
element.removeEventListener(eventName, handler);
};
});
return () => {
unregisters.forEach(fn => fn());
};
}
const NavParamsToken = new InjectionToken<any>('NavParamsToken');