feat(exception_handler): print originalException and originalStack for all exceptions

This commit is contained in:
vsavkin
2015-07-23 18:00:19 -07:00
parent 0a8b3816f7
commit e744409cb9
18 changed files with 259 additions and 120 deletions

View File

@ -64,7 +64,6 @@ import {
} from 'angular2/src/render/dom/dom_renderer';
import {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler';
import {internalView} from 'angular2/src/core/compiler/view_ref';
import {appComponentRefPromiseToken, appComponentTypeToken} from './application_tokens';
var _rootInjector: Injector;
@ -129,7 +128,7 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
DirectiveResolver,
Parser,
Lexer,
ExceptionHandler,
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(DOM)),
bind(XHR).toValue(new XHRImpl()),
ComponentUrlMapper,
UrlResolver,
@ -282,8 +281,7 @@ export function commonBootstrap(
componentInjectableBindings: List<Type | Binding | List<any>> = null): Promise<ApplicationRef> {
BrowserDomAdapter.makeCurrent();
var bootstrapProcess = PromiseWrapper.completer();
var zone = createNgZone(new ExceptionHandler());
var zone = createNgZone(new ExceptionHandler(DOM));
zone.run(() => {
// TODO(rado): prepopulate template cache, so applications with only
// index.html and main.js are possible.

View File

@ -1,7 +1,13 @@
import {Injectable} from 'angular2/di';
import {isPresent, print, BaseException} from 'angular2/src/facade/lang';
import {isPresent, isBlank, print, BaseException} from 'angular2/src/facade/lang';
import {ListWrapper, isListLikeIterable} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/dom/dom_adapter';
class _ArrayLogger {
res: any[] = [];
log(s: any): void { this.res.push(s); }
logGroup(s: any): void { this.res.push(s); }
logGroupEnd(){};
}
/**
* Provides a hook for centralized exception handling.
@ -26,31 +32,91 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
*/
@Injectable()
export class ExceptionHandler {
logError: Function = DOM.logError;
constructor(private logger: any, private rethrowException: boolean = true) {}
call(exception: Object, stackTrace: any = null, reason: string = null) {
var longStackTrace = isListLikeIterable(stackTrace) ?
(<any>stackTrace).join("\n\n-----async gap-----\n") :
stackTrace;
static exceptionToString(exception: any, stackTrace: any = null, reason: string = null): string {
var l = new _ArrayLogger();
var e = new ExceptionHandler(l, false);
e.call(exception, stackTrace, reason);
return l.res.join("\n");
}
this.logError(`${exception}\n\n${longStackTrace}`);
call(exception: any, stackTrace: any = null, reason: string = null): void {
var originalException = this._findOriginalException(exception);
var originalStack = this._findOriginalStack(exception);
var context = this._findContext(exception);
this.logger.logGroup(`EXCEPTION: ${exception}`);
if (isPresent(stackTrace) && isBlank(originalStack)) {
this.logger.log("STACKTRACE:");
this.logger.log(this._longStackTrace(stackTrace))
}
if (isPresent(reason)) {
this.logError(`Reason: ${reason}`);
this.logger.log(`REASON: ${reason}`);
}
if (isPresent(originalException)) {
this.logger.log(`ORIGINAL EXCEPTION: ${originalException}`);
}
if (isPresent(originalStack)) {
this.logger.log("ORIGINAL STACKTRACE:");
this.logger.log(this._longStackTrace(originalStack));
}
var context = this._findContext(exception);
if (isPresent(context)) {
this.logError("Error Context:");
this.logError(context);
this.logger.log("ERROR CONTEXT:");
this.logger.log(context);
}
throw exception;
this.logger.logGroupEnd();
// We rethrow exceptions, so operations like 'bootstrap' will result in an error
// when an exception happens. If we do not rethrow, bootstrap will always succeed.
if (this.rethrowException) throw exception;
}
_longStackTrace(stackTrace: any): any {
return isListLikeIterable(stackTrace) ? (<any>stackTrace).join("\n\n-----async gap-----\n") :
stackTrace;
}
_findContext(exception: any): any {
try {
if (!(exception instanceof BaseException)) return null;
return isPresent(exception.context) ? exception.context :
this._findContext(exception.originalException);
} catch (e) {
// exception.context can throw an exception. if it happens, we ignore the context.
return null;
}
}
_findOriginalException(exception: any): any {
if (!(exception instanceof BaseException)) return null;
return isPresent(exception.context) ? exception.context :
this._findContext(exception.originalException);
var e = exception.originalException;
while (e instanceof BaseException && isPresent(e.originalException)) {
e = e.originalException;
}
return e;
}
_findOriginalStack(exception: any): any {
if (!(exception instanceof BaseException)) return null;
var e = exception;
var stack = exception.originalStack;
while (e instanceof BaseException && isPresent(e.originalException)) {
e = e.originalException;
if (e instanceof BaseException && isPresent(e.originalException)) {
stack = e.originalStack;
}
}
return stack;
}
}