From fdf226ab69fbf4bdc7aec1e7e646b25c6b4fa7e6 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Wed, 22 Jul 2015 17:13:42 -0700 Subject: [PATCH] feat(exception_handler): change ExceptionHandler to output context --- .../angular2/src/core/exception_handler.ts | 44 +++++---- .../test/core/exception_handler_spec.ts | 90 +++++++++++++++++++ 2 files changed, 119 insertions(+), 15 deletions(-) create mode 100644 modules/angular2/test/core/exception_handler_spec.ts diff --git a/modules/angular2/src/core/exception_handler.ts b/modules/angular2/src/core/exception_handler.ts index cb80e47ee6..3751b38b39 100644 --- a/modules/angular2/src/core/exception_handler.ts +++ b/modules/angular2/src/core/exception_handler.ts @@ -1,5 +1,5 @@ import {Injectable} from 'angular2/di'; -import {isPresent, print} from 'angular2/src/facade/lang'; +import {isPresent, print, BaseException} from 'angular2/src/facade/lang'; import {ListWrapper, isListLikeIterable} from 'angular2/src/facade/collection'; import {DOM} from 'angular2/src/dom/dom_adapter'; @@ -13,15 +13,6 @@ import {DOM} from 'angular2/src/dom/dom_adapter'; * # Example * * ```javascript - * @Component({ - * selector: 'my-app', - * viewInjector: [ - * bind(ExceptionHandler).toClass(MyExceptionHandler) - * ] - * }) - * @View(...) - * class MyApp { ... } - * * * class MyExceptionHandler implements ExceptionHandler { * call(error, stackTrace = null, reason = null) { @@ -29,14 +20,37 @@ import {DOM} from 'angular2/src/dom/dom_adapter'; * } * } * + * bootstrap(MyApp, [bind(ExceptionHandler).toClass(MyExceptionHandler)]) + * * ``` */ @Injectable() export class ExceptionHandler { - call(error: Object, stackTrace: string | List = null, reason: string = null) { - var longStackTrace = - isListLikeIterable(stackTrace) ? ListWrapper.join(stackTrace, "\n\n") : stackTrace; - var reasonStr = isPresent(reason) ? `\n${reason}` : ''; - DOM.logError(`${error}${reasonStr}\nSTACKTRACE:\n${longStackTrace}`); + logError: Function = DOM.logError; + + call(exception: Object, stackTrace: string | string[] = null, reason: string = null) { + var longStackTrace = isListLikeIterable(stackTrace) ? + (stackTrace).join("\n\n-----async gap-----\n") : + stackTrace; + + this.logError(`${exception}\n\n${longStackTrace}`); + + if (isPresent(reason)) { + this.logError(`Reason: ${reason}`); + } + + var context = this._findContext(exception); + if (isPresent(context)) { + this.logError("Error Context:"); + this.logError(context); + } + + throw exception; + } + + _findContext(exception: any): any { + if (!(exception instanceof BaseException)) return null; + return isPresent(exception.context) ? exception.context : + this._findContext(exception.originalException); } } diff --git a/modules/angular2/test/core/exception_handler_spec.ts b/modules/angular2/test/core/exception_handler_spec.ts new file mode 100644 index 0000000000..1985f0320d --- /dev/null +++ b/modules/angular2/test/core/exception_handler_spec.ts @@ -0,0 +1,90 @@ +import { + AsyncTestCompleter, + beforeEach, + ddescribe, + describe, + expect, + iit, + inject, + it, + xdescribe, + xit, + IS_DARTIUM, + Log +} from 'angular2/test_lib'; +import {BaseException} from 'angular2/src/facade/lang'; +import {ExceptionHandler} from 'angular2/src/core/exception_handler'; + +class _CustomException { + context = "some context"; +} + +export function main() { + describe('ExceptionHandler', () => { + var log, handler; + + beforeEach(() => { + log = new Log(); + handler = new ExceptionHandler(); + handler.logError = (e) => log.add(e); + }); + + it("should output exception", () => { + try { + handler.call(new BaseException("message!")); + } catch (e) { + } + expect(log.result()).toContain("message!"); + }); + + it("should output stackTrace", () => { + try { + handler.call(new BaseException("message!"), "stack!"); + } catch (e) { + } + expect(log.result()).toContain("stack!"); + }); + + it("should join a long stackTrace", () => { + try { + handler.call(new BaseException("message!"), ["stack1", "stack2"]); + } catch (e) { + } + expect(log.result()).toContain("stack1"); + expect(log.result()).toContain("stack2"); + }); + + it("should output reason when present", () => { + try { + handler.call(new BaseException("message!"), null, "reason!"); + } catch (e) { + } + expect(log.result()).toContain("reason!"); + }); + + it("should print context", () => { + try { + handler.call(new BaseException("message!", null, null, "context!")); + } catch (e) { + } + expect(log.result()).toContain("context!"); + }); + + it("should print nested context", () => { + try { + var original = new BaseException("message!", null, null, "context!"); + handler.call(new BaseException("message", original)); + } catch (e) { + } + expect(log.result()).toContain("context!"); + }); + + it("should not print context when the passed-in exception is not a BaseException", () => { + try { + handler.call(new _CustomException()); + } catch (e) { + } + expect(log.result()).not.toContain("context"); + }); + }); +}