fix(change_detection): _throwError should not mask the original exception

This commit is contained in:
vsavkin 2015-09-30 15:28:26 -07:00
parent 5557a5716d
commit cec4b36d9b
5 changed files with 42 additions and 9 deletions

View File

@ -287,11 +287,19 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
}
private _throwError(exception: any, stack: any): void {
var error;
try {
var c = this.dispatcher.getDebugContext(this._currentBinding().elementIndex, null);
var context = isPresent(c) ? new _Context(c.element, c.componentElement, c.context, c.locals,
c.injector, this._currentBinding().debug) :
null;
throw new ChangeDetectionError(this._currentBinding().debug, exception, stack, context);
error = new ChangeDetectionError(this._currentBinding().debug, exception, stack, context);
} catch (e) {
// if an error happens during getting the debug context, we throw a ChangeDetectionError
// without the extra information.
error = new ChangeDetectionError(null, exception, stack, null);
}
throw error;
}
throwOnChangeError(oldValue: any, newValue: any): void {

View File

@ -254,7 +254,7 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
} catch (e) {
// TODO: vsavkin log the exception once we have a good way to log errors and warnings
// if an error happens during getting the debug context, we return an empty map.
// if an error happens during getting the debug context, we return null.
return null;
}
}

View File

@ -11,6 +11,8 @@ import {
fakeAsync
} from 'angular2/test_lib';
import {SpyChangeDispatcher} from '../spies';
import {
CONST_EXPR,
isPresent,
@ -92,8 +94,8 @@ export function main() {
function _createChangeDetector(expression: string, context = _DEFAULT_CONTEXT,
registry = null) {
var dispatcher = new TestDispatcher();
registry = null, dispatcher = null) {
if (isBlank(dispatcher)) dispatcher = new TestDispatcher();
var testDef = getDefinition(expression);
var protoCd = _getProtoChangeDetector(testDef.cdDef);
var cd = protoCd.instantiate(dispatcher);
@ -797,6 +799,22 @@ export function main() {
expect(e.location).toEqual('invalidFn(1) in location');
}
});
it('should handle unexpected errors in the event handler itself', () => {
var throwingDispatcher = new SpyChangeDispatcher();
throwingDispatcher.spy("getDebugContext")
.andCallFake((_, __) => { throw new BaseException('boom'); });
var val =
_createChangeDetector('invalidFn(1)', _DEFAULT_CONTEXT, null, throwingDispatcher);
try {
val.changeDetector.detectChanges();
throw new BaseException('fail');
} catch (e) {
expect(e).toBeAnInstanceOf(ChangeDetectionError);
expect(e.location).toEqual(null);
}
});
});
describe('Locals', () => {
@ -1398,5 +1416,5 @@ class TestDispatcher implements ChangeDispatcher {
}
class _ChangeDetectorAndDispatcher {
constructor(public changeDetector: any, public dispatcher: TestDispatcher) {}
constructor(public changeDetector: any, public dispatcher: any) {}
}

View File

@ -35,6 +35,11 @@ class SpyProtoChangeDetector extends SpyObject implements ProtoChangeDetector {
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy
class SpyChangeDispatcher extends SpyObject implements ChangeDispatcher {
noSuchMethod(m) => super.noSuchMethod(m);
}
@proxy
class SpyIterableDifferFactory extends SpyObject
implements IterableDifferFactory {

View File

@ -40,6 +40,8 @@ export class SpyProtoChangeDetector extends SpyObject {
constructor() { super(DynamicChangeDetector); }
}
export class SpyChangeDispatcher extends SpyObject {}
export class SpyIterableDifferFactory extends SpyObject {}
export class SpyRenderCompiler extends SpyObject {