mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 21:48:42 +08:00
fix(navcontroller): exceptions inside lifecycle events are printed properly
fixes #10974
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
import { AfterViewInit, Component, ComponentFactoryResolver, ElementRef, forwardRef, Input, Optional, NgZone, Renderer, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
|
import { AfterViewInit, Component, ComponentFactoryResolver, ElementRef, ErrorHandler, forwardRef, Input, Optional, NgZone, Renderer, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
|
||||||
|
|
||||||
import { App } from '../app/app';
|
import { App } from '../app/app';
|
||||||
import { Config } from '../../config/config';
|
import { Config } from '../../config/config';
|
||||||
@ -74,8 +74,9 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode {
|
|||||||
transCtrl: TransitionController,
|
transCtrl: TransitionController,
|
||||||
@Optional() linker: DeepLinker,
|
@Optional() linker: DeepLinker,
|
||||||
domCtrl: DomController,
|
domCtrl: DomController,
|
||||||
|
errHandler: ErrorHandler
|
||||||
) {
|
) {
|
||||||
super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl);
|
super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl, errHandler);
|
||||||
|
|
||||||
if (viewCtrl) {
|
if (viewCtrl) {
|
||||||
// an ion-nav can also act as an ion-page within a parent ion-nav
|
// an ion-nav can also act as an ion-page within a parent ion-nav
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ComponentFactoryResolver, Directive, ElementRef, forwardRef, Inject, Input, NgZone, Optional, Renderer, ViewContainerRef } from '@angular/core';
|
import { ComponentFactoryResolver, Directive, ElementRef, ErrorHandler, forwardRef, Inject, Input, NgZone, Optional, Renderer, ViewContainerRef } from '@angular/core';
|
||||||
|
|
||||||
import { App } from '../app/app';
|
import { App } from '../app/app';
|
||||||
import { Config } from '../../config/config';
|
import { Config } from '../../config/config';
|
||||||
@ -31,8 +31,9 @@ export class OverlayPortal extends NavControllerBase {
|
|||||||
@Optional() linker: DeepLinker,
|
@Optional() linker: DeepLinker,
|
||||||
viewPort: ViewContainerRef,
|
viewPort: ViewContainerRef,
|
||||||
domCtrl: DomController,
|
domCtrl: DomController,
|
||||||
|
errHandler: ErrorHandler
|
||||||
) {
|
) {
|
||||||
super(null, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl);
|
super(null, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl, errHandler);
|
||||||
this._isPortal = true;
|
this._isPortal = true;
|
||||||
this._init = true;
|
this._init = true;
|
||||||
this.setViewport(viewPort);
|
this.setViewport(viewPort);
|
||||||
|
@ -109,7 +109,8 @@ function getNav() {
|
|||||||
gestureCtrl,
|
gestureCtrl,
|
||||||
trnsCtrl,
|
trnsCtrl,
|
||||||
linker,
|
linker,
|
||||||
dom
|
dom,
|
||||||
|
null
|
||||||
);
|
);
|
||||||
return nav;
|
return nav;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectorRef, Component, ComponentFactoryResolver, ComponentRef, ElementRef, EventEmitter, Input, NgZone, Optional, Output, Renderer, ViewChild, ViewEncapsulation, ViewContainerRef } from '@angular/core';
|
import { ChangeDetectorRef, Component, ComponentFactoryResolver, ComponentRef, ElementRef, ErrorHandler, EventEmitter, Input, NgZone, Optional, Output, Renderer, ViewChild, ViewEncapsulation, ViewContainerRef } from '@angular/core';
|
||||||
|
|
||||||
import { App } from '../app/app';
|
import { App } from '../app/app';
|
||||||
import { Config } from '../../config/config';
|
import { Config } from '../../config/config';
|
||||||
@ -264,9 +264,10 @@ export class Tab extends NavControllerBase {
|
|||||||
transCtrl: TransitionController,
|
transCtrl: TransitionController,
|
||||||
@Optional() private linker: DeepLinker,
|
@Optional() private linker: DeepLinker,
|
||||||
private _dom: DomController,
|
private _dom: DomController,
|
||||||
|
errHandler: ErrorHandler
|
||||||
) {
|
) {
|
||||||
// A Tab is a NavController for its child pages
|
// A Tab is a NavController for its child pages
|
||||||
super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, _dom);
|
super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, _dom, errHandler);
|
||||||
|
|
||||||
this.id = parent.add(this);
|
this.id = parent.add(this);
|
||||||
this._tabsHideOnSubPages = config.getBoolean('tabsHideOnSubPages');
|
this._tabsHideOnSubPages = config.getBoolean('tabsHideOnSubPages');
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ComponentRef, Input, ComponentFactoryResolver, ElementRef, EventEmitter, NgZone, ReflectiveInjector, Renderer, ViewContainerRef } from '@angular/core';
|
import { ComponentRef, Input, ComponentFactoryResolver, ElementRef, ErrorHandler, EventEmitter, NgZone, ReflectiveInjector, Renderer, ViewContainerRef } from '@angular/core';
|
||||||
|
|
||||||
import { AnimationOptions } from '../animations/animation';
|
import { AnimationOptions } from '../animations/animation';
|
||||||
import { App } from '../components/app/app';
|
import { App } from '../components/app/app';
|
||||||
@ -71,7 +71,8 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
public _gestureCtrl: GestureController,
|
public _gestureCtrl: GestureController,
|
||||||
public _trnsCtrl: TransitionController,
|
public _trnsCtrl: TransitionController,
|
||||||
public _linker: DeepLinker,
|
public _linker: DeepLinker,
|
||||||
private _domCtrl: DomController
|
private _domCtrl: DomController,
|
||||||
|
private _errHandler: ErrorHandler
|
||||||
) {
|
) {
|
||||||
super(config, elementRef, renderer);
|
super(config, elementRef, renderer);
|
||||||
|
|
||||||
@ -350,7 +351,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
if (nav && nav !== this) {
|
if (nav && nav !== this) {
|
||||||
throw 'inserted view was already inserted';
|
throw 'inserted view was already inserted';
|
||||||
}
|
}
|
||||||
if (viewControllers[i]._state === STATE_DESTROYED) {
|
if (view._state === STATE_DESTROYED) {
|
||||||
throw 'inserted view was already destroyed';
|
throw 'inserted view was already destroyed';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -857,61 +858,89 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
_willLoad(view: ViewController) {
|
_willLoad(view: ViewController) {
|
||||||
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
||||||
|
|
||||||
view._willLoad();
|
try {
|
||||||
|
view._willLoad();
|
||||||
|
} catch (e) {
|
||||||
|
this._errHandler && this._errHandler.handleError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_didLoad(view: ViewController) {
|
_didLoad(view: ViewController) {
|
||||||
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
||||||
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
||||||
|
|
||||||
view._didLoad();
|
try {
|
||||||
this.viewDidLoad.emit(view);
|
view._didLoad();
|
||||||
this._app.viewDidLoad.emit(view);
|
this.viewDidLoad.emit(view);
|
||||||
|
this._app.viewDidLoad.emit(view);
|
||||||
|
} catch (e) {
|
||||||
|
this._errHandler && this._errHandler.handleError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_willEnter(view: ViewController) {
|
_willEnter(view: ViewController) {
|
||||||
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
||||||
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
||||||
|
|
||||||
view._willEnter();
|
try {
|
||||||
this.viewWillEnter.emit(view);
|
view._willEnter();
|
||||||
this._app.viewWillEnter.emit(view);
|
this.viewWillEnter.emit(view);
|
||||||
|
this._app.viewWillEnter.emit(view);
|
||||||
|
} catch (e) {
|
||||||
|
this._errHandler && this._errHandler.handleError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_didEnter(view: ViewController) {
|
_didEnter(view: ViewController) {
|
||||||
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
||||||
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
||||||
|
|
||||||
view._didEnter();
|
try {
|
||||||
this.viewDidEnter.emit(view);
|
view._didEnter();
|
||||||
this._app.viewDidEnter.emit(view);
|
this.viewDidEnter.emit(view);
|
||||||
|
this._app.viewDidEnter.emit(view);
|
||||||
|
} catch (e) {
|
||||||
|
this._errHandler && this._errHandler.handleError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_willLeave(view: ViewController, willUnload: boolean) {
|
_willLeave(view: ViewController, willUnload: boolean) {
|
||||||
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
||||||
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
||||||
|
|
||||||
view._willLeave(willUnload);
|
try {
|
||||||
this.viewWillLeave.emit(view);
|
view._willLeave(willUnload);
|
||||||
this._app.viewWillLeave.emit(view);
|
this.viewWillLeave.emit(view);
|
||||||
|
this._app.viewWillLeave.emit(view);
|
||||||
|
} catch (e) {
|
||||||
|
this._errHandler && this._errHandler.handleError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_didLeave(view: ViewController) {
|
_didLeave(view: ViewController) {
|
||||||
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
||||||
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
||||||
|
|
||||||
view._didLeave();
|
try {
|
||||||
this.viewDidLeave.emit(view);
|
view._didLeave();
|
||||||
this._app.viewDidLeave.emit(view);
|
this.viewDidLeave.emit(view);
|
||||||
|
this._app.viewDidLeave.emit(view);
|
||||||
|
} catch (e) {
|
||||||
|
this._errHandler && this._errHandler.handleError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_willUnload(view: ViewController) {
|
_willUnload(view: ViewController) {
|
||||||
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
assert(this.isTransitioning(), 'nav controller should be transitioning');
|
||||||
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
assert(NgZone.isInAngularZone(), 'callback should be zoned');
|
||||||
|
|
||||||
view._willUnload();
|
try {
|
||||||
this.viewWillUnload.emit(view);
|
view._willUnload();
|
||||||
this._app.viewWillUnload.emit(view);
|
this.viewWillUnload.emit(view);
|
||||||
|
this._app.viewWillUnload.emit(view);
|
||||||
|
} catch (e) {
|
||||||
|
this._errHandler && this._errHandler.handleError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hasChildren(): boolean {
|
hasChildren(): boolean {
|
||||||
|
@ -105,7 +105,11 @@ export class ViewController {
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Output() private _emitter: EventEmitter<any> = new EventEmitter();
|
@Output() private _emitter: EventEmitter<any> = new EventEmitter();
|
||||||
|
|
||||||
constructor(public component?: any, data?: any, rootCssClass: string = DEFAULT_CSS_CLASS) {
|
constructor(
|
||||||
|
public component?: any,
|
||||||
|
data?: any,
|
||||||
|
rootCssClass: string = DEFAULT_CSS_CLASS
|
||||||
|
) {
|
||||||
// passed in data could be NavParams, but all we care about is its data object
|
// passed in data could be NavParams, but all we care about is its data object
|
||||||
this.data = (data instanceof NavParams ? data.data : (isPresent(data) ? data : {}));
|
this.data = (data instanceof NavParams ? data.data : (isPresent(data) ? data : {}));
|
||||||
|
|
||||||
@ -541,7 +545,7 @@ export class ViewController {
|
|||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
_lifecycleTest(lifecycle: string): Promise<any> {
|
_lifecycleTest(lifecycle: string): Promise<boolean> {
|
||||||
const instance = this.instance;
|
const instance = this.instance;
|
||||||
const methodName = 'ionViewCan' + lifecycle;
|
const methodName = 'ionViewCan' + lifecycle;
|
||||||
if (instance && instance[methodName]) {
|
if (instance && instance[methodName]) {
|
||||||
@ -561,16 +565,14 @@ export class ViewController {
|
|||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
_lifecycle(lifecycle: string) {
|
_lifecycle(lifecycle: string) {
|
||||||
const instance = this.instance;
|
const instance = this.instance;
|
||||||
const methodName = 'ionView' + lifecycle;
|
const methodName = 'ionView' + lifecycle;
|
||||||
if (instance && instance[methodName]) {
|
if (instance && instance[methodName]) {
|
||||||
try {
|
instance[methodName]();
|
||||||
instance[methodName]();
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`${this.name} ${methodName} error: ${e.message}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +423,8 @@ export function mockNavController(): NavControllerBase {
|
|||||||
gestureCtrl,
|
gestureCtrl,
|
||||||
trnsCtrl,
|
trnsCtrl,
|
||||||
linker,
|
linker,
|
||||||
dom
|
dom,
|
||||||
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
nav._viewInit = function(enteringView: ViewController) {
|
nav._viewInit = function(enteringView: ViewController) {
|
||||||
@ -468,7 +469,8 @@ export function mockOverlayPortal(app: App, config: Config, plt: MockPlatform):
|
|||||||
null,
|
null,
|
||||||
deepLinker,
|
deepLinker,
|
||||||
null,
|
null,
|
||||||
dom
|
dom,
|
||||||
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +502,8 @@ export function mockTab(parentTabs: Tabs): Tab {
|
|||||||
gestureCtrl,
|
gestureCtrl,
|
||||||
null,
|
null,
|
||||||
linker,
|
linker,
|
||||||
dom
|
dom,
|
||||||
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
tab.load = (opts: any, cb: Function) => {
|
tab.load = (opts: any, cb: Function) => {
|
||||||
|
Reference in New Issue
Block a user