fix(errors): [2/2] Rename Exception to Error; remove from public API

BREAKING CHANGE:

Exceptions are no longer part of the public API. We don't expect that anyone should be referring to the Exception types.

ExceptionHandler.call(exception: any, stackTrace?: any, reason?: string): void;
change to:
ErrorHandler.handleError(error: any): void;
This commit is contained in:
Misko Hevery
2016-08-25 00:50:16 -07:00
committed by Victor Berchet
parent 86ba072758
commit 7c07bfff97
142 changed files with 565 additions and 774 deletions
@@ -8,15 +8,13 @@
import {APP_BOOTSTRAP_LISTENER, APP_INITIALIZER, ChangeDetectorRef, CompilerFactory, Component, Injector, NgModule, PlatformRef, Type} from '@angular/core';
import {ApplicationRef, ApplicationRef_} from '@angular/core/src/application_ref';
import {Console} from '@angular/core/src/console';
import {ErrorHandler} from '@angular/core/src/error_handler';
import {ComponentRef} from '@angular/core/src/linker/component_factory';
import {BrowserModule} from '@angular/platform-browser';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {DOCUMENT} from '@angular/platform-browser/src/dom/dom_tokens';
import {expect} from '@angular/platform-browser/testing/matchers';
import {ExceptionHandler} from '../src/facade/exception_handler';
import {BaseException} from '../src/facade/exceptions';
import {TestBed, async, inject, withModule} from '../testing';
import {SpyChangeDetectorRef} from './spies';
@@ -27,14 +25,14 @@ class SomeComponent {
export function main() {
describe('bootstrap', () => {
var errorLogger: _ArrayLogger;
var mockConsole: MockConsole;
var fakeDoc: Document;
beforeEach(() => {
fakeDoc = getDOM().createHtmlDocument();
const el = getDOM().createElement('comp', fakeDoc);
getDOM().appendChild(fakeDoc.body, el);
errorLogger = new _ArrayLogger();
mockConsole = new MockConsole();
});
type CreateModuleOptions = {providers?: any[], ngDoBootstrap?: any, bootstrap?: any[]};
@@ -48,12 +46,13 @@ export function main() {
} else {
options = providersOrOptions || {};
}
const errorHandler = new ErrorHandler(false);
errorHandler._console = mockConsole as any;
@NgModule({
providers: [
{provide: Console, useValue: new _MockConsole()},
{provide: ExceptionHandler, useValue: new ExceptionHandler(errorLogger, false)},
{provide: DOCUMENT, useValue: fakeDoc}, options.providers || []
{provide: ErrorHandler, useValue: errorHandler}, {provide: DOCUMENT, useValue: fakeDoc},
options.providers || []
],
imports: [BrowserModule],
declarations: [SomeComponent],
@@ -153,7 +152,7 @@ export function main() {
// we don't have an injector and therefore no way of
// getting the exception handler. So
// the error is only rethrown but not logged via the exception handler.
expect(errorLogger.res).toEqual([]);
expect(mockConsole.res).toEqual([]);
});
}));
@@ -165,7 +164,7 @@ export function main() {
]))
.then(() => expect(false).toBe(true), (e) => {
expect(e).toBe('Test');
expect(errorLogger.res).toEqual(['EXCEPTION: Test']);
expect(mockConsole.res).toEqual(['EXCEPTION: Test']);
});
}));
@@ -206,7 +205,7 @@ export function main() {
const expectedErrMsg =
`The module MyModule was bootstrapped, but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. Please define one of these.`;
expect(e.message).toEqual(expectedErrMsg);
expect(errorLogger.res).toEqual(['EXCEPTION: ' + expectedErrMsg]);
expect(mockConsole.res[0]).toEqual('EXCEPTION: ' + expectedErrMsg);
});
}));
});
@@ -243,7 +242,7 @@ export function main() {
// we don't have an injector and therefore no way of
// getting the exception handler. So
// the error is only rethrown but not logged via the exception handler.
expect(errorLogger.res).toEqual([]);
expect(mockConsole.res).toEqual([]);
}));
it('should rethrow promise errors even if the exceptionHandler is not rethrowing',
@@ -255,7 +254,7 @@ export function main() {
defaultPlatform.bootstrapModuleFactory(moduleFactory)
.then(() => expect(false).toBe(true), (e) => {
expect(e).toBe('Test');
expect(errorLogger.res).toEqual(['EXCEPTION: Test']);
expect(mockConsole.res).toEqual(['EXCEPTION: Test']);
});
}));
});
@@ -266,15 +265,8 @@ export function main() {
class MyComp6 {
}
class _ArrayLogger {
class MockConsole {
res: any[] = [];
log(s: any): void { this.res.push(s); }
logError(s: any): void { this.res.push(s); }
logGroup(s: any): void { this.res.push(s); }
logGroupEnd(){};
}
class _MockConsole implements Console {
log(message: string) {}
warn(message: string) {}
error(s: any): void { this.res.push(s); }
}
@@ -12,7 +12,6 @@ import {ReflectiveInjectorDynamicStrategy, ReflectiveInjectorInlineStrategy, Ref
import {ResolvedReflectiveProvider_} from '@angular/core/src/di/reflective_provider';
import {expect} from '@angular/platform-browser/testing/matchers';
import {BaseException} from '../../src/facade/exceptions';
import {isBlank, isPresent, stringify} from '../../src/facade/lang';
class CustomDependencyMetadata extends DependencyMetadata {}
@@ -20,7 +19,7 @@ class CustomDependencyMetadata extends DependencyMetadata {}
class Engine {}
class BrokenEngine {
constructor() { throw new BaseException('Broken Engine'); }
constructor() { throw new Error('Broken Engine'); }
}
class DashboardSoftware {}
@@ -332,7 +331,7 @@ export function main() {
} catch (e) {
expect(e.message).toContain(
`Error during instantiation of Engine! (${stringify(Car)} -> Engine)`);
expect(e.originalException instanceof BaseException).toBeTruthy();
expect(e.originalError instanceof Error).toBeTruthy();
expect(e.causeKey.token).toEqual(Engine);
}
});
@@ -364,7 +363,8 @@ export function main() {
{provide: Engine, useFactory: (() => isBroken ? new BrokenEngine() : new Engine())}
]);
expect(() => injector.get(Car)).toThrowError(new RegExp('Error'));
expect(() => injector.get(Car))
.toThrowError('Broken Engine: Error during instantiation of Engine! (Car -> Engine).');
isBroken = false;
@@ -6,8 +6,16 @@
* found in the LICENSE file at https://angular.io/license
*/
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit,} from '@angular/core/testing/testing_internal';
import {BaseException, WrappedException, ExceptionHandler} from '../src/exceptions';
import {WrappedError} from '@angular/core/src/facade/errors';
import {DebugContext} from '@angular/core/src/linker/debug_context';
import {ViewWrappedError} from '@angular/core/src/linker/errors';
import {ErrorHandler} from '../src/error_handler';
class MockConsole {
res: any[] = [];
error(s: any): void { this.res.push(s); }
}
class _CustomException {
context = 'some context';
@@ -15,74 +23,78 @@ class _CustomException {
}
export function main() {
describe('ExceptionHandler', () => {
function errorToString(error: any) {
var logger = new MockConsole();
var errorHandler = new ErrorHandler(false);
errorHandler._console = logger as any;
errorHandler.handleError(error);
return logger.res.join('\n');
}
function getStack(error: Error): string {
try {
throw error;
} catch (e) {
return e.stack;
}
}
describe('ErrorHandler', () => {
it('should output exception', () => {
var e = ExceptionHandler.exceptionToString(new BaseException('message!'));
var e = errorToString(new Error('message!'));
expect(e).toContain('message!');
});
it('should output stackTrace', () => {
var e = ExceptionHandler.exceptionToString(new BaseException('message!'), 'stack!');
expect(e).toContain('stack!');
});
it('should join a long stackTrace', () => {
var e =
ExceptionHandler.exceptionToString(new BaseException('message!'), ['stack1', 'stack2']);
expect(e).toContain('stack1');
expect(e).toContain('stack2');
});
it('should output reason when present', () => {
var e = ExceptionHandler.exceptionToString(new BaseException('message!'), null, 'reason!');
expect(e).toContain('reason!');
var error = new Error('message!');
var stack = getStack(error);
var e = errorToString(error);
expect(e).toContain(stack);
});
describe('context', () => {
it('should print context', () => {
var e = ExceptionHandler.exceptionToString(
new WrappedException('message!', null, null, 'context!'));
expect(e).toContain('context!');
});
it('should print nested context', () => {
var original = new WrappedException('message!', null, null, 'context!');
var e = ExceptionHandler.exceptionToString(new WrappedException('message', original));
expect(e).toContain('context!');
});
it('should not print context when the passed-in exception is not a BaseException', () => {
var e = ExceptionHandler.exceptionToString(new _CustomException());
expect(e).not.toContain('context');
var cause = new Error('message!');
var stack = getStack(cause);
var context = {
source: 'context!',
toString() { return 'Context'; }
} as any as DebugContext;
var original = new ViewWrappedError(cause, context);
var e = errorToString(new WrappedError('message', original));
expect(e).toEqual(`EXCEPTION: message caused by: Error in context! caused by: message!
ORIGINAL EXCEPTION: message!
ORIGINAL STACKTRACE:
${stack}
ERROR CONTEXT:
Context`);
});
});
describe('original exception', () => {
it('should print original exception message if available (original is BaseException)', () => {
var realOriginal = new BaseException('inner');
var original = new WrappedException('wrapped', realOriginal);
var e =
ExceptionHandler.exceptionToString(new WrappedException('wrappedwrapped', original));
expect(e).toContain('inner');
it('should print original exception message if available (original is Error)', () => {
var realOriginal = new Error('inner');
var stack = getStack(realOriginal);
var original = new WrappedError('wrapped', realOriginal);
var e = errorToString(new WrappedError('wrappedwrapped', original));
expect(e).toContain(stack);
});
it('should print original exception message if available (original is not BaseException)',
() => {
var realOriginal = new _CustomException();
var original = new WrappedException('wrapped', realOriginal);
var e =
ExceptionHandler.exceptionToString(new WrappedException('wrappedwrapped', original));
expect(e).toContain('custom');
});
it('should print original exception message if available (original is not Error)', () => {
var realOriginal = new _CustomException();
var original = new WrappedError('wrapped', realOriginal);
var e = errorToString(new WrappedError('wrappedwrapped', original));
expect(e).toContain('custom');
});
});
describe('original stack', () => {
it('should print original stack if available', () => {
var realOriginal = new BaseException('inner');
var original = new WrappedException('wrapped', realOriginal, 'originalStack');
var e = ExceptionHandler.exceptionToString(
new WrappedException('wrappedwrapped', original, 'wrappedStack'));
expect(e).toContain('originalStack');
var realOriginal = new Error('inner');
var stack = getStack(realOriginal);
var original = new WrappedError('wrapped', realOriginal);
var e = errorToString(new WrappedError('wrappedwrapped', original));
expect(e).toContain(stack);
});
});
});
@@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
import {BaseException} from '@angular/core';
import {discardPeriodicTasks, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
import {Log, beforeEach, ddescribe, describe, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers';
@@ -93,16 +92,14 @@ export function main() {
it('should complain if the test throws an exception during async calls', () => {
expect(() => {
fakeAsync(() => {
resolvedPromise.then((_) => { throw new BaseException('async'); });
resolvedPromise.then((_) => { throw new Error('async'); });
flushMicrotasks();
})();
}).toThrowError('Uncaught (in promise): async');
}).toThrowError('Uncaught (in promise): Error: async');
});
it('should complain if a test throws an exception', () => {
expect(() => {
fakeAsync(() => { throw new BaseException('sync'); })();
}).toThrowError('sync');
expect(() => { fakeAsync(() => { throw new Error('sync'); })(); }).toThrowError('sync');
});
});
@@ -18,7 +18,6 @@ import {DomRootRenderer} from '@angular/platform-browser/src/dom/dom_renderer';
import {EventEmitter} from '../../src/facade/async';
import {StringMapWrapper} from '../../src/facade/collection';
import {BaseException} from '../../src/facade/exceptions';
import {NumberWrapper, isBlank} from '../../src/facade/lang';
export function main() {
@@ -724,7 +723,7 @@ export function main() {
try {
ctx.detectChanges(false);
} catch (e) {
throw new BaseException('Second detectChanges() should not have run detection.');
throw new Error('Second detectChanges() should not have run detection.');
}
expect(directiveLog.filter(['ngOnInit'])).toEqual([]);
}));
@@ -821,7 +820,7 @@ export function main() {
try {
ctx.detectChanges(false);
} catch (e) {
throw new BaseException('Second detectChanges() should not have run detection.');
throw new Error('Second detectChanges() should not have run detection.');
}
expect(directiveLog.filter(['ngAfterContentInit'])).toEqual([]);
}));
@@ -935,7 +934,7 @@ export function main() {
try {
ctx.detectChanges(false);
} catch (e) {
throw new BaseException('Second detectChanges() should not have run detection.');
throw new Error('Second detectChanges() should not have run detection.');
}
expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]);
}));
@@ -1342,7 +1341,7 @@ class TestDirective implements OnInit, DoCheck, OnChanges, AfterContentInit, Aft
ngOnInit() {
this.log.add(this.name, 'ngOnInit');
if (this.throwOn == 'ngOnInit') {
throw new BaseException('Boom!');
throw new Error('Boom!');
}
}
@@ -1352,42 +1351,42 @@ class TestDirective implements OnInit, DoCheck, OnChanges, AfterContentInit, Aft
StringMapWrapper.forEach(changes, (c: SimpleChange, key: string) => r[key] = c.currentValue);
this.changes = r;
if (this.throwOn == 'ngOnChanges') {
throw new BaseException('Boom!');
throw new Error('Boom!');
}
}
ngAfterContentInit() {
this.log.add(this.name, 'ngAfterContentInit');
if (this.throwOn == 'ngAfterContentInit') {
throw new BaseException('Boom!');
throw new Error('Boom!');
}
}
ngAfterContentChecked() {
this.log.add(this.name, 'ngAfterContentChecked');
if (this.throwOn == 'ngAfterContentChecked') {
throw new BaseException('Boom!');
throw new Error('Boom!');
}
}
ngAfterViewInit() {
this.log.add(this.name, 'ngAfterViewInit');
if (this.throwOn == 'ngAfterViewInit') {
throw new BaseException('Boom!');
throw new Error('Boom!');
}
}
ngAfterViewChecked() {
this.log.add(this.name, 'ngAfterViewChecked');
if (this.throwOn == 'ngAfterViewChecked') {
throw new BaseException('Boom!');
throw new Error('Boom!');
}
}
ngOnDestroy() {
this.log.add(this.name, 'ngOnDestroy');
if (this.throwOn == 'ngOnDestroy') {
throw new BaseException('Boom!');
throw new Error('Boom!');
}
}
}
@@ -6,8 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver, NoComponentFactoryError, forwardRef} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver, forwardRef} from '@angular/core';
import {NoComponentFactoryError} from '@angular/core/src/linker/component_factory_resolver';
import {TestBed} from '@angular/core/testing';
import {Console} from '../../src/console';
@@ -23,7 +23,6 @@ import {dispatchEvent, el} from '@angular/platform-browser/testing/browser_util'
import {expect} from '@angular/platform-browser/testing/matchers';
import {EventEmitter} from '../../src/facade/async';
import {BaseException} from '../../src/facade/exceptions';
import {isBlank, isPresent, stringify} from '../../src/facade/lang';
const ANCHOR_ELEMENT = new OpaqueToken('AnchorElement');
@@ -2091,7 +2090,7 @@ class OtherDuplicateDir {
@Directive({selector: 'directive-throwing-error'})
class DirectiveThrowingAnError {
constructor() { throw new BaseException('BOOM'); }
constructor() { throw new Error('BOOM'); }
}
@Component({
@@ -11,14 +11,13 @@ import {Console} from '@angular/core/src/console';
import {ComponentFixture, TestBed, inject} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
import {BaseException} from '../../src/facade/exceptions';
import {stringify} from '../../src/facade/lang';
import {NgModuleInjector} from '../../src/linker/ng_module_factory';
class Engine {}
class BrokenEngine {
constructor() { throw new BaseException('Broken Engine'); }
constructor() { throw new Error('Broken Engine'); }
}
class DashboardSoftware {}
@@ -6,12 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/
import {BaseException} from '@angular/core';
import {NgZone} from '@angular/core/src/zone/ng_zone';
import {async, fakeAsync, flushMicrotasks} from '@angular/core/testing';
import {AsyncTestCompleter, Log, beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {browserDetection} from '@angular/platform-browser/testing/browser_util';
import {BaseError} from '../../src/facade/errors';
import {isPresent, scheduleMicroTask} from '../../src/facade/lang';
var needsLongerTimers = browserDetection.isSlow || browserDetection.isEdge;
@@ -95,7 +94,7 @@ export function main() {
setTimeout(() => {
setTimeout(() => {
resolve(null);
throw new BaseException('ccc');
throw new BaseError('ccc');
}, 0);
}, 0);
});
@@ -118,7 +117,7 @@ export function main() {
scheduleMicroTask(() => {
scheduleMicroTask(() => {
resolve(null);
throw new BaseException('ddd');
throw new BaseError('ddd');
});
});
});
@@ -153,7 +152,7 @@ export function main() {
setTimeout(() => {
setTimeout(() => {
resolve(null);
throw new BaseException('ccc');
throw new BaseError('ccc');
}, 0);
}, 0);
});
@@ -720,7 +719,7 @@ function commonTests() {
it('should call the on error callback when it is invoked via zone.runGuarded',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
macroTask(() => {
var exception = new BaseException('sync');
var exception = new BaseError('sync');
_zone.runGuarded(() => { throw exception; });
@@ -733,7 +732,7 @@ function commonTests() {
it('should not call the on error callback but rethrow when it is invoked via zone.run',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
macroTask(() => {
var exception = new BaseException('sync');
var exception = new BaseError('sync');
expect(() => _zone.run(() => { throw exception; })).toThrowError('sync');
expect(_errors.length).toBe(0);
@@ -743,7 +742,7 @@ function commonTests() {
it('should call onError for errors from microtasks',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var exception = new BaseException('async');
var exception = new BaseError('async');
macroTask(() => { _zone.run(() => { scheduleMicroTask(() => { throw exception; }); }); });