perf: Don’t subclass Error; resulting in smaller binary (#14160)
Subclassing errors is problematic since Error returns a new instance. All of the patching which we do than prevent proper application of source maps. PR Close #14160
This commit is contained in:

committed by
Miško Hevery

parent
3c2842be96
commit
c33fda2607
@ -9,6 +9,7 @@
|
||||
import {Inject, Injectable, Injector, Optional, Provider, ReflectiveInjector, ReflectiveKey, Self, forwardRef} from '@angular/core';
|
||||
import {ReflectiveInjector_} from '@angular/core/src/di/reflective_injector';
|
||||
import {ResolvedReflectiveProvider_} from '@angular/core/src/di/reflective_provider';
|
||||
import {getOriginalError} from '@angular/core/src/errors';
|
||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||
|
||||
import {isPresent, stringify} from '../../src/facade/lang';
|
||||
@ -293,8 +294,8 @@ export function main() {
|
||||
} catch (e) {
|
||||
expect(e.message).toContain(
|
||||
`Error during instantiation of Engine! (${stringify(Car)} -> Engine)`);
|
||||
expect(e.originalError instanceof Error).toBeTruthy();
|
||||
expect(e.causeKey.token).toEqual(Engine);
|
||||
expect(getOriginalError(e) instanceof Error).toBeTruthy();
|
||||
expect(e.keys[0].token).toEqual(Engine);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -6,22 +6,17 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {WrappedError} from '@angular/core/src/facade/errors';
|
||||
import {ERROR_DEBUG_CONTEXT} from '@angular/core/src/errors';
|
||||
import {DebugContext} from '@angular/core/src/linker/debug_context';
|
||||
import {ViewWrappedError} from '@angular/core/src/linker/errors';
|
||||
import {viewWrappedError} from '@angular/core/src/linker/errors';
|
||||
|
||||
import {ErrorHandler} from '../src/error_handler';
|
||||
import {ErrorHandler, wrappedError} from '../src/error_handler';
|
||||
|
||||
class MockConsole {
|
||||
res: any[] = [];
|
||||
error(s: any): void { this.res.push(s); }
|
||||
}
|
||||
|
||||
class _CustomException {
|
||||
context = 'some context';
|
||||
toString(): string { return 'custom'; }
|
||||
}
|
||||
|
||||
export function main() {
|
||||
function errorToString(error: any) {
|
||||
const logger = new MockConsole();
|
||||
@ -58,12 +53,9 @@ export function main() {
|
||||
it('should print nested context', () => {
|
||||
const cause = new Error('message!');
|
||||
const stack = getStack(cause);
|
||||
const context = {
|
||||
source: 'context!',
|
||||
toString() { return 'Context'; }
|
||||
} as any as DebugContext;
|
||||
const original = new ViewWrappedError(cause, context);
|
||||
const e = errorToString(new WrappedError('message', original));
|
||||
const context = { source: 'context!', toString() { return 'Context'; } } as any;
|
||||
const original = viewWrappedError(cause, context);
|
||||
const e = errorToString(wrappedError('message', original));
|
||||
expect(e).toEqual(
|
||||
stack ? `EXCEPTION: message caused by: Error in context! caused by: message!
|
||||
ORIGINAL EXCEPTION: message!
|
||||
@ -81,15 +73,15 @@ Context`);
|
||||
describe('original exception', () => {
|
||||
it('should print original exception message if available (original is Error)', () => {
|
||||
const realOriginal = new Error('inner');
|
||||
const original = new WrappedError('wrapped', realOriginal);
|
||||
const e = errorToString(new WrappedError('wrappedwrapped', original));
|
||||
const original = wrappedError('wrapped', realOriginal);
|
||||
const e = errorToString(wrappedError('wrappedwrapped', original));
|
||||
expect(e).toContain('inner');
|
||||
});
|
||||
|
||||
it('should print original exception message if available (original is not Error)', () => {
|
||||
const realOriginal = new _CustomException();
|
||||
const original = new WrappedError('wrapped', realOriginal);
|
||||
const e = errorToString(new WrappedError('wrappedwrapped', original));
|
||||
const realOriginal = new Error('custom');
|
||||
const original = wrappedError('wrapped', realOriginal);
|
||||
const e = errorToString(wrappedError('wrappedwrapped', original));
|
||||
expect(e).toContain('custom');
|
||||
});
|
||||
});
|
||||
@ -99,8 +91,8 @@ Context`);
|
||||
const realOriginal = new Error('inner');
|
||||
const stack = getStack(realOriginal);
|
||||
if (stack) {
|
||||
const original = new WrappedError('wrapped', realOriginal);
|
||||
const e = errorToString(new WrappedError('wrappedwrapped', original));
|
||||
const original = wrappedError('wrapped', realOriginal);
|
||||
const e = errorToString(wrappedError('wrappedwrapped', original));
|
||||
expect(e).toContain(stack);
|
||||
}
|
||||
});
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver} from '@angular/core';
|
||||
import {NoComponentFactoryError} from '@angular/core/src/linker/component_factory_resolver';
|
||||
import {noComponentFactoryError} from '@angular/core/src/linker/component_factory_resolver';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
|
||||
import {Console} from '../../src/console';
|
||||
@ -77,7 +77,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
const nestedChildComp: NestedChildComp = nestedChildCompEl.componentInstance;
|
||||
expect(nestedChildComp.cfr.resolveComponentFactory(ChildComp).componentType).toBe(ChildComp);
|
||||
expect(() => nestedChildComp.cfr.resolveComponentFactory(NestedChildComp))
|
||||
.toThrow(new NoComponentFactoryError(NestedChildComp));
|
||||
.toThrow(noComponentFactoryError(NestedChildComp));
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -9,6 +9,7 @@
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {ComponentFactory, Host, Inject, Injectable, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, OnDestroy, ReflectiveInjector, SkipSelf} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, PipeTransform} from '@angular/core/src/change_detection/change_detection';
|
||||
import {getDebugContext} from '@angular/core/src/errors';
|
||||
import {ComponentFactoryResolver} from '@angular/core/src/linker/component_factory_resolver';
|
||||
import {ElementRef} from '@angular/core/src/linker/element_ref';
|
||||
import {QueryList} from '@angular/core/src/linker/query_list';
|
||||
@ -1295,7 +1296,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
TestBed.createComponent(MyComp);
|
||||
throw 'Should throw';
|
||||
} catch (e) {
|
||||
const c = e.context;
|
||||
const c = getDebugContext(e);
|
||||
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
||||
expect((<Injector>c.injector).get).toBeTruthy();
|
||||
}
|
||||
@ -1310,7 +1311,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
fixture.detectChanges();
|
||||
throw 'Should throw';
|
||||
} catch (e) {
|
||||
const c = e.context;
|
||||
const c = getDebugContext(e);
|
||||
expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('INPUT');
|
||||
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
||||
expect((<Injector>c.injector).get).toBeTruthy();
|
||||
@ -1330,7 +1331,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
fixture.detectChanges();
|
||||
throw 'Should throw';
|
||||
} catch (e) {
|
||||
const c = e.context;
|
||||
const c = getDebugContext(e);
|
||||
expect(c.renderNode).toBeTruthy();
|
||||
expect(c.source).toContain(':0:5');
|
||||
}
|
||||
@ -1353,7 +1354,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||
try {
|
||||
tc.injector.get(DirectiveEmittingEvent).fireEvent('boom');
|
||||
} catch (e) {
|
||||
const c = e.context;
|
||||
const c = getDebugContext(e);
|
||||
expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('SPAN');
|
||||
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
||||
expect((<Injector>c.injector).get).toBeTruthy();
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core';
|
||||
import {getDebugContext} from '@angular/core/src/errors';
|
||||
import {BindingType, DebugContext, NodeDef, NodeFlags, RootData, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, destroyView, elementDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index';
|
||||
import {inject} from '@angular/core/testing';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
@ -363,7 +364,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
||||
}
|
||||
expect(err).toBeTruthy();
|
||||
expect(err.message).toBe('Test');
|
||||
const debugCtx = <DebugContext>err.context;
|
||||
const debugCtx = getDebugContext(err);
|
||||
expect(debugCtx.view).toBe(view);
|
||||
expect(debugCtx.nodeIndex).toBe(0);
|
||||
});
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, DoCheck, ElementRef, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, RenderComponentType, Renderer, RootRenderer, Sanitizer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core';
|
||||
import {getDebugContext} from '@angular/core/src/errors';
|
||||
import {BindingType, DebugContext, DepFlags, NodeDef, NodeFlags, ProviderType, RootData, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, destroyView, directiveDef, elementDef, providerDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index';
|
||||
import {inject} from '@angular/core/testing';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
@ -135,7 +136,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
||||
}
|
||||
expect(err).toBeTruthy();
|
||||
expect(err.message).toBe('Test');
|
||||
const debugCtx = <DebugContext>err.context;
|
||||
const debugCtx = getDebugContext(err);
|
||||
expect(debugCtx.view).toBeTruthy();
|
||||
// errors should point to the already existing element
|
||||
expect(debugCtx.nodeIndex).toBe(0);
|
||||
@ -447,7 +448,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
||||
err = e;
|
||||
}
|
||||
expect(err).toBeTruthy();
|
||||
const debugCtx = <DebugContext>err.context;
|
||||
const debugCtx = getDebugContext(err);
|
||||
expect(debugCtx.view).toBe(view);
|
||||
// events are emitted with the index of the element, not the index of the provider.
|
||||
expect(debugCtx.nodeIndex).toBe(0);
|
||||
@ -576,7 +577,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
||||
}
|
||||
expect(err).toBeTruthy();
|
||||
expect(err.message).toBe('Test');
|
||||
const debugCtx = <DebugContext>err.context;
|
||||
const debugCtx = getDebugContext(err);
|
||||
expect(debugCtx.view).toBe(view);
|
||||
expect(debugCtx.nodeIndex).toBe(1);
|
||||
});
|
||||
@ -599,7 +600,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
||||
}
|
||||
expect(err).toBeTruthy();
|
||||
expect(err.message).toBe('Test');
|
||||
const debugCtx = <DebugContext>err.context;
|
||||
const debugCtx = getDebugContext(err);
|
||||
expect(debugCtx.view).toBe(view);
|
||||
expect(debugCtx.nodeIndex).toBe(1);
|
||||
});
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {ElementRef, Injector, QueryList, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, TemplateRef, ViewContainerRef, ViewEncapsulation, getDebugNode} from '@angular/core';
|
||||
import {getDebugContext} from '@angular/core/src/errors';
|
||||
import {BindingType, DebugContext, NodeDef, NodeFlags, QueryBindingType, QueryValueType, RootData, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, attachEmbeddedView, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createEmbeddedView, createRootView, destroyView, detachEmbeddedView, directiveDef, elementDef, queryDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index';
|
||||
import {inject} from '@angular/core/testing';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
@ -395,7 +396,7 @@ export function main() {
|
||||
expect(err.message)
|
||||
.toBe(
|
||||
`Expression has changed after it was checked. Previous value: 'Query query1 not dirty'. Current value: 'Query query1 dirty'.`);
|
||||
const debugCtx = <DebugContext>err.context;
|
||||
const debugCtx = getDebugContext(err);
|
||||
expect(debugCtx.view).toBe(view);
|
||||
expect(debugCtx.nodeIndex).toBe(2);
|
||||
});
|
||||
@ -421,10 +422,10 @@ export function main() {
|
||||
}
|
||||
expect(err).toBeTruthy();
|
||||
expect(err.message).toBe('Test');
|
||||
const debugCtx = <DebugContext>err.context;
|
||||
const debugCtx = getDebugContext(err);
|
||||
expect(debugCtx.view).toBe(view);
|
||||
expect(debugCtx.nodeIndex).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import {NgZone} from '@angular/core/src/zone/ng_zone';
|
||||
import {async, fakeAsync, flushMicrotasks} from '@angular/core/testing';
|
||||
import {AsyncTestCompleter, Log, beforeEach, describe, expect, inject, it, 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';
|
||||
|
||||
const needsLongerTimers = browserDetection.isSlow || browserDetection.isEdge;
|
||||
@ -94,7 +93,7 @@ export function main() {
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
resolve(null);
|
||||
throw new BaseError('ccc');
|
||||
throw new Error('ccc');
|
||||
}, 0);
|
||||
}, 0);
|
||||
});
|
||||
@ -117,7 +116,7 @@ export function main() {
|
||||
scheduleMicroTask(() => {
|
||||
scheduleMicroTask(() => {
|
||||
resolve(null);
|
||||
throw new BaseError('ddd');
|
||||
throw new Error('ddd');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -152,7 +151,7 @@ export function main() {
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
resolve(null);
|
||||
throw new BaseError('ccc');
|
||||
throw new Error('ccc');
|
||||
}, 0);
|
||||
}, 0);
|
||||
});
|
||||
@ -719,7 +718,7 @@ function commonTests() {
|
||||
it('should call the on error callback when it is invoked via zone.runGuarded',
|
||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||
macroTask(() => {
|
||||
const exception = new BaseError('sync');
|
||||
const exception = new Error('sync');
|
||||
|
||||
_zone.runGuarded(() => { throw exception; });
|
||||
|
||||
@ -732,7 +731,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(() => {
|
||||
const exception = new BaseError('sync');
|
||||
const exception = new Error('sync');
|
||||
expect(() => _zone.run(() => { throw exception; })).toThrowError('sync');
|
||||
|
||||
expect(_errors.length).toBe(0);
|
||||
@ -742,7 +741,7 @@ function commonTests() {
|
||||
|
||||
it('should call onError for errors from microtasks',
|
||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||
const exception = new BaseError('async');
|
||||
const exception = new Error('async');
|
||||
|
||||
macroTask(() => { _zone.run(() => { scheduleMicroTask(() => { throw exception; }); }); });
|
||||
|
||||
|
Reference in New Issue
Block a user