fix(exception_handler): log errors via `console.error`

This is e.g. needed as we use this to test for errors
in our examples.
This commit is contained in:
Tobias Bosch 2015-04-30 11:25:50 -07:00
parent 87dcd5eb6f
commit ead21c91a4
10 changed files with 52 additions and 20 deletions

View File

@ -134,7 +134,7 @@ function _injectorBindings(appComponentType): List<Binding> {
function _createVmZone(givenReporter:Function): VmTurnZone { function _createVmZone(givenReporter:Function): VmTurnZone {
var defaultErrorReporter = (exception, stackTrace) => { var defaultErrorReporter = (exception, stackTrace) => {
var longStackTrace = ListWrapper.join(stackTrace, "\n\n-----async gap-----\n"); var longStackTrace = ListWrapper.join(stackTrace, "\n\n-----async gap-----\n");
print(`${exception}\n\n${longStackTrace}`); DOM.logError(`${exception}\n\n${longStackTrace}`);
throw exception; throw exception;
}; };

View File

@ -1,6 +1,7 @@
import {Injectable} from 'angular2/di'; import {Injectable} from 'angular2/di';
import {isPresent, print} from 'angular2/src/facade/lang'; import {isPresent, print} from 'angular2/src/facade/lang';
import {ListWrapper, isListLikeIterable} from 'angular2/src/facade/collection'; import {ListWrapper, isListLikeIterable} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/dom/dom_adapter';
/** /**
* Provides a hook for centralized exception handling. * Provides a hook for centralized exception handling.
@ -36,6 +37,6 @@ export class ExceptionHandler {
call(error, stackTrace = null, reason = null) { call(error, stackTrace = null, reason = null) {
var longStackTrace = isListLikeIterable(stackTrace) ? ListWrapper.join(stackTrace, "\n\n") : stackTrace; var longStackTrace = isListLikeIterable(stackTrace) ? ListWrapper.join(stackTrace, "\n\n") : stackTrace;
var reasonStr = isPresent(reason) ? `\n${reason}` : ''; var reasonStr = isPresent(reason) ? `\n${reason}` : '';
print(`${error}${reasonStr}\nSTACKTRACE:\n${longStackTrace}`); DOM.logError(`${error}${reasonStr}\nSTACKTRACE:\n${longStackTrace}`);
} }
} }

View File

@ -100,6 +100,10 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
setRootDomAdapter(new BrowserDomAdapter()); setRootDomAdapter(new BrowserDomAdapter());
} }
logError(error) {
window.console.error(error);
}
@override @override
Map<String, String> get attrToPropMap => const <String, String>{ Map<String, String> get attrToPropMap => const <String, String>{
'innerHtml': 'innerHtml', 'innerHtml': 'innerHtml',

View File

@ -57,6 +57,10 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
setRootDomAdapter(new BrowserDomAdapter()); setRootDomAdapter(new BrowserDomAdapter());
} }
logError(error) {
window.console.error(error);
}
get attrToPropMap() { get attrToPropMap() {
return _attrToPropMap; return _attrToPropMap;
} }

View File

@ -16,6 +16,10 @@ function _abstract() {
@ABSTRACT() @ABSTRACT()
export class DomAdapter { export class DomAdapter {
logError(error) {
throw _abstract();
}
/** /**
* Maps attribute names to their corresponding property names for cases * Maps attribute names to their corresponding property names for cases
* where attribute name doesn't match property name. * where attribute name doesn't match property name.

View File

@ -3,12 +3,17 @@ library angular2.dom.htmlAdapter;
import 'dom_adapter.dart'; import 'dom_adapter.dart';
import 'package:html/parser.dart' as parser; import 'package:html/parser.dart' as parser;
import 'package:html/dom.dart'; import 'package:html/dom.dart';
import 'dart:io';
class Html5LibDomAdapter implements DomAdapter { class Html5LibDomAdapter implements DomAdapter {
static void makeCurrent() { static void makeCurrent() {
setRootDomAdapter(new Html5LibDomAdapter()); setRootDomAdapter(new Html5LibDomAdapter());
} }
logError(error) {
stderr.writeln('${error}');
}
@override @override
final attrToPropMap = const { final attrToPropMap = const {
'innerHtml': 'innerHtml', 'innerHtml': 'innerHtml',

View File

@ -28,6 +28,10 @@ export class Parse5DomAdapter extends DomAdapter {
setRootDomAdapter(new Parse5DomAdapter()); setRootDomAdapter(new Parse5DomAdapter());
} }
logError(error) {
console.error(error);
}
get attrToPropMap() { get attrToPropMap() {
return _attrToPropMap; return _attrToPropMap;
} }

View File

@ -6,6 +6,9 @@ describe('sourcemaps', function () {
it('should map sources', function() { it('should map sources', function() {
browser.get(URL); browser.get(URL);
$('error-app .errorButton').click();
// TODO(tbosch): Bug in ChromeDriver: Need to execute at least one command // TODO(tbosch): Bug in ChromeDriver: Need to execute at least one command
// so that the browser logs can be read out! // so that the browser logs can be read out!
browser.executeScript('1+1'); browser.executeScript('1+1');
@ -13,7 +16,7 @@ describe('sourcemaps', function () {
var errorLine = null; var errorLine = null;
var errorColumn = null; var errorColumn = null;
logs.forEach(function(log) { logs.forEach(function(log) {
var match = /Test\.run\s+\(.+:(\d+):(\d+)/m.exec(log.message); var match = /\.createError\s+\(.+:(\d+):(\d+)/m.exec(log.message);
if (match) { if (match) {
errorLine = parseInt(match[1]); errorLine = parseInt(match[1]);
errorColumn = parseInt(match[2]); errorColumn = parseInt(match[2]);

View File

@ -2,8 +2,15 @@
<html> <html>
<title>Sourcemaps</title> <title>Sourcemaps</title>
<body> <body>
<error-app>
Loading...
</error-app>
<p>
Please look into the console and check whether the stack trace is mapped Please look into the console and check whether the stack trace is mapped
via source maps! via source maps!
</p>
$SCRIPTS$ $SCRIPTS$
</body> </body>
</html> </html>

View File

@ -1,24 +1,24 @@
import { BaseException, print, CONST } from 'angular2/src/facade/lang'; import { BaseException, print, CONST } from 'angular2/src/facade/lang';
import { bootstrap } from 'angular2/angular2';
// TODO(radokirov): Once the application is transpiled by TS instead of Traceur,
// add those imports back into 'angular2/angular2';
import {Component} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view';
class TestAnnotation { @Component({
@CONST() selector: 'error-app',
constructor() {} })
} @View({
template: `
// Use a class with an annotation, <button class="errorButton" (click)="createError()">create error</button>`,
// as this is where we expect the most source code changes directives: []
// through compilation. })
@TestAnnotation() export class ErrorComponent {
class Test { createError() {
run() { throw new BaseException('Sourcemap test');
try {
throw new BaseException('Sourcemap test');
} catch (e) {
print(e);
}
} }
} }
export function main() { export function main() {
new Test().run(); bootstrap(ErrorComponent);
} }