fix(errors): require passing stack traces explicitly in ng2 own code
This commit is contained in:
@@ -7,6 +7,7 @@ import 'package:angular2/src/test_lib/test_bed.dart';
|
||||
import 'package:angular2/test_lib.dart';
|
||||
|
||||
class MockException implements Error { var message; var stackTrace; }
|
||||
class NonError { var message; }
|
||||
|
||||
void functionThatThrows() {
|
||||
try { throw new MockException(); }
|
||||
@@ -19,6 +20,16 @@ void functionThatThrows() {
|
||||
}
|
||||
}
|
||||
|
||||
void functionThatThrowsNonError() {
|
||||
try { throw new NonError(); }
|
||||
catch(e, stack) {
|
||||
// If we lose the stack trace the message will no longer match
|
||||
// the first line in the stack
|
||||
e.message = stack.toString().split('\n')[0];
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
describe('TypeLiteral', () {
|
||||
it('should publish via appInjector',
|
||||
@@ -37,7 +48,7 @@ main() {
|
||||
});
|
||||
|
||||
describe('Error handling', () {
|
||||
it('should preserve stack traces throws from components',
|
||||
it('should preserve Error stack traces thrown from components',
|
||||
inject([TestBed, AsyncTestCompleter], (tb, async) {
|
||||
tb.overrideView(Dummy, new View(
|
||||
template: '<throwing-component></throwing-component>',
|
||||
@@ -49,6 +60,19 @@ main() {
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should preserve non-Error stack traces thrown from components',
|
||||
inject([TestBed, AsyncTestCompleter], (tb, async) {
|
||||
tb.overrideView(Dummy, new View(
|
||||
template: '<throwing-component2></throwing-component2>',
|
||||
directives: [ThrowingComponent2]
|
||||
));
|
||||
|
||||
tb.createView(Dummy).catchError((e, stack) {
|
||||
expect(stack.toString().split('\n')[0]).toEqual(e.message);
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -81,3 +105,13 @@ class ThrowingComponent {
|
||||
functionThatThrows();
|
||||
}
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'throwing-component2'
|
||||
)
|
||||
@View(template: '')
|
||||
class ThrowingComponent2 {
|
||||
ThrowingComponent2() {
|
||||
functionThatThrowsNonError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:angular2/test_lib.dart';
|
||||
import 'package:angular2/src/facade/async.dart';
|
||||
|
||||
class MockException implements Error { var message; var stackTrace; }
|
||||
class NonError { var message; }
|
||||
|
||||
void functionThatThrows() {
|
||||
try { throw new MockException(); }
|
||||
@@ -18,7 +19,13 @@ void functionThatThrows() {
|
||||
}
|
||||
|
||||
void functionThatThrowsNonError() {
|
||||
throw 'this is an error';
|
||||
try { throw new NonError(); }
|
||||
catch(e, stack) {
|
||||
// If we lose the stack trace the message will no longer match
|
||||
// the first line in the stack
|
||||
e.message = stack.toString().split('\n')[0];
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
void expectFunctionThatThrowsWithStackTrace(
|
||||
@@ -29,72 +36,65 @@ void expectFunctionThatThrowsWithStackTrace(
|
||||
});
|
||||
}
|
||||
|
||||
void expectFunctionThatThrowsWithoutStackTrace(Future future,
|
||||
AsyncTestCompleter async) {
|
||||
PromiseWrapper.catchError(future, (err, StackTrace stack) {
|
||||
expect(stack).toBe(null);
|
||||
async.done();
|
||||
});
|
||||
}
|
||||
|
||||
main() {
|
||||
describe('Completer', () {
|
||||
describe('async facade', () {
|
||||
describe('Completer', () {
|
||||
|
||||
it('should preserve error stack traces',
|
||||
inject([AsyncTestCompleter], (async) {
|
||||
var c = PromiseWrapper.completer();
|
||||
|
||||
expectFunctionThatThrowsWithStackTrace(c.promise, async);
|
||||
|
||||
try {
|
||||
functionThatThrows();
|
||||
} catch(e) {
|
||||
c.reject(e);
|
||||
}
|
||||
}));
|
||||
|
||||
// TODO: We might fix this one day; for now testing it to be explicit
|
||||
it('CANNOT preserve error stack traces for non-Errors',
|
||||
inject([AsyncTestCompleter], (async) {
|
||||
var c = PromiseWrapper.completer();
|
||||
|
||||
expectFunctionThatThrowsWithoutStackTrace(c.promise, async);
|
||||
|
||||
try {
|
||||
functionThatThrowsNonError();
|
||||
} catch(e) {
|
||||
c.reject(e);
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('PromiseWrapper', () {
|
||||
|
||||
describe('reject', () {
|
||||
|
||||
it('should preserve error stack traces',
|
||||
it('should preserve Error stack traces',
|
||||
inject([AsyncTestCompleter], (async) {
|
||||
var c = PromiseWrapper.completer();
|
||||
|
||||
expectFunctionThatThrowsWithStackTrace(c.promise, async);
|
||||
|
||||
try {
|
||||
functionThatThrows();
|
||||
} catch(e) {
|
||||
var rejectedFuture = PromiseWrapper.reject(e);
|
||||
expectFunctionThatThrowsWithStackTrace(rejectedFuture, async);
|
||||
c.reject(e, null);
|
||||
}
|
||||
}));
|
||||
|
||||
// TODO: We might fix this one day; for now testing it to be explicit
|
||||
it('CANNOT preserve stack traces for non-Errors',
|
||||
it('should preserve error stack traces for non-Errors',
|
||||
inject([AsyncTestCompleter], (async) {
|
||||
var c = PromiseWrapper.completer();
|
||||
|
||||
expectFunctionThatThrowsWithStackTrace(c.promise, async);
|
||||
|
||||
try {
|
||||
functionThatThrowsNonError();
|
||||
} catch(e) {
|
||||
var rejectedFuture = PromiseWrapper.reject(e);
|
||||
expectFunctionThatThrowsWithoutStackTrace(rejectedFuture, async);
|
||||
} catch(e, s) {
|
||||
c.reject(e, s);
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('PromiseWrapper', () {
|
||||
|
||||
describe('reject', () {
|
||||
|
||||
it('should preserve Error stack traces',
|
||||
inject([AsyncTestCompleter], (async) {
|
||||
try {
|
||||
functionThatThrows();
|
||||
} catch(e) {
|
||||
var rejectedFuture = PromiseWrapper.reject(e, null);
|
||||
expectFunctionThatThrowsWithStackTrace(rejectedFuture, async);
|
||||
}
|
||||
}));
|
||||
|
||||
it('should preserve stack traces for non-Errors',
|
||||
inject([AsyncTestCompleter], (async) {
|
||||
try {
|
||||
functionThatThrowsNonError();
|
||||
} catch(e, s) {
|
||||
var rejectedFuture = PromiseWrapper.reject(e, s);
|
||||
expectFunctionThatThrowsWithStackTrace(rejectedFuture, async);
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ class FakeTemplateLoader extends TemplateLoader {
|
||||
}
|
||||
}
|
||||
|
||||
return PromiseWrapper.reject('Load failed');
|
||||
return PromiseWrapper.reject('Load failed', null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ class FakeXHR extends XHR {
|
||||
get(url: string): Promise<string> {
|
||||
var response = MapWrapper.get(this._responses, url);
|
||||
if (isBlank(response)) {
|
||||
return PromiseWrapper.reject('xhr error');
|
||||
return PromiseWrapper.reject('xhr error', null);
|
||||
}
|
||||
|
||||
return PromiseWrapper.resolve(response);
|
||||
|
||||
@@ -223,7 +223,7 @@ class FakeXHR extends XHR {
|
||||
get(url: string): Promise<string> {
|
||||
var response = MapWrapper.get(this._responses, url);
|
||||
if (isBlank(response)) {
|
||||
return PromiseWrapper.reject('xhr error');
|
||||
return PromiseWrapper.reject('xhr error', null);
|
||||
}
|
||||
|
||||
return PromiseWrapper.resolve(response);
|
||||
|
||||
Reference in New Issue
Block a user