11import { Injectable } from 'angular2/di' ;
2- import { isPresent , print , BaseException } from 'angular2/src/facade/lang' ;
2+ import { isPresent , isBlank , print , BaseException } from 'angular2/src/facade/lang' ;
33import { ListWrapper , isListLikeIterable } from 'angular2/src/facade/collection' ;
4- import { DOM } from 'angular2/src/dom/dom_adapter' ;
4+
5+ class _ArrayLogger {
6+ res : any [ ] = [ ] ;
7+ log ( s : any ) : void { this . res . push ( s ) ; }
8+ logGroup ( s : any ) : void { this . res . push ( s ) ; }
9+ logGroupEnd ( ) { } ;
10+ }
511
612/**
713 * Provides a hook for centralized exception handling.
@@ -26,31 +32,91 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
2632 */
2733@Injectable ( )
2834export class ExceptionHandler {
29- logError : Function = DOM . logError ;
35+ constructor ( private logger : any , private rethrowException : boolean = true ) { }
3036
31- call ( exception : Object , stackTrace : any = null , reason : string = null ) {
32- var longStackTrace = isListLikeIterable ( stackTrace ) ?
33- ( < any > stackTrace ) . join ( "\n\n-----async gap-----\n" ) :
34- stackTrace ;
37+ static exceptionToString ( exception : any , stackTrace : any = null , reason : string = null ) : string {
38+ var l = new _ArrayLogger ( ) ;
39+ var e = new ExceptionHandler ( l , false ) ;
40+ e . call ( exception , stackTrace , reason ) ;
41+ return l . res . join ( "\n" ) ;
42+ }
3543
36- this . logError ( `${ exception } \n\n${ longStackTrace } ` ) ;
44+ call ( exception : any , stackTrace : any = null , reason : string = null ) : void {
45+ var originalException = this . _findOriginalException ( exception ) ;
46+ var originalStack = this . _findOriginalStack ( exception ) ;
47+ var context = this . _findContext ( exception ) ;
48+
49+ this . logger . logGroup ( `EXCEPTION: ${ exception } ` ) ;
50+
51+ if ( isPresent ( stackTrace ) && isBlank ( originalStack ) ) {
52+ this . logger . log ( "STACKTRACE:" ) ;
53+ this . logger . log ( this . _longStackTrace ( stackTrace ) )
54+ }
3755
3856 if ( isPresent ( reason ) ) {
39- this . logError ( `Reason: ${ reason } ` ) ;
57+ this . logger . log ( `REASON: ${ reason } ` ) ;
58+ }
59+
60+ if ( isPresent ( originalException ) ) {
61+ this . logger . log ( `ORIGINAL EXCEPTION: ${ originalException } ` ) ;
62+ }
63+
64+ if ( isPresent ( originalStack ) ) {
65+ this . logger . log ( "ORIGINAL STACKTRACE:" ) ;
66+ this . logger . log ( this . _longStackTrace ( originalStack ) ) ;
4067 }
4168
42- var context = this . _findContext ( exception ) ;
4369 if ( isPresent ( context ) ) {
44- this . logError ( "Error Context :") ;
45- this . logError ( context ) ;
70+ this . logger . log ( "ERROR CONTEXT :") ;
71+ this . logger . log ( context ) ;
4672 }
4773
48- throw exception ;
74+ this . logger . logGroupEnd ( ) ;
75+
76+ // We rethrow exceptions, so operations like 'bootstrap' will result in an error
77+ // when an exception happens. If we do not rethrow, bootstrap will always succeed.
78+ if ( this . rethrowException ) throw exception ;
79+ }
80+
81+ _longStackTrace ( stackTrace : any ) : any {
82+ return isListLikeIterable ( stackTrace ) ? ( < any > stackTrace ) . join ( "\n\n-----async gap-----\n" ) :
83+ stackTrace ;
4984 }
5085
5186 _findContext ( exception : any ) : any {
87+ try {
88+ if ( ! ( exception instanceof BaseException ) ) return null ;
89+ return isPresent ( exception . context ) ? exception . context :
90+ this . _findContext ( exception . originalException ) ;
91+ } catch ( e ) {
92+ // exception.context can throw an exception. if it happens, we ignore the context.
93+ return null ;
94+ }
95+ }
96+
97+ _findOriginalException ( exception : any ) : any {
5298 if ( ! ( exception instanceof BaseException ) ) return null ;
53- return isPresent ( exception . context ) ? exception . context :
54- this . _findContext ( exception . originalException ) ;
99+
100+ var e = exception . originalException ;
101+ while ( e instanceof BaseException && isPresent ( e . originalException ) ) {
102+ e = e . originalException ;
103+ }
104+
105+ return e ;
106+ }
107+
108+ _findOriginalStack ( exception : any ) : any {
109+ if ( ! ( exception instanceof BaseException ) ) return null ;
110+
111+ var e = exception ;
112+ var stack = exception . originalStack ;
113+ while ( e instanceof BaseException && isPresent ( e . originalException ) ) {
114+ e = e . originalException ;
115+ if ( e instanceof BaseException && isPresent ( e . originalException ) ) {
116+ stack = e . originalStack ;
117+ }
118+ }
119+
120+ return stack ;
55121 }
56122}
0 commit comments