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:
parent
3c2842be96
commit
c33fda2607
@ -9,7 +9,7 @@
|
|||||||
import {ChangeDetectorRef, OnDestroy, Pipe, PipeTransform, WrappedValue} from '@angular/core';
|
import {ChangeDetectorRef, OnDestroy, Pipe, PipeTransform, WrappedValue} from '@angular/core';
|
||||||
import {EventEmitter, Observable} from '../facade/async';
|
import {EventEmitter, Observable} from '../facade/async';
|
||||||
import {isObservable, isPromise} from '../private_import_core';
|
import {isObservable, isPromise} from '../private_import_core';
|
||||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||||
|
|
||||||
interface SubscriptionStrategy {
|
interface SubscriptionStrategy {
|
||||||
createSubscription(async: any, updateLatestValue: any): any;
|
createSubscription(async: any, updateLatestValue: any): any;
|
||||||
@ -120,7 +120,7 @@ export class AsyncPipe implements OnDestroy, PipeTransform {
|
|||||||
return _observableStrategy;
|
return _observableStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidPipeArgumentError(AsyncPipe, obj);
|
throw invalidPipeArgumentError(AsyncPipe, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _dispose(): void {
|
private _dispose(): void {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Pipe, PipeTransform} from '@angular/core';
|
import {Pipe, PipeTransform} from '@angular/core';
|
||||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms text to lowercase.
|
* Transforms text to lowercase.
|
||||||
@ -21,7 +21,7 @@ export class LowerCasePipe implements PipeTransform {
|
|||||||
transform(value: string): string {
|
transform(value: string): string {
|
||||||
if (!value) return value;
|
if (!value) return value;
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
throw new InvalidPipeArgumentError(LowerCasePipe, value);
|
throw invalidPipeArgumentError(LowerCasePipe, value);
|
||||||
}
|
}
|
||||||
return value.toLowerCase();
|
return value.toLowerCase();
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ export class TitleCasePipe implements PipeTransform {
|
|||||||
transform(value: string): string {
|
transform(value: string): string {
|
||||||
if (!value) return value;
|
if (!value) return value;
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
throw new InvalidPipeArgumentError(TitleCasePipe, value);
|
throw invalidPipeArgumentError(TitleCasePipe, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value.split(/\b/g).map(word => titleCaseWord(word)).join('');
|
return value.split(/\b/g).map(word => titleCaseWord(word)).join('');
|
||||||
@ -65,7 +65,7 @@ export class UpperCasePipe implements PipeTransform {
|
|||||||
transform(value: string): string {
|
transform(value: string): string {
|
||||||
if (!value) return value;
|
if (!value) return value;
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
throw new InvalidPipeArgumentError(UpperCasePipe, value);
|
throw invalidPipeArgumentError(UpperCasePipe, value);
|
||||||
}
|
}
|
||||||
return value.toUpperCase();
|
return value.toUpperCase();
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
import {Inject, LOCALE_ID, Pipe, PipeTransform} from '@angular/core';
|
import {Inject, LOCALE_ID, Pipe, PipeTransform} from '@angular/core';
|
||||||
import {NumberWrapper} from '../facade/lang';
|
import {NumberWrapper} from '../facade/lang';
|
||||||
import {DateFormatter} from './intl';
|
import {DateFormatter} from './intl';
|
||||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||||
|
|
||||||
const ISO8601_DATE_REGEX =
|
const ISO8601_DATE_REGEX =
|
||||||
/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
|
/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
|
||||||
@ -134,7 +134,7 @@ export class DatePipe implements PipeTransform {
|
|||||||
if ((typeof value === 'string') && (match = value.match(ISO8601_DATE_REGEX))) {
|
if ((typeof value === 'string') && (match = value.match(ISO8601_DATE_REGEX))) {
|
||||||
date = isoStringToDate(match);
|
date = isoStringToDate(match);
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidPipeArgumentError(DatePipe, value);
|
throw invalidPipeArgumentError(DatePipe, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import {Pipe, PipeTransform} from '@angular/core';
|
import {Pipe, PipeTransform} from '@angular/core';
|
||||||
import {NgLocalization, getPluralCategory} from '../localization';
|
import {NgLocalization, getPluralCategory} from '../localization';
|
||||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||||
|
|
||||||
const _INTERPOLATION_REGEXP: RegExp = /#/g;
|
const _INTERPOLATION_REGEXP: RegExp = /#/g;
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ export class I18nPluralPipe implements PipeTransform {
|
|||||||
if (value == null) return '';
|
if (value == null) return '';
|
||||||
|
|
||||||
if (typeof pluralMap !== 'object' || pluralMap === null) {
|
if (typeof pluralMap !== 'object' || pluralMap === null) {
|
||||||
throw new InvalidPipeArgumentError(I18nPluralPipe, pluralMap);
|
throw invalidPipeArgumentError(I18nPluralPipe, pluralMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = getPluralCategory(value, Object.keys(pluralMap), this._localization);
|
const key = getPluralCategory(value, Object.keys(pluralMap), this._localization);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Pipe, PipeTransform} from '@angular/core';
|
import {Pipe, PipeTransform} from '@angular/core';
|
||||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngModule CommonModule
|
* @ngModule CommonModule
|
||||||
@ -32,7 +32,7 @@ export class I18nSelectPipe implements PipeTransform {
|
|||||||
if (value == null) return '';
|
if (value == null) return '';
|
||||||
|
|
||||||
if (typeof mapping !== 'object' || typeof value !== 'string') {
|
if (typeof mapping !== 'object' || typeof value !== 'string') {
|
||||||
throw new InvalidPipeArgumentError(I18nSelectPipe, mapping);
|
throw invalidPipeArgumentError(I18nSelectPipe, mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapping.hasOwnProperty(value)) {
|
if (mapping.hasOwnProperty(value)) {
|
||||||
|
@ -8,11 +8,8 @@
|
|||||||
|
|
||||||
import {Type} from '@angular/core';
|
import {Type} from '@angular/core';
|
||||||
|
|
||||||
import {BaseError} from '../facade/errors';
|
|
||||||
import {stringify} from '../facade/lang';
|
import {stringify} from '../facade/lang';
|
||||||
|
|
||||||
export class InvalidPipeArgumentError extends BaseError {
|
export function invalidPipeArgumentError(type: Type<any>, value: Object) {
|
||||||
constructor(type: Type<any>, value: Object) {
|
return Error(`InvalidPipeArgument: '${value}' for pipe '${stringify(type)}'`);
|
||||||
super(`Invalid argument '${value}' for pipe '${stringify(type)}'`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import {Inject, LOCALE_ID, Pipe, PipeTransform, Type} from '@angular/core';
|
|||||||
import {NumberWrapper} from '../facade/lang';
|
import {NumberWrapper} from '../facade/lang';
|
||||||
|
|
||||||
import {NumberFormatStyle, NumberFormatter} from './intl';
|
import {NumberFormatStyle, NumberFormatter} from './intl';
|
||||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||||
|
|
||||||
const _NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
|
const _NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ function formatNumber(
|
|||||||
// Convert strings to numbers
|
// Convert strings to numbers
|
||||||
value = typeof value === 'string' && NumberWrapper.isNumeric(value) ? +value : value;
|
value = typeof value === 'string' && NumberWrapper.isNumeric(value) ? +value : value;
|
||||||
if (typeof value !== 'number') {
|
if (typeof value !== 'number') {
|
||||||
throw new InvalidPipeArgumentError(pipe, value);
|
throw invalidPipeArgumentError(pipe, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let minInt: number;
|
let minInt: number;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Pipe, PipeTransform} from '@angular/core';
|
import {Pipe, PipeTransform} from '@angular/core';
|
||||||
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
|
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngModule CommonModule
|
* @ngModule CommonModule
|
||||||
@ -60,7 +60,7 @@ export class SlicePipe implements PipeTransform {
|
|||||||
if (value == null) return value;
|
if (value == null) return value;
|
||||||
|
|
||||||
if (!this.supports(value)) {
|
if (!this.supports(value)) {
|
||||||
throw new InvalidPipeArgumentError(SlicePipe, value);
|
throw invalidPipeArgumentError(SlicePipe, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value.slice(start, end);
|
return value.slice(start, end);
|
||||||
|
@ -59,7 +59,7 @@ export function main() {
|
|||||||
() => { expect(() => pipe.transform(isoStringWithoutTime)).not.toThrow(); });
|
() => { expect(() => pipe.transform(isoStringWithoutTime)).not.toThrow(); });
|
||||||
|
|
||||||
it('should not support other objects',
|
it('should not support other objects',
|
||||||
() => expect(() => pipe.transform({})).toThrowError(/Invalid argument/));
|
() => expect(() => pipe.transform({})).toThrowError(/InvalidPipeArgument/));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('transform', () => {
|
describe('transform', () => {
|
||||||
|
@ -13,8 +13,8 @@ import 'reflect-metadata';
|
|||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import * as tsc from '@angular/tsc-wrapped';
|
import * as tsc from '@angular/tsc-wrapped';
|
||||||
|
import {isSyntaxError} from '@angular/compiler';
|
||||||
|
|
||||||
import {SyntaxError} from '@angular/compiler';
|
|
||||||
import {CodeGenerator} from './codegen';
|
import {CodeGenerator} from './codegen';
|
||||||
|
|
||||||
function codegen(
|
function codegen(
|
||||||
@ -29,7 +29,7 @@ export function main(
|
|||||||
const cliOptions = new tsc.NgcCliOptions(args);
|
const cliOptions = new tsc.NgcCliOptions(args);
|
||||||
|
|
||||||
return tsc.main(project, cliOptions, codegen).then(() => 0).catch(e => {
|
return tsc.main(project, cliOptions, codegen).then(() => 0).catch(e => {
|
||||||
if (e instanceof tsc.UserError || e instanceof SyntaxError) {
|
if (e instanceof tsc.UserError || isSyntaxError(e)) {
|
||||||
consoleError(e.message);
|
consoleError(e.message);
|
||||||
return Promise.resolve(1);
|
return Promise.resolve(1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,5 +62,5 @@ export * from './src/style_compiler';
|
|||||||
export * from './src/template_parser/template_parser';
|
export * from './src/template_parser/template_parser';
|
||||||
export {ViewCompiler} from './src/view_compiler/view_compiler';
|
export {ViewCompiler} from './src/view_compiler/view_compiler';
|
||||||
export {AnimationParser} from './src/animation/animation_parser';
|
export {AnimationParser} from './src/animation/animation_parser';
|
||||||
export {SyntaxError} from './src/util';
|
export {isSyntaxError, syntaxError} from './src/util';
|
||||||
// This file only reexports content of the `src` folder. Keep it that way.
|
// This file only reexports content of the `src` folder. Keep it that way.
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
import {Attribute, Component, ContentChild, ContentChildren, Directive, Host, HostBinding, HostListener, Inject, Injectable, Input, NgModule, Optional, Output, Pipe, Self, SkipSelf, ViewChild, ViewChildren, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
|
import {Attribute, Component, ContentChild, ContentChildren, Directive, Host, HostBinding, HostListener, Inject, Injectable, Input, NgModule, Optional, Output, Pipe, Self, SkipSelf, ViewChild, ViewChildren, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
|
||||||
|
|
||||||
import {ReflectorReader} from '../private_import_core';
|
import {ReflectorReader} from '../private_import_core';
|
||||||
import {SyntaxError} from '../util';
|
import {syntaxError} from '../util';
|
||||||
|
|
||||||
import {StaticSymbol} from './static_symbol';
|
import {StaticSymbol} from './static_symbol';
|
||||||
import {StaticSymbolResolver} from './static_symbol_resolver';
|
import {StaticSymbolResolver} from './static_symbol_resolver';
|
||||||
@ -566,7 +566,7 @@ export class StaticReflector implements ReflectorReader {
|
|||||||
if (e.fileName) {
|
if (e.fileName) {
|
||||||
throw positionalError(message, e.fileName, e.line, e.column);
|
throw positionalError(message, e.fileName, e.line, e.column);
|
||||||
}
|
}
|
||||||
throw new SyntaxError(message);
|
throw syntaxError(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
|
|
||||||
import * as chars from '../chars';
|
import * as chars from '../chars';
|
||||||
import {BaseError} from '../facade/errors';
|
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
|
|
||||||
export enum CssTokenType {
|
export enum CssTokenType {
|
||||||
@ -42,7 +41,7 @@ export enum CssLexerMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class LexedCssResult {
|
export class LexedCssResult {
|
||||||
constructor(public error: CssScannerError, public token: CssToken) {}
|
constructor(public error: Error, public token: CssToken) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateErrorMessage(
|
export function generateErrorMessage(
|
||||||
@ -86,16 +85,22 @@ export class CssLexer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CssScannerError extends BaseError {
|
export function cssScannerError(token: CssToken, message: string): Error {
|
||||||
public rawMessage: string;
|
const error = Error('CssParseError: ' + message);
|
||||||
public message: string;
|
(error as any)[ERROR_RAW_MESSAGE] = message;
|
||||||
|
(error as any)[ERROR_TOKEN] = token;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(public token: CssToken, message: string) {
|
const ERROR_TOKEN = 'ngToken';
|
||||||
super('Css Parse Error: ' + message);
|
const ERROR_RAW_MESSAGE = 'ngRawMessage';
|
||||||
this.rawMessage = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
toString(): string { return this.message; }
|
export function getRawMessage(error: Error): string {
|
||||||
|
return (error as any)[ERROR_RAW_MESSAGE];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getToken(error: Error): CssToken {
|
||||||
|
return (error as any)[ERROR_TOKEN];
|
||||||
}
|
}
|
||||||
|
|
||||||
function _trackWhitespace(mode: CssLexerMode) {
|
function _trackWhitespace(mode: CssLexerMode) {
|
||||||
@ -122,7 +127,7 @@ export class CssScanner {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
_currentMode: CssLexerMode = CssLexerMode.BLOCK;
|
_currentMode: CssLexerMode = CssLexerMode.BLOCK;
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_currentError: CssScannerError = null;
|
_currentError: Error = null;
|
||||||
|
|
||||||
constructor(public input: string, private _trackComments: boolean = false) {
|
constructor(public input: string, private _trackComments: boolean = false) {
|
||||||
this.length = this.input.length;
|
this.length = this.input.length;
|
||||||
@ -221,7 +226,7 @@ export class CssScanner {
|
|||||||
// mode so that the parser can recover...
|
// mode so that the parser can recover...
|
||||||
this.setMode(mode);
|
this.setMode(mode);
|
||||||
|
|
||||||
let error: CssScannerError = null;
|
let error: Error = null;
|
||||||
if (!isMatchingType || (isPresent(value) && value != next.strValue)) {
|
if (!isMatchingType || (isPresent(value) && value != next.strValue)) {
|
||||||
let errorMessage =
|
let errorMessage =
|
||||||
CssTokenType[next.type] + ' does not match expected ' + CssTokenType[type] + ' value';
|
CssTokenType[next.type] + ' does not match expected ' + CssTokenType[type] + ' value';
|
||||||
@ -230,7 +235,7 @@ export class CssScanner {
|
|||||||
errorMessage += ' ("' + next.strValue + '" should match "' + value + '")';
|
errorMessage += ' ("' + next.strValue + '" should match "' + value + '")';
|
||||||
}
|
}
|
||||||
|
|
||||||
error = new CssScannerError(
|
error = cssScannerError(
|
||||||
next, generateErrorMessage(
|
next, generateErrorMessage(
|
||||||
this.input, errorMessage, next.strValue, previousIndex, previousLine,
|
this.input, errorMessage, next.strValue, previousIndex, previousLine,
|
||||||
previousColumn));
|
previousColumn));
|
||||||
@ -483,7 +488,7 @@ export class CssScanner {
|
|||||||
if (!doNotAdvance) {
|
if (!doNotAdvance) {
|
||||||
this.advance();
|
this.advance();
|
||||||
}
|
}
|
||||||
this._currentError = new CssScannerError(invalidToken, errorMessage);
|
this._currentError = cssScannerError(invalidToken, errorMessage);
|
||||||
return invalidToken;
|
return invalidToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import {isPresent} from '../facade/lang';
|
|||||||
import {ParseError, ParseLocation, ParseSourceFile, ParseSourceSpan} from '../parse_util';
|
import {ParseError, ParseLocation, ParseSourceFile, ParseSourceSpan} from '../parse_util';
|
||||||
|
|
||||||
import {BlockType, CssAst, CssAtRulePredicateAst, CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssPseudoSelectorAst, CssRuleAst, CssSelectorAst, CssSelectorRuleAst, CssSimpleSelectorAst, CssStyleSheetAst, CssStyleValueAst, CssStylesBlockAst, CssUnknownRuleAst, CssUnknownTokenListAst, mergeTokens} from './css_ast';
|
import {BlockType, CssAst, CssAtRulePredicateAst, CssBlockAst, CssBlockDefinitionRuleAst, CssBlockRuleAst, CssDefinitionAst, CssInlineRuleAst, CssKeyframeDefinitionAst, CssKeyframeRuleAst, CssMediaQueryRuleAst, CssPseudoSelectorAst, CssRuleAst, CssSelectorAst, CssSelectorRuleAst, CssSimpleSelectorAst, CssStyleSheetAst, CssStyleValueAst, CssStylesBlockAst, CssUnknownRuleAst, CssUnknownTokenListAst, mergeTokens} from './css_ast';
|
||||||
import {CssLexer, CssLexerMode, CssScanner, CssToken, CssTokenType, generateErrorMessage, isNewline} from './css_lexer';
|
import {CssLexer, CssLexerMode, CssScanner, CssToken, CssTokenType, generateErrorMessage, getRawMessage, isNewline} from './css_lexer';
|
||||||
|
|
||||||
const SPACE_OPERATOR = ' ';
|
const SPACE_OPERATOR = ' ';
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ export class CssParser {
|
|||||||
const token = output.token;
|
const token = output.token;
|
||||||
const error = output.error;
|
const error = output.error;
|
||||||
if (isPresent(error)) {
|
if (isPresent(error)) {
|
||||||
this._error(error.rawMessage, token);
|
this._error(getRawMessage(error), token);
|
||||||
}
|
}
|
||||||
this._lastToken = token;
|
this._lastToken = token;
|
||||||
return token;
|
return token;
|
||||||
@ -393,7 +393,7 @@ export class CssParser {
|
|||||||
const token = output.token;
|
const token = output.token;
|
||||||
const error = output.error;
|
const error = output.error;
|
||||||
if (isPresent(error)) {
|
if (isPresent(error)) {
|
||||||
this._error(error.rawMessage, token);
|
this._error(getRawMessage(error), token);
|
||||||
}
|
}
|
||||||
this._lastToken = token;
|
this._lastToken = token;
|
||||||
return token;
|
return token;
|
||||||
|
@ -19,7 +19,7 @@ import {ResourceLoader} from './resource_loader';
|
|||||||
import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver';
|
import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver';
|
||||||
import {PreparsedElementType, preparseElement} from './template_parser/template_preparser';
|
import {PreparsedElementType, preparseElement} from './template_parser/template_preparser';
|
||||||
import {UrlResolver} from './url_resolver';
|
import {UrlResolver} from './url_resolver';
|
||||||
import {SyncAsyncResult, SyntaxError} from './util';
|
import {SyncAsyncResult, syntaxError} from './util';
|
||||||
|
|
||||||
export interface PrenormalizedTemplateMetadata {
|
export interface PrenormalizedTemplateMetadata {
|
||||||
componentType: any;
|
componentType: any;
|
||||||
@ -67,19 +67,19 @@ export class DirectiveNormalizer {
|
|||||||
let normalizedTemplateAsync: Promise<CompileTemplateMetadata>;
|
let normalizedTemplateAsync: Promise<CompileTemplateMetadata>;
|
||||||
if (prenormData.template != null) {
|
if (prenormData.template != null) {
|
||||||
if (typeof prenormData.template !== 'string') {
|
if (typeof prenormData.template !== 'string') {
|
||||||
throw new SyntaxError(
|
throw syntaxError(
|
||||||
`The template specified for component ${stringify(prenormData.componentType)} is not a string`);
|
`The template specified for component ${stringify(prenormData.componentType)} is not a string`);
|
||||||
}
|
}
|
||||||
normalizedTemplateSync = this.normalizeTemplateSync(prenormData);
|
normalizedTemplateSync = this.normalizeTemplateSync(prenormData);
|
||||||
normalizedTemplateAsync = Promise.resolve(normalizedTemplateSync);
|
normalizedTemplateAsync = Promise.resolve(normalizedTemplateSync);
|
||||||
} else if (prenormData.templateUrl) {
|
} else if (prenormData.templateUrl) {
|
||||||
if (typeof prenormData.templateUrl !== 'string') {
|
if (typeof prenormData.templateUrl !== 'string') {
|
||||||
throw new SyntaxError(
|
throw syntaxError(
|
||||||
`The templateUrl specified for component ${stringify(prenormData.componentType)} is not a string`);
|
`The templateUrl specified for component ${stringify(prenormData.componentType)} is not a string`);
|
||||||
}
|
}
|
||||||
normalizedTemplateAsync = this.normalizeTemplateAsync(prenormData);
|
normalizedTemplateAsync = this.normalizeTemplateAsync(prenormData);
|
||||||
} else {
|
} else {
|
||||||
throw new SyntaxError(
|
throw syntaxError(
|
||||||
`No template specified for component ${stringify(prenormData.componentType)}`);
|
`No template specified for component ${stringify(prenormData.componentType)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ export class DirectiveNormalizer {
|
|||||||
template, stringify(prenomData.componentType), true, interpolationConfig);
|
template, stringify(prenomData.componentType), true, interpolationConfig);
|
||||||
if (rootNodesAndErrors.errors.length > 0) {
|
if (rootNodesAndErrors.errors.length > 0) {
|
||||||
const errorString = rootNodesAndErrors.errors.join('\n');
|
const errorString = rootNodesAndErrors.errors.join('\n');
|
||||||
throw new SyntaxError(`Template parse errors:\n${errorString}`);
|
throw syntaxError(`Template parse errors:\n${errorString}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const templateMetadataStyles = this.normalizeStylesheet(new CompileStylesheetMetadata({
|
const templateMetadataStyles = this.normalizeStylesheet(new CompileStylesheetMetadata({
|
||||||
|
@ -20,11 +20,11 @@ import {CompilerInjectable} from './injectable';
|
|||||||
import {hasLifecycleHook} from './lifecycle_reflector';
|
import {hasLifecycleHook} from './lifecycle_reflector';
|
||||||
import {NgModuleResolver} from './ng_module_resolver';
|
import {NgModuleResolver} from './ng_module_resolver';
|
||||||
import {PipeResolver} from './pipe_resolver';
|
import {PipeResolver} from './pipe_resolver';
|
||||||
import {ComponentStillLoadingError, LIFECYCLE_HOOKS_VALUES, ReflectorReader, reflector} from './private_import_core';
|
import {ERROR_COMPONENT_TYPE, LIFECYCLE_HOOKS_VALUES, ReflectorReader, reflector} from './private_import_core';
|
||||||
import {ElementSchemaRegistry} from './schema/element_schema_registry';
|
import {ElementSchemaRegistry} from './schema/element_schema_registry';
|
||||||
import {SummaryResolver} from './summary_resolver';
|
import {SummaryResolver} from './summary_resolver';
|
||||||
import {getUrlScheme} from './url_resolver';
|
import {getUrlScheme} from './url_resolver';
|
||||||
import {MODULE_SUFFIX, SyntaxError, ValueTransformer, visitValue} from './util';
|
import {MODULE_SUFFIX, ValueTransformer, syntaxError, visitValue} from './util';
|
||||||
|
|
||||||
export type ErrorCollector = (error: any, type?: any) => void;
|
export type ErrorCollector = (error: any, type?: any) => void;
|
||||||
export const ERROR_COLLECTOR_TOKEN = new InjectionToken('ErrorCollector');
|
export const ERROR_COLLECTOR_TOKEN = new InjectionToken('ErrorCollector');
|
||||||
@ -254,7 +254,7 @@ export class CompileMetadataResolver {
|
|||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
if (isSync) {
|
if (isSync) {
|
||||||
this._reportError(new ComponentStillLoadingError(directiveType), directiveType);
|
this._reportError(componentStillLoadingError(directiveType), directiveType);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return templateMeta.asyncResult.then(createDirectiveMetadata);
|
return templateMeta.asyncResult.then(createDirectiveMetadata);
|
||||||
@ -328,7 +328,7 @@ export class CompileMetadataResolver {
|
|||||||
// Directive
|
// Directive
|
||||||
if (!selector) {
|
if (!selector) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Directive ${stringifyType(directiveType)} has no selector, please add it!`),
|
`Directive ${stringifyType(directiveType)} has no selector, please add it!`),
|
||||||
directiveType);
|
directiveType);
|
||||||
selector = 'error';
|
selector = 'error';
|
||||||
@ -383,7 +383,7 @@ export class CompileMetadataResolver {
|
|||||||
const dirMeta = this._directiveCache.get(directiveType);
|
const dirMeta = this._directiveCache.get(directiveType);
|
||||||
if (!dirMeta) {
|
if (!dirMeta) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Illegal state: getDirectiveMetadata can only be called after loadNgModuleDirectiveAndPipeMetadata for a module that declares it. Directive ${stringifyType(directiveType)}.`),
|
`Illegal state: getDirectiveMetadata can only be called after loadNgModuleDirectiveAndPipeMetadata for a module that declares it. Directive ${stringifyType(directiveType)}.`),
|
||||||
directiveType);
|
directiveType);
|
||||||
}
|
}
|
||||||
@ -395,7 +395,7 @@ export class CompileMetadataResolver {
|
|||||||
<cpl.CompileDirectiveSummary>this._loadSummary(dirType, cpl.CompileSummaryKind.Directive);
|
<cpl.CompileDirectiveSummary>this._loadSummary(dirType, cpl.CompileSummaryKind.Directive);
|
||||||
if (!dirSummary) {
|
if (!dirSummary) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Illegal state: Could not load the summary for directive ${stringifyType(dirType)}.`),
|
`Illegal state: Could not load the summary for directive ${stringifyType(dirType)}.`),
|
||||||
dirType);
|
dirType);
|
||||||
}
|
}
|
||||||
@ -478,7 +478,7 @@ export class CompileMetadataResolver {
|
|||||||
const importedModuleSummary = this.getNgModuleSummary(importedModuleType);
|
const importedModuleSummary = this.getNgModuleSummary(importedModuleType);
|
||||||
if (!importedModuleSummary) {
|
if (!importedModuleSummary) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Unexpected ${this._getTypeDescriptor(importedType)} '${stringifyType(importedType)}' imported by the module '${stringifyType(moduleType)}'`),
|
`Unexpected ${this._getTypeDescriptor(importedType)} '${stringifyType(importedType)}' imported by the module '${stringifyType(moduleType)}'`),
|
||||||
moduleType);
|
moduleType);
|
||||||
return;
|
return;
|
||||||
@ -486,7 +486,7 @@ export class CompileMetadataResolver {
|
|||||||
importedModules.push(importedModuleSummary);
|
importedModules.push(importedModuleSummary);
|
||||||
} else {
|
} else {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Unexpected value '${stringifyType(importedType)}' imported by the module '${stringifyType(moduleType)}'`),
|
`Unexpected value '${stringifyType(importedType)}' imported by the module '${stringifyType(moduleType)}'`),
|
||||||
moduleType);
|
moduleType);
|
||||||
return;
|
return;
|
||||||
@ -498,7 +498,7 @@ export class CompileMetadataResolver {
|
|||||||
flattenAndDedupeArray(meta.exports).forEach((exportedType) => {
|
flattenAndDedupeArray(meta.exports).forEach((exportedType) => {
|
||||||
if (!isValidType(exportedType)) {
|
if (!isValidType(exportedType)) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Unexpected value '${stringifyType(exportedType)}' exported by the module '${stringifyType(moduleType)}'`),
|
`Unexpected value '${stringifyType(exportedType)}' exported by the module '${stringifyType(moduleType)}'`),
|
||||||
moduleType);
|
moduleType);
|
||||||
return;
|
return;
|
||||||
@ -519,7 +519,7 @@ export class CompileMetadataResolver {
|
|||||||
flattenAndDedupeArray(meta.declarations).forEach((declaredType) => {
|
flattenAndDedupeArray(meta.declarations).forEach((declaredType) => {
|
||||||
if (!isValidType(declaredType)) {
|
if (!isValidType(declaredType)) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Unexpected value '${stringifyType(declaredType)}' declared by the module '${stringifyType(moduleType)}'`),
|
`Unexpected value '${stringifyType(declaredType)}' declared by the module '${stringifyType(moduleType)}'`),
|
||||||
moduleType);
|
moduleType);
|
||||||
return;
|
return;
|
||||||
@ -536,7 +536,7 @@ export class CompileMetadataResolver {
|
|||||||
this._addTypeToModule(declaredType, moduleType);
|
this._addTypeToModule(declaredType, moduleType);
|
||||||
} else {
|
} else {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Unexpected ${this._getTypeDescriptor(declaredType)} '${stringifyType(declaredType)}' declared by the module '${stringifyType(moduleType)}'`),
|
`Unexpected ${this._getTypeDescriptor(declaredType)} '${stringifyType(declaredType)}' declared by the module '${stringifyType(moduleType)}'`),
|
||||||
moduleType);
|
moduleType);
|
||||||
return;
|
return;
|
||||||
@ -555,7 +555,7 @@ export class CompileMetadataResolver {
|
|||||||
transitiveModule.addExportedPipe(exportedId);
|
transitiveModule.addExportedPipe(exportedId);
|
||||||
} else {
|
} else {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Can't export ${this._getTypeDescriptor(exportedId.reference)} ${stringifyType(exportedId.reference)} from ${stringifyType(moduleType)} as it was neither declared nor imported!`),
|
`Can't export ${this._getTypeDescriptor(exportedId.reference)} ${stringifyType(exportedId.reference)} from ${stringifyType(moduleType)} as it was neither declared nor imported!`),
|
||||||
moduleType);
|
moduleType);
|
||||||
}
|
}
|
||||||
@ -578,7 +578,7 @@ export class CompileMetadataResolver {
|
|||||||
flattenAndDedupeArray(meta.bootstrap).forEach(type => {
|
flattenAndDedupeArray(meta.bootstrap).forEach(type => {
|
||||||
if (!isValidType(type)) {
|
if (!isValidType(type)) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Unexpected value '${stringifyType(type)}' used in the bootstrap property of module '${stringifyType(moduleType)}'`),
|
`Unexpected value '${stringifyType(type)}' used in the bootstrap property of module '${stringifyType(moduleType)}'`),
|
||||||
moduleType);
|
moduleType);
|
||||||
return;
|
return;
|
||||||
@ -642,7 +642,7 @@ export class CompileMetadataResolver {
|
|||||||
const oldModule = this._ngModuleOfTypes.get(type);
|
const oldModule = this._ngModuleOfTypes.get(type);
|
||||||
if (oldModule && oldModule !== moduleType) {
|
if (oldModule && oldModule !== moduleType) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Type ${stringifyType(type)} is part of the declarations of 2 modules: ${stringifyType(oldModule)} and ${stringifyType(moduleType)}! ` +
|
`Type ${stringifyType(type)} is part of the declarations of 2 modules: ${stringifyType(oldModule)} and ${stringifyType(moduleType)}! ` +
|
||||||
`Please consider moving ${stringifyType(type)} to a higher module that imports ${stringifyType(oldModule)} and ${stringifyType(moduleType)}. ` +
|
`Please consider moving ${stringifyType(type)} to a higher module that imports ${stringifyType(oldModule)} and ${stringifyType(moduleType)}. ` +
|
||||||
`You can also create a new NgModule that exports and includes ${stringifyType(type)} then import that NgModule in ${stringifyType(oldModule)} and ${stringifyType(moduleType)}.`),
|
`You can also create a new NgModule that exports and includes ${stringifyType(type)} then import that NgModule in ${stringifyType(oldModule)} and ${stringifyType(moduleType)}.`),
|
||||||
@ -738,7 +738,7 @@ export class CompileMetadataResolver {
|
|||||||
const pipeMeta = this._pipeCache.get(pipeType);
|
const pipeMeta = this._pipeCache.get(pipeType);
|
||||||
if (!pipeMeta) {
|
if (!pipeMeta) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Illegal state: getPipeMetadata can only be called after loadNgModuleDirectiveAndPipeMetadata for a module that declares it. Pipe ${stringifyType(pipeType)}.`),
|
`Illegal state: getPipeMetadata can only be called after loadNgModuleDirectiveAndPipeMetadata for a module that declares it. Pipe ${stringifyType(pipeType)}.`),
|
||||||
pipeType);
|
pipeType);
|
||||||
}
|
}
|
||||||
@ -750,7 +750,7 @@ export class CompileMetadataResolver {
|
|||||||
<cpl.CompilePipeSummary>this._loadSummary(pipeType, cpl.CompileSummaryKind.Pipe);
|
<cpl.CompilePipeSummary>this._loadSummary(pipeType, cpl.CompileSummaryKind.Pipe);
|
||||||
if (!pipeSummary) {
|
if (!pipeSummary) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Illegal state: Could not load the summary for pipe ${stringifyType(pipeType)}.`),
|
`Illegal state: Could not load the summary for pipe ${stringifyType(pipeType)}.`),
|
||||||
pipeType);
|
pipeType);
|
||||||
}
|
}
|
||||||
@ -833,7 +833,7 @@ export class CompileMetadataResolver {
|
|||||||
const depsTokens =
|
const depsTokens =
|
||||||
dependenciesMetadata.map((dep) => dep ? stringifyType(dep.token) : '?').join(', ');
|
dependenciesMetadata.map((dep) => dep ? stringifyType(dep.token) : '?').join(', ');
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Can't resolve all parameters for ${stringifyType(typeOrFunc)}: (${depsTokens}).`),
|
`Can't resolve all parameters for ${stringifyType(typeOrFunc)}: (${depsTokens}).`),
|
||||||
typeOrFunc);
|
typeOrFunc);
|
||||||
}
|
}
|
||||||
@ -868,7 +868,7 @@ export class CompileMetadataResolver {
|
|||||||
} else if (isValidType(provider)) {
|
} else if (isValidType(provider)) {
|
||||||
providerMeta = new cpl.ProviderMeta(provider, {useClass: provider});
|
providerMeta = new cpl.ProviderMeta(provider, {useClass: provider});
|
||||||
} else if (provider === void 0) {
|
} else if (provider === void 0) {
|
||||||
this._reportError(new SyntaxError(
|
this._reportError(syntaxError(
|
||||||
`Encountered undefined provider! Usually this means you have a circular dependencies (might be caused by using 'barrel' index.ts files.`));
|
`Encountered undefined provider! Usually this means you have a circular dependencies (might be caused by using 'barrel' index.ts files.`));
|
||||||
} else {
|
} else {
|
||||||
const providersInfo =
|
const providersInfo =
|
||||||
@ -886,7 +886,7 @@ export class CompileMetadataResolver {
|
|||||||
[]))
|
[]))
|
||||||
.join(', ');
|
.join(', ');
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`),
|
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`),
|
||||||
type);
|
type);
|
||||||
}
|
}
|
||||||
@ -902,7 +902,7 @@ export class CompileMetadataResolver {
|
|||||||
|
|
||||||
private _validateProvider(provider: any): void {
|
private _validateProvider(provider: any): void {
|
||||||
if (provider.hasOwnProperty('useClass') && provider.useClass == null) {
|
if (provider.hasOwnProperty('useClass') && provider.useClass == null) {
|
||||||
this._reportError(new SyntaxError(
|
this._reportError(syntaxError(
|
||||||
`Invalid provider for ${stringifyType(provider.provide)}. useClass cannot be ${provider.useClass}.
|
`Invalid provider for ${stringifyType(provider.provide)}. useClass cannot be ${provider.useClass}.
|
||||||
Usually it happens when:
|
Usually it happens when:
|
||||||
1. There's a circular dependency (might be caused by using index.ts (barrel) files).
|
1. There's a circular dependency (might be caused by using index.ts (barrel) files).
|
||||||
@ -917,13 +917,13 @@ export class CompileMetadataResolver {
|
|||||||
|
|
||||||
if (provider.useFactory || provider.useExisting || provider.useClass) {
|
if (provider.useFactory || provider.useExisting || provider.useClass) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(`The ANALYZE_FOR_ENTRY_COMPONENTS token only supports useValue!`), type);
|
syntaxError(`The ANALYZE_FOR_ENTRY_COMPONENTS token only supports useValue!`), type);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!provider.multi) {
|
if (!provider.multi) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(`The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'!`),
|
syntaxError(`The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'!`),
|
||||||
type);
|
type);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -1006,7 +1006,7 @@ export class CompileMetadataResolver {
|
|||||||
} else {
|
} else {
|
||||||
if (!q.selector) {
|
if (!q.selector) {
|
||||||
this._reportError(
|
this._reportError(
|
||||||
new SyntaxError(
|
syntaxError(
|
||||||
`Can't construct a query for the property "${propertyName}" of "${stringifyType(typeOrFunc)}" since the query selector wasn't defined.`),
|
`Can't construct a query for the property "${propertyName}" of "${stringifyType(typeOrFunc)}" since the query selector wasn't defined.`),
|
||||||
typeOrFunc);
|
typeOrFunc);
|
||||||
}
|
}
|
||||||
@ -1074,7 +1074,7 @@ export function componentModuleUrl(
|
|||||||
const scheme = getUrlScheme(moduleId);
|
const scheme = getUrlScheme(moduleId);
|
||||||
return scheme ? moduleId : `package:${moduleId}${MODULE_SUFFIX}`;
|
return scheme ? moduleId : `package:${moduleId}${MODULE_SUFFIX}`;
|
||||||
} else if (moduleId !== null && moduleId !== void 0) {
|
} else if (moduleId !== null && moduleId !== void 0) {
|
||||||
throw new SyntaxError(
|
throw syntaxError(
|
||||||
`moduleId should be a string in "${stringifyType(type)}". See https://goo.gl/wIDDiL for more information.\n` +
|
`moduleId should be a string in "${stringifyType(type)}". See https://goo.gl/wIDDiL for more information.\n` +
|
||||||
`If you're using Webpack you should inline the template and the styles, see https://goo.gl/X2J8zc.`);
|
`If you're using Webpack you should inline the template and the styles, see https://goo.gl/X2J8zc.`);
|
||||||
}
|
}
|
||||||
@ -1099,3 +1099,14 @@ function stringifyType(type: any): string {
|
|||||||
return stringify(type);
|
return stringify(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that a component is still being loaded in a synchronous compile.
|
||||||
|
*/
|
||||||
|
function componentStillLoadingError(compType: Type<any>) {
|
||||||
|
debugger;
|
||||||
|
const error =
|
||||||
|
Error(`Can't compile synchronously as ${stringify(compType)} is still being loaded!`);
|
||||||
|
(error as any)[ERROR_COMPONENT_TYPE] = compType;
|
||||||
|
return error;
|
||||||
|
}
|
@ -58,6 +58,7 @@ export const AnimationStyles: typeof r.AnimationStyles = r.AnimationStyles;
|
|||||||
export const ANY_STATE = r.ANY_STATE;
|
export const ANY_STATE = r.ANY_STATE;
|
||||||
export const DEFAULT_STATE = r.DEFAULT_STATE;
|
export const DEFAULT_STATE = r.DEFAULT_STATE;
|
||||||
export const EMPTY_STATE = r.EMPTY_STATE;
|
export const EMPTY_STATE = r.EMPTY_STATE;
|
||||||
|
export const ERROR_COMPONENT_TYPE = r.ERROR_COMPONENT_TYPE;
|
||||||
export const FILL_STYLE_FLAG = r.FILL_STYLE_FLAG;
|
export const FILL_STYLE_FLAG = r.FILL_STYLE_FLAG;
|
||||||
export const prepareFinalAnimationStyles: typeof r.prepareFinalAnimationStyles =
|
export const prepareFinalAnimationStyles: typeof r.prepareFinalAnimationStyles =
|
||||||
r.prepareFinalAnimationStyles;
|
r.prepareFinalAnimationStyles;
|
||||||
@ -68,9 +69,6 @@ export const collectAndResolveStyles: typeof r.collectAndResolveStyles = r.colle
|
|||||||
export const renderStyles: typeof r.renderStyles = r.renderStyles;
|
export const renderStyles: typeof r.renderStyles = r.renderStyles;
|
||||||
export type ViewMetadata = typeof r._ViewMetadata;
|
export type ViewMetadata = typeof r._ViewMetadata;
|
||||||
export const ViewMetadata: typeof r.ViewMetadata = r.ViewMetadata;
|
export const ViewMetadata: typeof r.ViewMetadata = r.ViewMetadata;
|
||||||
export type ComponentStillLoadingError = typeof r._ComponentStillLoadingError;
|
|
||||||
export const ComponentStillLoadingError: typeof r.ComponentStillLoadingError =
|
|
||||||
r.ComponentStillLoadingError;
|
|
||||||
export const AnimationTransition: typeof r.AnimationTransition = r.AnimationTransition;
|
export const AnimationTransition: typeof r.AnimationTransition = r.AnimationTransition;
|
||||||
export type SetterFn = typeof r._SetterFn;
|
export type SetterFn = typeof r._SetterFn;
|
||||||
export type GetterFn = typeof r._GetterFn;
|
export type GetterFn = typeof r._GetterFn;
|
||||||
|
@ -24,7 +24,7 @@ import {ProviderElementContext, ProviderViewContext} from '../provider_analyzer'
|
|||||||
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
||||||
import {CssSelector, SelectorMatcher} from '../selector';
|
import {CssSelector, SelectorMatcher} from '../selector';
|
||||||
import {isStyleUrlResolvable} from '../style_url_resolver';
|
import {isStyleUrlResolvable} from '../style_url_resolver';
|
||||||
import {SyntaxError} from '../util';
|
import {syntaxError} from '../util';
|
||||||
import {BindingParser, BoundProperty} from './binding_parser';
|
import {BindingParser, BoundProperty} from './binding_parser';
|
||||||
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from './template_ast';
|
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from './template_ast';
|
||||||
import {PreparsedElementType, preparseElement} from './template_preparser';
|
import {PreparsedElementType, preparseElement} from './template_preparser';
|
||||||
@ -99,7 +99,7 @@ export class TemplateParser {
|
|||||||
|
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
const errorString = errors.join('\n');
|
const errorString = errors.join('\n');
|
||||||
throw new SyntaxError(`Template parse errors:\n${errorString}`);
|
throw syntaxError(`Template parse errors:\n${errorString}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.templateAst;
|
return result.templateAst;
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {BaseError} from './facade/errors';
|
|
||||||
import {isPrimitive, isStrictStringMap} from './facade/lang';
|
import {isPrimitive, isStrictStringMap} from './facade/lang';
|
||||||
export const MODULE_SUFFIX = '';
|
export const MODULE_SUFFIX = '';
|
||||||
|
|
||||||
@ -79,4 +78,14 @@ export class SyncAsyncResult<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SyntaxError extends BaseError {}
|
export function syntaxError(msg: string): Error {
|
||||||
|
const error = Error(msg);
|
||||||
|
(error as any)[ERROR_SYNTAX_ERROR] = true;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ERROR_SYNTAX_ERROR = 'ngSyntaxError';
|
||||||
|
|
||||||
|
export function isSyntaxError(error: Error): boolean {
|
||||||
|
return (error as any)[ERROR_SYNTAX_ERROR];
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, StaticSymbolResolverHost, SyntaxError} from '@angular/compiler';
|
import {StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, StaticSymbolResolverHost} from '@angular/compiler';
|
||||||
import {HostListener, Inject, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
|
import {HostListener, Inject, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
|
||||||
|
|
||||||
import {MockStaticSymbolResolverHost, MockSummaryResolver} from './static_symbol_resolver_spec';
|
import {MockStaticSymbolResolverHost, MockSummaryResolver} from './static_symbol_resolver_spec';
|
||||||
@ -354,7 +354,6 @@ describe('StaticReflector', () => {
|
|||||||
'Could not resolve ./does-not-exist.component relative to /tmp/src/function-reference.ts'
|
'Could not resolve ./does-not-exist.component relative to /tmp/src/function-reference.ts'
|
||||||
})))
|
})))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
'Error encountered resolving symbol values statically. Could not resolve ./does-not-exist.component relative to /tmp/src/function-reference.ts, resolving symbol AppModule in /tmp/src/function-reference.ts');
|
'Error encountered resolving symbol values statically. Could not resolve ./does-not-exist.component relative to /tmp/src/function-reference.ts, resolving symbol AppModule in /tmp/src/function-reference.ts');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {describe, expect, it} from '../../../core/testing/testing_internal';
|
import {describe, expect, it} from '../../../core/testing/testing_internal';
|
||||||
import {CssLexer, CssLexerMode, CssScannerError, CssToken, CssTokenType} from '../../src/css_parser/css_lexer';
|
import {CssLexer, CssLexerMode, CssToken, CssTokenType, cssScannerError, getRawMessage, getToken} from '../../src/css_parser/css_lexer';
|
||||||
import {isPresent} from '../../src/facade/lang';
|
import {isPresent} from '../../src/facade/lang';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
@ -22,7 +22,7 @@ export function main() {
|
|||||||
while (output != null) {
|
while (output != null) {
|
||||||
const error = output.error;
|
const error = output.error;
|
||||||
if (isPresent(error)) {
|
if (isPresent(error)) {
|
||||||
throw new CssScannerError(error.token, error.rawMessage);
|
throw cssScannerError(getToken(error), getRawMessage(error));
|
||||||
}
|
}
|
||||||
tokens.push(output.token);
|
tokens.push(output.token);
|
||||||
output = scanner.scan();
|
output = scanner.scan();
|
||||||
@ -279,7 +279,7 @@ export function main() {
|
|||||||
try {
|
try {
|
||||||
tokenize(cssCode, false, CssLexerMode.STYLE_BLOCK);
|
tokenize(cssCode, false, CssLexerMode.STYLE_BLOCK);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
capturedMessage = e.rawMessage;
|
capturedMessage = getRawMessage(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(capturedMessage).toMatch(/Unexpected character \[\>\] at column 0:7 in expression/g);
|
expect(capturedMessage).toMatch(/Unexpected character \[\>\] at column 0:7 in expression/g);
|
||||||
@ -288,7 +288,7 @@ export function main() {
|
|||||||
try {
|
try {
|
||||||
tokenize(cssCode, false, CssLexerMode.SELECTOR);
|
tokenize(cssCode, false, CssLexerMode.SELECTOR);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
capturedMessage = e.rawMessage;
|
capturedMessage = getRawMessage(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(capturedMessage).toEqual(null);
|
expect(capturedMessage).toEqual(null);
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {SyntaxError} from '@angular/compiler';
|
|
||||||
import {CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
|
import {CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
|
||||||
import {CompilerConfig} from '@angular/compiler/src/config';
|
import {CompilerConfig} from '@angular/compiler/src/config';
|
||||||
import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer';
|
import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer';
|
||||||
@ -31,23 +30,23 @@ export function main() {
|
|||||||
expect(() => normalizer.normalizeTemplate({
|
expect(() => normalizer.normalizeTemplate({
|
||||||
componentType: SomeComp,
|
componentType: SomeComp,
|
||||||
moduleUrl: SOME_MODULE_URL,
|
moduleUrl: SOME_MODULE_URL,
|
||||||
})).toThrowError(SyntaxError, 'No template specified for component SomeComp');
|
})).toThrowError('No template specified for component SomeComp');
|
||||||
}));
|
}));
|
||||||
it('should throw if template is not a string',
|
it('should throw if template is not a string',
|
||||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||||
expect(
|
expect(() => normalizer.normalizeTemplate({
|
||||||
() => normalizer.normalizeTemplate(
|
componentType: SomeComp,
|
||||||
{componentType: SomeComp, moduleUrl: SOME_MODULE_URL, template: <any>{}}))
|
moduleUrl: SOME_MODULE_URL,
|
||||||
.toThrowError(
|
template: <any>{}
|
||||||
SyntaxError, 'The template specified for component SomeComp is not a string');
|
})).toThrowError('The template specified for component SomeComp is not a string');
|
||||||
}));
|
}));
|
||||||
it('should throw if templateUrl is not a string',
|
it('should throw if templateUrl is not a string',
|
||||||
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
|
||||||
expect(
|
expect(() => normalizer.normalizeTemplate({
|
||||||
() => normalizer.normalizeTemplate(
|
componentType: SomeComp,
|
||||||
{componentType: SomeComp, moduleUrl: SOME_MODULE_URL, templateUrl: <any>{}}))
|
moduleUrl: SOME_MODULE_URL,
|
||||||
.toThrowError(
|
templateUrl: <any>{}
|
||||||
SyntaxError, 'The templateUrl specified for component SomeComp is not a string');
|
})).toThrowError('The templateUrl specified for component SomeComp is not a string');
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ import {identifierName} from '../src/compile_metadata';
|
|||||||
import {stringify} from '../src/facade/lang';
|
import {stringify} from '../src/facade/lang';
|
||||||
import {CompileMetadataResolver} from '../src/metadata_resolver';
|
import {CompileMetadataResolver} from '../src/metadata_resolver';
|
||||||
import {ResourceLoader} from '../src/resource_loader';
|
import {ResourceLoader} from '../src/resource_loader';
|
||||||
import {SyntaxError} from '../src/util';
|
|
||||||
import {MockResourceLoader} from '../testing/resource_loader_mock';
|
import {MockResourceLoader} from '../testing/resource_loader_mock';
|
||||||
import {MalformedStylesComponent} from './metadata_resolver_fixture';
|
import {MalformedStylesComponent} from './metadata_resolver_fixture';
|
||||||
|
|
||||||
@ -34,9 +33,8 @@ export function main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(() => resolver.getDirectiveMetadata(ComponentWithEverythingInline))
|
expect(() => resolver.getDirectiveMetadata(ComponentWithEverythingInline))
|
||||||
.toThrowError(SyntaxError, /Illegal state/);
|
.toThrowError(/Illegal state/);
|
||||||
expect(() => resolver.getPipeMetadata(SomePipe))
|
expect(() => resolver.getPipeMetadata(SomePipe)).toThrowError(/Illegal state/);
|
||||||
.toThrowError(SyntaxError, /Illegal state/);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should read metadata in sync for components with inline resources',
|
it('should read metadata in sync for components with inline resources',
|
||||||
@ -122,7 +120,7 @@ export function main() {
|
|||||||
|
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError, `moduleId should be a string in "ComponentWithInvalidModuleId". See` +
|
`moduleId should be a string in "ComponentWithInvalidModuleId". See` +
|
||||||
` https://goo.gl/wIDDiL for more information.\n` +
|
` https://goo.gl/wIDDiL for more information.\n` +
|
||||||
`If you're using Webpack you should inline the template and the styles, see` +
|
`If you're using Webpack you should inline the template and the styles, see` +
|
||||||
` https://goo.gl/X2J8zc.`);
|
` https://goo.gl/X2J8zc.`);
|
||||||
@ -146,7 +144,7 @@ export function main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
||||||
.toThrowError(SyntaxError, `Can't resolve all parameters for MyBrokenComp1: (?).`);
|
.toThrowError(`Can't resolve all parameters for MyBrokenComp1: (?).`);
|
||||||
}));
|
}));
|
||||||
it('should throw with descriptive error message when a directive is passed to imports',
|
it('should throw with descriptive error message when a directive is passed to imports',
|
||||||
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
|
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
|
||||||
@ -156,7 +154,6 @@ export function main() {
|
|||||||
expect(
|
expect(
|
||||||
() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithImportedComponent, true))
|
() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithImportedComponent, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Unexpected directive 'ComponentWithoutModuleId' imported by the module 'ModuleWithImportedComponent'`);
|
`Unexpected directive 'ComponentWithoutModuleId' imported by the module 'ModuleWithImportedComponent'`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -170,7 +167,6 @@ export function main() {
|
|||||||
}
|
}
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithImportedPipe, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithImportedPipe, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Unexpected pipe 'SomePipe' imported by the module 'ModuleWithImportedPipe'`);
|
`Unexpected pipe 'SomePipe' imported by the module 'ModuleWithImportedPipe'`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -184,7 +180,6 @@ export function main() {
|
|||||||
}
|
}
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithDeclaredModule, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithDeclaredModule, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Unexpected module 'SomeModule' declared by the module 'ModuleWithDeclaredModule'`);
|
`Unexpected module 'SomeModule' declared by the module 'ModuleWithDeclaredModule'`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -195,7 +190,6 @@ export function main() {
|
|||||||
}
|
}
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullDeclared, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullDeclared, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Unexpected value 'null' declared by the module 'ModuleWithNullDeclared'`);
|
`Unexpected value 'null' declared by the module 'ModuleWithNullDeclared'`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -206,7 +200,6 @@ export function main() {
|
|||||||
}
|
}
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullImported, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullImported, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Unexpected value 'null' imported by the module 'ModuleWithNullImported'`);
|
`Unexpected value 'null' imported by the module 'ModuleWithNullImported'`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -218,8 +211,7 @@ export function main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
||||||
.toThrowError(
|
.toThrowError(`Can't resolve all parameters for NonAnnotatedService: (?).`);
|
||||||
SyntaxError, `Can't resolve all parameters for NonAnnotatedService: (?).`);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should throw with descriptive error message when encounter invalid provider',
|
it('should throw with descriptive error message when encounter invalid provider',
|
||||||
@ -229,8 +221,7 @@ export function main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
||||||
.toThrowError(
|
.toThrowError(/Invalid provider for SimpleService. useClass cannot be undefined./);
|
||||||
SyntaxError, /Invalid provider for SimpleService. useClass cannot be undefined./);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should throw with descriptive error message when provider is undefined',
|
it('should throw with descriptive error message when provider is undefined',
|
||||||
@ -240,7 +231,7 @@ export function main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
||||||
.toThrowError(SyntaxError, /Encountered undefined provider!/);
|
.toThrowError(/Encountered undefined provider!/);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should throw with descriptive error message when one of providers is not present',
|
it('should throw with descriptive error message when one of providers is not present',
|
||||||
@ -251,7 +242,6 @@ export function main() {
|
|||||||
|
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Invalid providers for "MyBrokenComp3" - only instances of Provider and Type are allowed, got: [SimpleService, ?null?, ...]`);
|
`Invalid providers for "MyBrokenComp3" - only instances of Provider and Type are allowed, got: [SimpleService, ?null?, ...]`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -263,7 +253,6 @@ export function main() {
|
|||||||
|
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(SomeModule, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Invalid viewProviders for "MyBrokenComp4" - only instances of Provider and Type are allowed, got: [?null?, ...]`);
|
`Invalid viewProviders for "MyBrokenComp4" - only instances of Provider and Type are allowed, got: [?null?, ...]`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -278,13 +267,11 @@ export function main() {
|
|||||||
|
|
||||||
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullBootstrap, true))
|
expect(() => resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithNullBootstrap, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Unexpected value 'null' used in the bootstrap property of module 'ModuleWithNullBootstrap'`);
|
`Unexpected value 'null' used in the bootstrap property of module 'ModuleWithNullBootstrap'`);
|
||||||
expect(
|
expect(
|
||||||
() =>
|
() =>
|
||||||
resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithUndefinedBootstrap, true))
|
resolver.loadNgModuleDirectiveAndPipeMetadata(ModuleWithUndefinedBootstrap, true))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Unexpected value 'undefined' used in the bootstrap property of module 'ModuleWithUndefinedBootstrap'`);
|
`Unexpected value 'undefined' used in the bootstrap property of module 'ModuleWithUndefinedBootstrap'`);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {SyntaxError} from '@angular/compiler';
|
|
||||||
import {CompileAnimationEntryMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenReference} from '@angular/compiler/src/compile_metadata';
|
import {CompileAnimationEntryMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenReference} from '@angular/compiler/src/compile_metadata';
|
||||||
import {DomElementSchemaRegistry} from '@angular/compiler/src/schema/dom_element_schema_registry';
|
import {DomElementSchemaRegistry} from '@angular/compiler/src/schema/dom_element_schema_registry';
|
||||||
import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema_registry';
|
import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema_registry';
|
||||||
@ -374,7 +373,7 @@ export function main() {
|
|||||||
describe('errors', () => {
|
describe('errors', () => {
|
||||||
it('should throw error when binding to an unknown property', () => {
|
it('should throw error when binding to an unknown property', () => {
|
||||||
expect(() => parse('<my-component [invalidProp]="bar"></my-component>', []))
|
expect(() => parse('<my-component [invalidProp]="bar"></my-component>', []))
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
.toThrowError(`Template parse errors:
|
||||||
Can't bind to 'invalidProp' since it isn't a known property of 'my-component'.
|
Can't bind to 'invalidProp' since it isn't a known property of 'my-component'.
|
||||||
1. If 'my-component' is an Angular component and it has 'invalidProp' input, then verify that it is part of this module.
|
1. If 'my-component' is an Angular component and it has 'invalidProp' input, then verify that it is part of this module.
|
||||||
2. If 'my-component' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.
|
2. If 'my-component' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.
|
||||||
@ -382,16 +381,14 @@ Can't bind to 'invalidProp' since it isn't a known property of 'my-component'.
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error when binding to an unknown element w/o bindings', () => {
|
it('should throw error when binding to an unknown element w/o bindings', () => {
|
||||||
expect(() => parse('<unknown></unknown>', []))
|
expect(() => parse('<unknown></unknown>', [])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
'unknown' is not a known element:
|
'unknown' is not a known element:
|
||||||
1. If 'unknown' is an Angular component, then verify that it is part of this module.
|
1. If 'unknown' is an Angular component, then verify that it is part of this module.
|
||||||
2. If 'unknown' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("[ERROR ->]<unknown></unknown>"): TestComp@0:0`);
|
2. If 'unknown' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("[ERROR ->]<unknown></unknown>"): TestComp@0:0`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error when binding to an unknown custom element w/o bindings', () => {
|
it('should throw error when binding to an unknown custom element w/o bindings', () => {
|
||||||
expect(() => parse('<un-known></un-known>', []))
|
expect(() => parse('<un-known></un-known>', [])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
'un-known' is not a known element:
|
'un-known' is not a known element:
|
||||||
1. If 'un-known' is an Angular component, then verify that it is part of this module.
|
1. If 'un-known' is an Angular component, then verify that it is part of this module.
|
||||||
2. If 'un-known' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("[ERROR ->]<un-known></un-known>"): TestComp@0:0`);
|
2. If 'un-known' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("[ERROR ->]<un-known></un-known>"): TestComp@0:0`);
|
||||||
@ -399,13 +396,13 @@ Can't bind to 'invalidProp' since it isn't a known property of 'my-component'.
|
|||||||
|
|
||||||
it('should throw error when binding to an invalid property', () => {
|
it('should throw error when binding to an invalid property', () => {
|
||||||
expect(() => parse('<my-component [onEvent]="bar"></my-component>', []))
|
expect(() => parse('<my-component [onEvent]="bar"></my-component>', []))
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
.toThrowError(`Template parse errors:
|
||||||
Binding to property 'onEvent' is disallowed for security reasons ("<my-component [ERROR ->][onEvent]="bar"></my-component>"): TestComp@0:14`);
|
Binding to property 'onEvent' is disallowed for security reasons ("<my-component [ERROR ->][onEvent]="bar"></my-component>"): TestComp@0:14`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error when binding to an invalid attribute', () => {
|
it('should throw error when binding to an invalid attribute', () => {
|
||||||
expect(() => parse('<my-component [attr.onEvent]="bar"></my-component>', []))
|
expect(() => parse('<my-component [attr.onEvent]="bar"></my-component>', []))
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
.toThrowError(`Template parse errors:
|
||||||
Binding to attribute 'onEvent' is disallowed for security reasons ("<my-component [ERROR ->][attr.onEvent]="bar"></my-component>"): TestComp@0:14`);
|
Binding to attribute 'onEvent' is disallowed for security reasons ("<my-component [ERROR ->][attr.onEvent]="bar"></my-component>"): TestComp@0:14`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -447,7 +444,6 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
|
|||||||
() => {
|
() => {
|
||||||
expect(() => { parse('<div @someAnimation="value2">', [], [], []); })
|
expect(() => { parse('<div @someAnimation="value2">', [], [], []); })
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
/Assigning animation triggers via @prop="exp" attributes with an expression is invalid. Use property bindings \(e.g. \[@prop\]="exp"\) or use an attribute without a value \(e.g. @prop\) instead. \("<div \[ERROR ->\]@someAnimation="value2">"\): TestComp@0:5/);
|
/Assigning animation triggers via @prop="exp" attributes with an expression is invalid. Use property bindings \(e.g. \[@prop\]="exp"\) or use an attribute without a value \(e.g. @prop\) instead. \("<div \[ERROR ->\]@someAnimation="value2">"\): TestComp@0:5/);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -482,7 +478,6 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
|
|||||||
|
|
||||||
expect(() => { parse('<broken></broken>', [dirA]); })
|
expect(() => { parse('<broken></broken>', [dirA]); })
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Template parse errors:\nValue of the host property binding "class.foo" needs to be a string representing an expression but got "null" (object) ("[ERROR ->]<broken></broken>"): TestComp@0:0, Directive DirA`);
|
`Template parse errors:\nValue of the host property binding "class.foo" needs to be a string representing an expression but got "null" (object) ("[ERROR ->]<broken></broken>"): TestComp@0:0, Directive DirA`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -498,7 +493,6 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
|
|||||||
|
|
||||||
expect(() => { parse('<broken></broken>', [dirA]); })
|
expect(() => { parse('<broken></broken>', [dirA]); })
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
`Template parse errors:\nValue of the host listener "click" needs to be a string representing an expression but got "null" (object) ("[ERROR ->]<broken></broken>"): TestComp@0:0, Directive DirA`);
|
`Template parse errors:\nValue of the host listener "click" needs to be a string representing an expression but got "null" (object) ("[ERROR ->]<broken></broken>"): TestComp@0:0, Directive DirA`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -962,7 +956,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
|
|||||||
const dirB = createDir('[dirB]', {providers: [provider1]});
|
const dirB = createDir('[dirB]', {providers: [provider1]});
|
||||||
expect(() => parse('<div dirA dirB>', [dirA, dirB]))
|
expect(() => parse('<div dirA dirB>', [dirA, dirB]))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError, `Template parse errors:\n` +
|
`Template parse errors:\n` +
|
||||||
`Mixing multi and non multi provider is not possible for token service0 ("[ERROR ->]<div dirA dirB>"): TestComp@0:0`);
|
`Mixing multi and non multi provider is not possible for token service0 ("[ERROR ->]<div dirA dirB>"): TestComp@0:0`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1055,7 +1049,6 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
|
|||||||
const dirA = createDir('[dirA]', {deps: ['self:provider0']});
|
const dirA = createDir('[dirA]', {deps: ['self:provider0']});
|
||||||
expect(() => parse('<div dirA></div>', [dirA]))
|
expect(() => parse('<div dirA></div>', [dirA]))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
'Template parse errors:\nNo provider for provider0 ("[ERROR ->]<div dirA></div>"): TestComp@0:0');
|
'Template parse errors:\nNo provider for provider0 ("[ERROR ->]<div dirA></div>"): TestComp@0:0');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1070,7 +1063,6 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
|
|||||||
const dirA = createDir('[dirA]', {deps: ['host:provider0']});
|
const dirA = createDir('[dirA]', {deps: ['host:provider0']});
|
||||||
expect(() => parse('<div dirA></div>', [dirA]))
|
expect(() => parse('<div dirA></div>', [dirA]))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError,
|
|
||||||
'Template parse errors:\nNo provider for provider0 ("[ERROR ->]<div dirA></div>"): TestComp@0:0');
|
'Template parse errors:\nNo provider for provider0 ("[ERROR ->]<div dirA></div>"): TestComp@0:0');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1122,26 +1114,23 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should report references with values that dont match a directive as errors', () => {
|
it('should report references with values that dont match a directive as errors', () => {
|
||||||
expect(() => parse('<div #a="dirA"></div>', []))
|
expect(() => parse('<div #a="dirA"></div>', [])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
There is no directive with "exportAs" set to "dirA" ("<div [ERROR ->]#a="dirA"></div>"): TestComp@0:5`);
|
There is no directive with "exportAs" set to "dirA" ("<div [ERROR ->]#a="dirA"></div>"): TestComp@0:5`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report invalid reference names', () => {
|
it('should report invalid reference names', () => {
|
||||||
expect(() => parse('<div #a-b></div>', []))
|
expect(() => parse('<div #a-b></div>', [])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
"-" is not allowed in reference names ("<div [ERROR ->]#a-b></div>"): TestComp@0:5`);
|
"-" is not allowed in reference names ("<div [ERROR ->]#a-b></div>"): TestComp@0:5`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report variables as errors', () => {
|
it('should report variables as errors', () => {
|
||||||
expect(() => parse('<div let-a></div>', []))
|
expect(() => parse('<div let-a></div>', [])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
"let-" is only supported on template elements. ("<div [ERROR ->]let-a></div>"): TestComp@0:5`);
|
"let-" is only supported on template elements. ("<div [ERROR ->]let-a></div>"): TestComp@0:5`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report duplicate reference names', () => {
|
it('should report duplicate reference names', () => {
|
||||||
expect(() => parse('<div #a></div><div #a></div>', []))
|
expect(() => parse('<div #a></div><div #a></div>', []))
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
.toThrowError(`Template parse errors:
|
||||||
Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>"): TestComp@0:19`);
|
Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>"): TestComp@0:19`);
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -1513,7 +1502,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
|
|||||||
it('should report when ng-content has non WS content', () => {
|
it('should report when ng-content has non WS content', () => {
|
||||||
expect(() => parse('<ng-content>content</ng-content>', []))
|
expect(() => parse('<ng-content>content</ng-content>', []))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError, `Template parse errors:\n` +
|
`Template parse errors:\n` +
|
||||||
`<ng-content> element cannot have content. ("[ERROR ->]<ng-content>content</ng-content>"): TestComp@0:0`);
|
`<ng-content> element cannot have content. ("[ERROR ->]<ng-content>content</ng-content>"): TestComp@0:0`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1524,20 +1513,18 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
|
|||||||
() => { expect(() => parse('<template template="ngIf">', [])).not.toThrowError(); });
|
() => { expect(() => parse('<template template="ngIf">', [])).not.toThrowError(); });
|
||||||
|
|
||||||
it('should report when mutliple *attrs are used on the same element', () => {
|
it('should report when mutliple *attrs are used on the same element', () => {
|
||||||
expect(() => parse('<div *ngIf *ngFor>', []))
|
expect(() => parse('<div *ngIf *ngFor>', [])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with * ("<div *ngIf [ERROR ->]*ngFor>"): TestComp@0:11`);
|
Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with * ("<div *ngIf [ERROR ->]*ngFor>"): TestComp@0:11`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report when mix of template and *attrs are used on the same element', () => {
|
it('should report when mix of template and *attrs are used on the same element', () => {
|
||||||
expect(() => parse('<span template="ngIf" *ngFor>', []))
|
expect(() => parse('<span template="ngIf" *ngFor>', []))
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
.toThrowError(`Template parse errors:
|
||||||
Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with * ("<span template="ngIf" [ERROR ->]*ngFor>"): TestComp@0:22`);
|
Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with * ("<span template="ngIf" [ERROR ->]*ngFor>"): TestComp@0:22`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report invalid property names', () => {
|
it('should report invalid property names', () => {
|
||||||
expect(() => parse('<div [invalidProp]></div>', []))
|
expect(() => parse('<div [invalidProp]></div>', [])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("<div [ERROR ->][invalidProp]></div>"): TestComp@0:5`);
|
Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("<div [ERROR ->][invalidProp]></div>"): TestComp@0:5`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1550,13 +1537,12 @@ Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("<div [ER
|
|||||||
host: {'[invalidProp]': 'someProp'}
|
host: {'[invalidProp]': 'someProp'}
|
||||||
})
|
})
|
||||||
.toSummary();
|
.toSummary();
|
||||||
expect(() => parse('<div></div>', [dirA])).toThrowError(SyntaxError, `Template parse errors:
|
expect(() => parse('<div></div>', [dirA])).toThrowError(`Template parse errors:
|
||||||
Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("[ERROR ->]<div></div>"): TestComp@0:0, Directive DirA`);
|
Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("[ERROR ->]<div></div>"): TestComp@0:0, Directive DirA`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report errors in expressions', () => {
|
it('should report errors in expressions', () => {
|
||||||
expect(() => parse('<div [prop]="a b"></div>', []))
|
expect(() => parse('<div [prop]="a b"></div>', [])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [ERROR ->][prop]="a b"></div>"): TestComp@0:5`);
|
Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [ERROR ->][prop]="a b"></div>"): TestComp@0:5`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1594,7 +1580,7 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [
|
|||||||
.toSummary();
|
.toSummary();
|
||||||
expect(() => parse('<div>', [dirB, dirA]))
|
expect(() => parse('<div>', [dirB, dirA]))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
SyntaxError, `Template parse errors:\n` +
|
`Template parse errors:\n` +
|
||||||
`More than one component matched on this element.\n` +
|
`More than one component matched on this element.\n` +
|
||||||
`Make sure that only one component's selector can match a given element.\n` +
|
`Make sure that only one component's selector can match a given element.\n` +
|
||||||
`Conflicting components: DirB,DirA ("[ERROR ->]<div>"): TestComp@0:0`);
|
`Conflicting components: DirB,DirA ("[ERROR ->]<div>"): TestComp@0:0`);
|
||||||
@ -1612,7 +1598,7 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [
|
|||||||
})
|
})
|
||||||
.toSummary();
|
.toSummary();
|
||||||
expect(() => parse('<template [a]="b" (e)="f"></template>', [dirA]))
|
expect(() => parse('<template [a]="b" (e)="f"></template>', [dirA]))
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
.toThrowError(`Template parse errors:
|
||||||
Event binding e not emitted by any directive on an embedded template. Make sure that the event name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("<template [a]="b" [ERROR ->](e)="f"></template>"): TestComp@0:18
|
Event binding e not emitted by any directive on an embedded template. Make sure that the event name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("<template [a]="b" [ERROR ->](e)="f"></template>"): TestComp@0:18
|
||||||
Components on an embedded template: DirA ("[ERROR ->]<template [a]="b" (e)="f"></template>"): TestComp@0:0
|
Components on an embedded template: DirA ("[ERROR ->]<template [a]="b" (e)="f"></template>"): TestComp@0:0
|
||||||
Property binding a not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("[ERROR ->]<template [a]="b" (e)="f"></template>"): TestComp@0:0`);
|
Property binding a not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("[ERROR ->]<template [a]="b" (e)="f"></template>"): TestComp@0:0`);
|
||||||
@ -1628,8 +1614,7 @@ Property binding a not used by any directive on an embedded template. Make sure
|
|||||||
template: new CompileTemplateMetadata({ngContentSelectors: []})
|
template: new CompileTemplateMetadata({ngContentSelectors: []})
|
||||||
})
|
})
|
||||||
.toSummary();
|
.toSummary();
|
||||||
expect(() => parse('<div *a="b"></div>', [dirA]))
|
expect(() => parse('<div *a="b"></div>', [dirA])).toThrowError(`Template parse errors:
|
||||||
.toThrowError(SyntaxError, `Template parse errors:
|
|
||||||
Components on an embedded template: DirA ("[ERROR ->]<div *a="b"></div>"): TestComp@0:0
|
Components on an embedded template: DirA ("[ERROR ->]<div *a="b"></div>"): TestComp@0:0
|
||||||
Property binding a not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("[ERROR ->]<div *a="b"></div>"): TestComp@0:0`);
|
Property binding a not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations". ("[ERROR ->]<div *a="b"></div>"): TestComp@0:0`);
|
||||||
});
|
});
|
||||||
@ -1889,7 +1874,7 @@ Property binding a not used by any directive on an embedded template. Make sure
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should report pipes as error that have not been defined as dependencies', () => {
|
it('should report pipes as error that have not been defined as dependencies', () => {
|
||||||
expect(() => parse('{{a | test}}', [])).toThrowError(SyntaxError, `Template parse errors:
|
expect(() => parse('{{a | test}}', [])).toThrowError(`Template parse errors:
|
||||||
The pipe 'test' could not be found ("{{[ERROR ->]a | test}}"): TestComp@0:2`);
|
The pipe 'test' could not be found ("{{[ERROR ->]a | test}}"): TestComp@0:2`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import * as constants from './change_detection/constants';
|
|||||||
import * as console from './console';
|
import * as console from './console';
|
||||||
import * as debug from './debug/debug_renderer';
|
import * as debug from './debug/debug_renderer';
|
||||||
import * as reflective_provider from './di/reflective_provider';
|
import * as reflective_provider from './di/reflective_provider';
|
||||||
import {ComponentStillLoadingError} from './linker/compiler';
|
import {ERROR_COMPONENT_TYPE} from './errors';
|
||||||
import * as component_factory from './linker/component_factory';
|
import * as component_factory from './linker/component_factory';
|
||||||
import * as component_factory_resolver from './linker/component_factory_resolver';
|
import * as component_factory_resolver from './linker/component_factory_resolver';
|
||||||
import * as debug_context from './linker/debug_context';
|
import * as debug_context from './linker/debug_context';
|
||||||
@ -104,12 +104,11 @@ export const __core_private__: {
|
|||||||
DEFAULT_STATE: typeof DEFAULT_STATE_,
|
DEFAULT_STATE: typeof DEFAULT_STATE_,
|
||||||
EMPTY_STATE: typeof EMPTY_STATE_,
|
EMPTY_STATE: typeof EMPTY_STATE_,
|
||||||
FILL_STYLE_FLAG: typeof FILL_STYLE_FLAG_,
|
FILL_STYLE_FLAG: typeof FILL_STYLE_FLAG_,
|
||||||
_ComponentStillLoadingError?: ComponentStillLoadingError,
|
|
||||||
ComponentStillLoadingError: typeof ComponentStillLoadingError,
|
|
||||||
isPromise: typeof isPromise,
|
isPromise: typeof isPromise,
|
||||||
isObservable: typeof isObservable,
|
isObservable: typeof isObservable,
|
||||||
AnimationTransition: typeof AnimationTransition
|
AnimationTransition: typeof AnimationTransition
|
||||||
view_utils: typeof view_utils,
|
view_utils: typeof view_utils,
|
||||||
|
ERROR_COMPONENT_TYPE: typeof ERROR_COMPONENT_TYPE,
|
||||||
} = {
|
} = {
|
||||||
isDefaultChangeDetectionStrategy: constants.isDefaultChangeDetectionStrategy,
|
isDefaultChangeDetectionStrategy: constants.isDefaultChangeDetectionStrategy,
|
||||||
ChangeDetectorStatus: constants.ChangeDetectorStatus,
|
ChangeDetectorStatus: constants.ChangeDetectorStatus,
|
||||||
@ -156,8 +155,8 @@ export const __core_private__: {
|
|||||||
DEFAULT_STATE: DEFAULT_STATE_,
|
DEFAULT_STATE: DEFAULT_STATE_,
|
||||||
EMPTY_STATE: EMPTY_STATE_,
|
EMPTY_STATE: EMPTY_STATE_,
|
||||||
FILL_STYLE_FLAG: FILL_STYLE_FLAG_,
|
FILL_STYLE_FLAG: FILL_STYLE_FLAG_,
|
||||||
ComponentStillLoadingError: ComponentStillLoadingError,
|
|
||||||
isPromise: isPromise,
|
isPromise: isPromise,
|
||||||
isObservable: isObservable,
|
isObservable: isObservable,
|
||||||
AnimationTransition: AnimationTransition
|
AnimationTransition: AnimationTransition,
|
||||||
|
ERROR_COMPONENT_TYPE: ERROR_COMPONENT_TYPE
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {BaseError, WrappedError} from '../facade/errors';
|
import {wrappedError} from '../error_handler';
|
||||||
|
import {ERROR_ORIGINAL_ERROR, getOriginalError} from '../errors';
|
||||||
import {stringify} from '../facade/lang';
|
import {stringify} from '../facade/lang';
|
||||||
import {Type} from '../type';
|
import {Type} from '../type';
|
||||||
|
|
||||||
@ -35,38 +36,31 @@ function constructResolvingPath(keys: any[]): string {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface InjectionError extends Error {
|
||||||
/**
|
|
||||||
* Base class for all errors arising from misconfigured providers.
|
|
||||||
* @stable
|
|
||||||
*/
|
|
||||||
export class AbstractProviderError extends BaseError {
|
|
||||||
/** @internal */
|
|
||||||
message: string;
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
keys: ReflectiveKey[];
|
keys: ReflectiveKey[];
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
injectors: ReflectiveInjector[];
|
injectors: ReflectiveInjector[];
|
||||||
|
constructResolvingMessage: (this: InjectionError) => string;
|
||||||
|
addKey(injector: ReflectiveInjector, key: ReflectiveKey): void;
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal */
|
function injectionError(
|
||||||
constructResolvingMessage: Function;
|
injector: ReflectiveInjector, key: ReflectiveKey,
|
||||||
|
constructResolvingMessage: (this: InjectionError) => string,
|
||||||
|
originalError?: Error): InjectionError {
|
||||||
|
const error = (originalError ? wrappedError('', originalError) : Error()) as InjectionError;
|
||||||
|
error.addKey = addKey;
|
||||||
|
error.keys = [key];
|
||||||
|
error.injectors = [injector];
|
||||||
|
error.constructResolvingMessage = constructResolvingMessage;
|
||||||
|
error.message = error.constructResolvingMessage();
|
||||||
|
(error as any)[ERROR_ORIGINAL_ERROR] = originalError;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
function addKey(this: InjectionError, injector: ReflectiveInjector, key: ReflectiveKey): void {
|
||||||
injector: ReflectiveInjector, key: ReflectiveKey, constructResolvingMessage: Function) {
|
|
||||||
super('DI Error');
|
|
||||||
this.keys = [key];
|
|
||||||
this.injectors = [injector];
|
|
||||||
this.constructResolvingMessage = constructResolvingMessage;
|
|
||||||
this.message = this.constructResolvingMessage(this.keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
addKey(injector: ReflectiveInjector, key: ReflectiveKey): void {
|
|
||||||
this.injectors.push(injector);
|
this.injectors.push(injector);
|
||||||
this.keys.push(key);
|
this.keys.push(key);
|
||||||
this.message = this.constructResolvingMessage(this.keys);
|
this.message = this.constructResolvingMessage();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,15 +76,12 @@ export class AbstractProviderError extends BaseError {
|
|||||||
*
|
*
|
||||||
* expect(() => Injector.resolveAndCreate([A])).toThrowError();
|
* expect(() => Injector.resolveAndCreate([A])).toThrowError();
|
||||||
* ```
|
* ```
|
||||||
* @stable
|
|
||||||
*/
|
*/
|
||||||
export class NoProviderError extends AbstractProviderError {
|
export function noProviderError(injector: ReflectiveInjector, key: ReflectiveKey): InjectionError {
|
||||||
constructor(injector: ReflectiveInjector, key: ReflectiveKey) {
|
return injectionError(injector, key, function(this: InjectionError) {
|
||||||
super(injector, key, function(keys: any[]) {
|
const first = stringify(this.keys[0].token);
|
||||||
const first = stringify(keys[0].token);
|
return `No provider for ${first}!${constructResolvingPath(this.keys)}`;
|
||||||
return `No provider for ${first}!${constructResolvingPath(keys)}`;
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,14 +99,12 @@ export class NoProviderError extends AbstractProviderError {
|
|||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Retrieving `A` or `B` throws a `CyclicDependencyError` as the graph above cannot be constructed.
|
* Retrieving `A` or `B` throws a `CyclicDependencyError` as the graph above cannot be constructed.
|
||||||
* @stable
|
|
||||||
*/
|
*/
|
||||||
export class CyclicDependencyError extends AbstractProviderError {
|
export function cyclicDependencyError(
|
||||||
constructor(injector: ReflectiveInjector, key: ReflectiveKey) {
|
injector: ReflectiveInjector, key: ReflectiveKey): InjectionError {
|
||||||
super(injector, key, function(keys: any[]) {
|
return injectionError(injector, key, function(this: InjectionError) {
|
||||||
return `Cannot instantiate cyclic dependency!${constructResolvingPath(keys)}`;
|
return `Cannot instantiate cyclic dependency!${constructResolvingPath(this.keys)}`;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,34 +132,14 @@ export class CyclicDependencyError extends AbstractProviderError {
|
|||||||
* expect(e.originalStack).toBeDefined();
|
* expect(e.originalStack).toBeDefined();
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
* @stable
|
|
||||||
*/
|
*/
|
||||||
export class InstantiationError extends WrappedError {
|
export function instantiationError(
|
||||||
/** @internal */
|
|
||||||
keys: ReflectiveKey[];
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
injectors: ReflectiveInjector[];
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
injector: ReflectiveInjector, originalException: any, originalStack: any,
|
injector: ReflectiveInjector, originalException: any, originalStack: any,
|
||||||
key: ReflectiveKey) {
|
key: ReflectiveKey): InjectionError {
|
||||||
super('DI Error', originalException);
|
return injectionError(injector, key, function(this: InjectionError) {
|
||||||
this.keys = [key];
|
|
||||||
this.injectors = [injector];
|
|
||||||
}
|
|
||||||
|
|
||||||
addKey(injector: ReflectiveInjector, key: ReflectiveKey): void {
|
|
||||||
this.injectors.push(injector);
|
|
||||||
this.keys.push(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
get message(): string {
|
|
||||||
const first = stringify(this.keys[0].token);
|
const first = stringify(this.keys[0].token);
|
||||||
return `${this.originalError.message}: Error during instantiation of ${first}!${constructResolvingPath(this.keys)}.`;
|
return `${getOriginalError(this).message}: Error during instantiation of ${first}!${constructResolvingPath(this.keys)}.`;
|
||||||
}
|
}, originalException);
|
||||||
|
|
||||||
get causeKey(): ReflectiveKey { return this.keys[0]; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,12 +151,10 @@ export class InstantiationError extends WrappedError {
|
|||||||
* ```typescript
|
* ```typescript
|
||||||
* expect(() => Injector.resolveAndCreate(["not a type"])).toThrowError();
|
* expect(() => Injector.resolveAndCreate(["not a type"])).toThrowError();
|
||||||
* ```
|
* ```
|
||||||
* @stable
|
|
||||||
*/
|
*/
|
||||||
export class InvalidProviderError extends BaseError {
|
export function invalidProviderError(provider: any) {
|
||||||
constructor(provider: any) {
|
return Error(
|
||||||
super(`Invalid provider - only instances of Provider and Type are allowed, got: ${provider}`);
|
`Invalid provider - only instances of Provider and Type are allowed, got: ${provider}`);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -219,12 +186,7 @@ export class InvalidProviderError extends BaseError {
|
|||||||
* ```
|
* ```
|
||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
export class NoAnnotationError extends BaseError {
|
export function noAnnotationError(typeOrFunc: Type<any>| Function, params: any[][]): Error {
|
||||||
constructor(typeOrFunc: Type<any>|Function, params: any[][]) {
|
|
||||||
super(NoAnnotationError._genMessage(typeOrFunc, params));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static _genMessage(typeOrFunc: Type<any>|Function, params: any[][]) {
|
|
||||||
const signature: string[] = [];
|
const signature: string[] = [];
|
||||||
for (let i = 0, ii = params.length; i < ii; i++) {
|
for (let i = 0, ii = params.length; i < ii; i++) {
|
||||||
const parameter = params[i];
|
const parameter = params[i];
|
||||||
@ -234,11 +196,11 @@ export class NoAnnotationError extends BaseError {
|
|||||||
signature.push(parameter.map(stringify).join(' '));
|
signature.push(parameter.map(stringify).join(' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 'Cannot resolve all parameters for \'' + stringify(typeOrFunc) + '\'(' +
|
return Error(
|
||||||
|
'Cannot resolve all parameters for \'' + stringify(typeOrFunc) + '\'(' +
|
||||||
signature.join(', ') + '). ' +
|
signature.join(', ') + '). ' +
|
||||||
'Make sure that all the parameters are decorated with Inject or have valid type annotations and that \'' +
|
'Make sure that all the parameters are decorated with Inject or have valid type annotations and that \'' +
|
||||||
stringify(typeOrFunc) + '\' is decorated with Injectable.';
|
stringify(typeOrFunc) + '\' is decorated with Injectable.');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,8 +217,8 @@ export class NoAnnotationError extends BaseError {
|
|||||||
* ```
|
* ```
|
||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
export class OutOfBoundsError extends BaseError {
|
export function outOfBoundsError(index: number) {
|
||||||
constructor(index: number) { super(`Index ${index} is out-of-bounds.`); }
|
return Error(`Index ${index} is out-of-bounds.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add a working example after alpha38 is released
|
// TODO: add a working example after alpha38 is released
|
||||||
@ -272,10 +234,7 @@ export class OutOfBoundsError extends BaseError {
|
|||||||
* ])).toThrowError();
|
* ])).toThrowError();
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export class MixingMultiProvidersWithRegularProvidersError extends BaseError {
|
export function mixingMultiProvidersWithRegularProvidersError(
|
||||||
constructor(provider1: any, provider2: any) {
|
provider1: any, provider2: any): Error {
|
||||||
super(
|
return Error(`Cannot mix multi providers and regular providers, got: ${provider1} ${provider2}`);
|
||||||
'Cannot mix multi providers and regular providers, got: ' + provider1.toString() + ' ' +
|
|
||||||
provider2.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
import {Injector, THROW_IF_NOT_FOUND} from './injector';
|
import {Injector, THROW_IF_NOT_FOUND} from './injector';
|
||||||
import {Self, SkipSelf} from './metadata';
|
import {Self, SkipSelf} from './metadata';
|
||||||
import {Provider} from './provider';
|
import {Provider} from './provider';
|
||||||
import {AbstractProviderError, CyclicDependencyError, InstantiationError, NoProviderError, OutOfBoundsError} from './reflective_errors';
|
import {cyclicDependencyError, instantiationError, noProviderError, outOfBoundsError} from './reflective_errors';
|
||||||
import {ReflectiveKey} from './reflective_key';
|
import {ReflectiveKey} from './reflective_key';
|
||||||
import {ReflectiveDependency, ResolvedReflectiveFactory, ResolvedReflectiveProvider, resolveReflectiveProviders} from './reflective_provider';
|
import {ReflectiveDependency, ResolvedReflectiveFactory, ResolvedReflectiveProvider, resolveReflectiveProviders} from './reflective_provider';
|
||||||
|
|
||||||
@ -331,7 +331,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
|
|||||||
|
|
||||||
getProviderAtIndex(index: number): ResolvedReflectiveProvider {
|
getProviderAtIndex(index: number): ResolvedReflectiveProvider {
|
||||||
if (index < 0 || index >= this._providers.length) {
|
if (index < 0 || index >= this._providers.length) {
|
||||||
throw new OutOfBoundsError(index);
|
throw outOfBoundsError(index);
|
||||||
}
|
}
|
||||||
return this._providers[index];
|
return this._providers[index];
|
||||||
}
|
}
|
||||||
@ -339,7 +339,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
_new(provider: ResolvedReflectiveProvider): any {
|
_new(provider: ResolvedReflectiveProvider): any {
|
||||||
if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
|
if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
|
||||||
throw new CyclicDependencyError(this, provider.key);
|
throw cyclicDependencyError(this, provider.key);
|
||||||
}
|
}
|
||||||
return this._instantiateProvider(provider);
|
return this._instantiateProvider(provider);
|
||||||
}
|
}
|
||||||
@ -368,7 +368,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
|
|||||||
deps =
|
deps =
|
||||||
ResolvedReflectiveFactory.dependencies.map(dep => this._getByReflectiveDependency(dep));
|
ResolvedReflectiveFactory.dependencies.map(dep => this._getByReflectiveDependency(dep));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof AbstractProviderError || e instanceof InstantiationError) {
|
if (e.addKey) {
|
||||||
e.addKey(this, provider.key);
|
e.addKey(this, provider.key);
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@ -378,7 +378,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
|
|||||||
try {
|
try {
|
||||||
obj = factory(...deps);
|
obj = factory(...deps);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new InstantiationError(this, e, e.stack, provider.key);
|
throw instantiationError(this, e, e.stack, provider.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
@ -420,7 +420,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
|
|||||||
if (notFoundValue !== THROW_IF_NOT_FOUND) {
|
if (notFoundValue !== THROW_IF_NOT_FOUND) {
|
||||||
return notFoundValue;
|
return notFoundValue;
|
||||||
} else {
|
} else {
|
||||||
throw new NoProviderError(this, key);
|
throw noProviderError(this, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import {Type} from '../type';
|
|||||||
import {resolveForwardRef} from './forward_ref';
|
import {resolveForwardRef} from './forward_ref';
|
||||||
import {Host, Inject, Optional, Self, SkipSelf} from './metadata';
|
import {Host, Inject, Optional, Self, SkipSelf} from './metadata';
|
||||||
import {ClassProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ValueProvider} from './provider';
|
import {ClassProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ValueProvider} from './provider';
|
||||||
import {InvalidProviderError, MixingMultiProvidersWithRegularProvidersError, NoAnnotationError} from './reflective_errors';
|
import {invalidProviderError, mixingMultiProvidersWithRegularProvidersError, noAnnotationError} from './reflective_errors';
|
||||||
import {ReflectiveKey} from './reflective_key';
|
import {ReflectiveKey} from './reflective_key';
|
||||||
|
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ export function mergeResolvedReflectiveProviders(
|
|||||||
const existing = normalizedProvidersMap.get(provider.key.id);
|
const existing = normalizedProvidersMap.get(provider.key.id);
|
||||||
if (existing) {
|
if (existing) {
|
||||||
if (provider.multiProvider !== existing.multiProvider) {
|
if (provider.multiProvider !== existing.multiProvider) {
|
||||||
throw new MixingMultiProvidersWithRegularProvidersError(existing, provider);
|
throw mixingMultiProvidersWithRegularProvidersError(existing, provider);
|
||||||
}
|
}
|
||||||
if (provider.multiProvider) {
|
if (provider.multiProvider) {
|
||||||
for (let j = 0; j < provider.resolvedFactories.length; j++) {
|
for (let j = 0; j < provider.resolvedFactories.length; j++) {
|
||||||
@ -189,7 +189,7 @@ function _normalizeProviders(providers: Provider[], res: Provider[]): Provider[]
|
|||||||
_normalizeProviders(b, res);
|
_normalizeProviders(b, res);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidProviderError(b);
|
throw invalidProviderError(b);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ function _dependenciesFor(typeOrFunc: any): ReflectiveDependency[] {
|
|||||||
|
|
||||||
if (!params) return [];
|
if (!params) return [];
|
||||||
if (params.some(p => p == null)) {
|
if (params.some(p => p == null)) {
|
||||||
throw new NoAnnotationError(typeOrFunc, params);
|
throw noAnnotationError(typeOrFunc, params);
|
||||||
}
|
}
|
||||||
return params.map(p => _extractToken(typeOrFunc, p, params));
|
return params.map(p => _extractToken(typeOrFunc, p, params));
|
||||||
}
|
}
|
||||||
@ -253,7 +253,7 @@ function _extractToken(
|
|||||||
if (token != null) {
|
if (token != null) {
|
||||||
return _createDependency(token, optional, visibility);
|
return _createDependency(token, optional, visibility);
|
||||||
} else {
|
} else {
|
||||||
throw new NoAnnotationError(typeOrFunc, params);
|
throw noAnnotationError(typeOrFunc, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {WrappedError} from './facade/errors';
|
import {ERROR_ORIGINAL_ERROR, getDebugContext, getOriginalError} from './errors';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @whatItDoes Provides a hook for centralized exception handling.
|
* @whatItDoes Provides a hook for centralized exception handling.
|
||||||
@ -48,12 +49,13 @@ export class ErrorHandler {
|
|||||||
constructor(rethrowError: boolean = true) { this.rethrowError = rethrowError; }
|
constructor(rethrowError: boolean = true) { this.rethrowError = rethrowError; }
|
||||||
|
|
||||||
handleError(error: any): void {
|
handleError(error: any): void {
|
||||||
|
this._console.error(`EXCEPTION: ${this._extractMessage(error)}`);
|
||||||
|
|
||||||
|
if (error instanceof Error) {
|
||||||
const originalError = this._findOriginalError(error);
|
const originalError = this._findOriginalError(error);
|
||||||
const originalStack = this._findOriginalStack(error);
|
const originalStack = this._findOriginalStack(error);
|
||||||
const context = this._findContext(error);
|
const context = this._findContext(error);
|
||||||
|
|
||||||
this._console.error(`EXCEPTION: ${this._extractMessage(error)}`);
|
|
||||||
|
|
||||||
if (originalError) {
|
if (originalError) {
|
||||||
this._console.error(`ORIGINAL EXCEPTION: ${this._extractMessage(originalError)}`);
|
this._console.error(`ORIGINAL EXCEPTION: ${this._extractMessage(originalError)}`);
|
||||||
}
|
}
|
||||||
@ -67,6 +69,7 @@ export class ErrorHandler {
|
|||||||
this._console.error('ERROR CONTEXT:');
|
this._console.error('ERROR CONTEXT:');
|
||||||
this._console.error(context);
|
this._console.error(context);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We rethrow exceptions, so operations like 'bootstrap' will result in an error
|
// We rethrow exceptions, so operations like 'bootstrap' will result in an error
|
||||||
// when an error happens. If we do not rethrow, bootstrap will always succeed.
|
// when an error happens. If we do not rethrow, bootstrap will always succeed.
|
||||||
@ -81,31 +84,29 @@ export class ErrorHandler {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
_findContext(error: any): any {
|
_findContext(error: any): any {
|
||||||
if (error) {
|
if (error) {
|
||||||
return error.context ? error.context :
|
return getDebugContext(error) ? getDebugContext(error) :
|
||||||
this._findContext((error as WrappedError).originalError);
|
this._findContext(getOriginalError(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_findOriginalError(error: any): any {
|
_findOriginalError(error: Error): any {
|
||||||
let e = (error as WrappedError).originalError;
|
let e = getOriginalError(error);
|
||||||
while (e && (e as WrappedError).originalError) {
|
while (e && getOriginalError(e)) {
|
||||||
e = (e as WrappedError).originalError;
|
e = getOriginalError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_findOriginalStack(error: any): string {
|
_findOriginalStack(error: Error): string {
|
||||||
if (!(error instanceof Error)) return null;
|
|
||||||
|
|
||||||
let e: any = error;
|
let e: any = error;
|
||||||
let stack: string = e.stack;
|
let stack: string = e.stack;
|
||||||
while (e instanceof Error && (e as WrappedError).originalError) {
|
while (e instanceof Error && getOriginalError(e)) {
|
||||||
e = (e as WrappedError).originalError;
|
e = getOriginalError(e);
|
||||||
if (e instanceof Error && e.stack) {
|
if (e instanceof Error && e.stack) {
|
||||||
stack = e.stack;
|
stack = e.stack;
|
||||||
}
|
}
|
||||||
@ -114,3 +115,11 @@ export class ErrorHandler {
|
|||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function wrappedError(message: string, originalError: any): Error {
|
||||||
|
const msg =
|
||||||
|
`${message} caused by: ${originalError instanceof Error ? originalError.message: originalError }`;
|
||||||
|
const error = Error(msg);
|
||||||
|
(error as any)[ERROR_ORIGINAL_ERROR] = originalError;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
28
modules/@angular/core/src/errors.ts
Normal file
28
modules/@angular/core/src/errors.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Type} from './type';
|
||||||
|
import {DebugContext} from './view';
|
||||||
|
|
||||||
|
export const ERROR_TYPE = 'ngType';
|
||||||
|
export const ERROR_COMPONENT_TYPE = 'ngComponentType';
|
||||||
|
export const ERROR_DEBUG_CONTEXT = 'ngDebugContext';
|
||||||
|
export const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
|
||||||
|
|
||||||
|
|
||||||
|
export function getType(error: Error): Function {
|
||||||
|
return (error as any)[ERROR_TYPE];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDebugContext(error: Error): DebugContext {
|
||||||
|
return (error as any)[ERROR_DEBUG_CONTEXT];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getOriginalError(error: Error): Error {
|
||||||
|
return (error as any)[ERROR_ORIGINAL_ERROR];
|
||||||
|
}
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Injectable, InjectionToken} from '../di';
|
import {Injectable, InjectionToken} from '../di';
|
||||||
import {BaseError} from '../facade/errors';
|
|
||||||
import {stringify} from '../facade/lang';
|
import {stringify} from '../facade/lang';
|
||||||
import {MissingTranslationStrategy} from '../i18n/tokens';
|
import {MissingTranslationStrategy} from '../i18n/tokens';
|
||||||
import {ViewEncapsulation} from '../metadata';
|
import {ViewEncapsulation} from '../metadata';
|
||||||
@ -16,19 +15,6 @@ import {Type} from '../type';
|
|||||||
import {ComponentFactory} from './component_factory';
|
import {ComponentFactory} from './component_factory';
|
||||||
import {NgModuleFactory} from './ng_module_factory';
|
import {NgModuleFactory} from './ng_module_factory';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that a component is still being loaded in a synchronous compile.
|
|
||||||
*
|
|
||||||
* @stable
|
|
||||||
*/
|
|
||||||
export class ComponentStillLoadingError extends BaseError {
|
|
||||||
constructor(public compType: Type<any>) {
|
|
||||||
super(`Can't compile synchronously as ${stringify(compType)} is still being loaded!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combination of NgModuleFactory and ComponentFactorys.
|
* Combination of NgModuleFactory and ComponentFactorys.
|
||||||
*
|
*
|
||||||
@ -59,8 +45,7 @@ function _throwError() {
|
|||||||
export class Compiler {
|
export class Compiler {
|
||||||
/**
|
/**
|
||||||
* Compiles the given NgModule and all of its components. All templates of the components listed
|
* Compiles the given NgModule and all of its components. All templates of the components listed
|
||||||
* in `entryComponents`
|
* in `entryComponents` have to be inlined.
|
||||||
* have to be inlined. Otherwise throws a {@link ComponentStillLoadingError}.
|
|
||||||
*/
|
*/
|
||||||
compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T> { throw _throwError(); }
|
compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T> { throw _throwError(); }
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {BaseError} from '../facade/errors';
|
|
||||||
import {stringify} from '../facade/lang';
|
import {stringify} from '../facade/lang';
|
||||||
import {Type} from '../type';
|
import {Type} from '../type';
|
||||||
|
|
||||||
@ -14,19 +13,23 @@ import {ComponentFactory} from './component_factory';
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
export function noComponentFactoryError(component: Function) {
|
||||||
* @stable
|
const error = Error(
|
||||||
*/
|
|
||||||
export class NoComponentFactoryError extends BaseError {
|
|
||||||
constructor(public component: Function) {
|
|
||||||
super(
|
|
||||||
`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`);
|
`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`);
|
||||||
}
|
(error as any)[ERROR_COMPONENT] = component;
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ERROR_COMPONENT = 'ngComponent';
|
||||||
|
|
||||||
|
export function getComponent(error: Error): Type<any> {
|
||||||
|
return (error as any)[ERROR_COMPONENT];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class _NullComponentFactoryResolver implements ComponentFactoryResolver {
|
class _NullComponentFactoryResolver implements ComponentFactoryResolver {
|
||||||
resolveComponentFactory<T>(component: {new (...args: any[]): T}): ComponentFactory<T> {
|
resolveComponentFactory<T>(component: {new (...args: any[]): T}): ComponentFactory<T> {
|
||||||
throw new NoComponentFactoryError(component);
|
throw noComponentFactoryError(component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {BaseError, WrappedError} from '../facade/errors';
|
import {wrappedError} from '../error_handler';
|
||||||
|
import {ERROR_DEBUG_CONTEXT, ERROR_TYPE} from '../errors';
|
||||||
import {DebugContext} from './debug_context';
|
import {DebugContext} from './debug_context';
|
||||||
|
|
||||||
|
|
||||||
@ -41,10 +41,9 @@ import {DebugContext} from './debug_context';
|
|||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
* @stable
|
|
||||||
*/
|
*/
|
||||||
export class ExpressionChangedAfterItHasBeenCheckedError extends BaseError {
|
export function expressionChangedAfterItHasBeenCheckedError(
|
||||||
constructor(oldValue: any, currValue: any, isFirstCheck: boolean) {
|
oldValue: any, currValue: any, isFirstCheck: boolean) {
|
||||||
let msg =
|
let msg =
|
||||||
`Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
|
`Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
|
||||||
if (isFirstCheck) {
|
if (isFirstCheck) {
|
||||||
@ -52,8 +51,9 @@ export class ExpressionChangedAfterItHasBeenCheckedError extends BaseError {
|
|||||||
` It seems like the view has been created after its parent and its children have been dirty checked.` +
|
` It seems like the view has been created after its parent and its children have been dirty checked.` +
|
||||||
` Has it been created in a change detection hook ?`;
|
` Has it been created in a change detection hook ?`;
|
||||||
}
|
}
|
||||||
super(msg);
|
const error = Error(msg);
|
||||||
}
|
(error as any)[ERROR_TYPE] = expressionChangedAfterItHasBeenCheckedError;
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,28 +61,21 @@ export class ExpressionChangedAfterItHasBeenCheckedError extends BaseError {
|
|||||||
*
|
*
|
||||||
* This error wraps the original exception to attach additional contextual information that can
|
* This error wraps the original exception to attach additional contextual information that can
|
||||||
* be useful for debugging.
|
* be useful for debugging.
|
||||||
* @stable
|
|
||||||
*/
|
*/
|
||||||
export class ViewWrappedError extends WrappedError {
|
export function viewWrappedError(originalError: any, context: DebugContext): Error {
|
||||||
/**
|
const error = wrappedError(`Error in ${context.source}`, originalError);
|
||||||
* DebugContext
|
(error as any)[ERROR_DEBUG_CONTEXT] = context;
|
||||||
*/
|
(error as any)[ERROR_TYPE] = viewWrappedError;
|
||||||
context: DebugContext;
|
return error;
|
||||||
|
|
||||||
constructor(originalError: any, context: DebugContext) {
|
|
||||||
super(`Error in ${context.source}`, originalError);
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown when a destroyed view is used.
|
* Thrown when a destroyed view is used.
|
||||||
*
|
*
|
||||||
* This error indicates a bug in the framework.
|
* This error indicates a bug in the framework.
|
||||||
*
|
*
|
||||||
* This is an internal Angular error.
|
* This is an internal Angular error.
|
||||||
* @stable
|
*/
|
||||||
*/
|
export function viewDestroyedError(details: string) {
|
||||||
export class ViewDestroyedError extends BaseError {
|
return Error(`Attempt to use a destroyed view: ${details}`);
|
||||||
constructor(details: string) { super(`Attempt to use a destroyed view: ${details}`); }
|
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,11 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import {ApplicationRef} from '../application_ref';
|
import {ApplicationRef} from '../application_ref';
|
||||||
import {ChangeDetectorRef, ChangeDetectorStatus} from '../change_detection/change_detection';
|
import {ChangeDetectorRef, ChangeDetectorStatus} from '../change_detection/change_detection';
|
||||||
import {Injector, THROW_IF_NOT_FOUND} from '../di/injector';
|
import {Injector, THROW_IF_NOT_FOUND} from '../di/injector';
|
||||||
|
import {getType} from '../errors';
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
import {WtfScopeFn, wtfCreateScope, wtfLeave} from '../profile/profile';
|
import {WtfScopeFn, wtfCreateScope, wtfLeave} from '../profile/profile';
|
||||||
import {DirectRenderer, RenderComponentType, Renderer} from '../render/api';
|
import {DirectRenderer, RenderComponentType, Renderer} from '../render/api';
|
||||||
@ -17,7 +19,7 @@ import {AnimationViewContext} from './animation_view_context';
|
|||||||
import {ComponentRef} from './component_factory';
|
import {ComponentRef} from './component_factory';
|
||||||
import {DebugContext, StaticNodeDebugInfo} from './debug_context';
|
import {DebugContext, StaticNodeDebugInfo} from './debug_context';
|
||||||
import {ElementInjector} from './element_injector';
|
import {ElementInjector} from './element_injector';
|
||||||
import {ExpressionChangedAfterItHasBeenCheckedError, ViewDestroyedError, ViewWrappedError} from './errors';
|
import {expressionChangedAfterItHasBeenCheckedError, viewDestroyedError, viewWrappedError} from './errors';
|
||||||
import {ViewContainer} from './view_container';
|
import {ViewContainer} from './view_container';
|
||||||
import {ViewRef_} from './view_ref';
|
import {ViewRef_} from './view_ref';
|
||||||
import {ViewType} from './view_type';
|
import {ViewType} from './view_type';
|
||||||
@ -360,7 +362,7 @@ export abstract class AppView<T> {
|
|||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
throwDestroyedError(details: string): void { throw new ViewDestroyedError(details); }
|
throwDestroyedError(details: string): void { throw viewDestroyedError(details); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DebugAppView<T> extends AppView<T> {
|
export class DebugAppView<T> extends AppView<T> {
|
||||||
@ -445,12 +447,12 @@ export class DebugAppView<T> extends AppView<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _rethrowWithContext(e: any) {
|
private _rethrowWithContext(e: any) {
|
||||||
if (!(e instanceof ViewWrappedError)) {
|
if (!(getType(e) == viewWrappedError)) {
|
||||||
if (!(e instanceof ExpressionChangedAfterItHasBeenCheckedError)) {
|
if (!(getType(e) == expressionChangedAfterItHasBeenCheckedError)) {
|
||||||
this.cdMode = ChangeDetectorStatus.Errored;
|
this.cdMode = ChangeDetectorStatus.Errored;
|
||||||
}
|
}
|
||||||
if (isPresent(this._currentDebugContext)) {
|
if (isPresent(this._currentDebugContext)) {
|
||||||
throw new ViewWrappedError(e, this._currentDebugContext);
|
throw viewWrappedError(e, this._currentDebugContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import {Type} from '../type';
|
|||||||
import {VERSION} from '../version';
|
import {VERSION} from '../version';
|
||||||
|
|
||||||
import {ComponentFactory} from './component_factory';
|
import {ComponentFactory} from './component_factory';
|
||||||
import {ExpressionChangedAfterItHasBeenCheckedError} from './errors';
|
import {expressionChangedAfterItHasBeenCheckedError} from './errors';
|
||||||
import {AppView} from './view';
|
import {AppView} from './view';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -104,7 +104,7 @@ export function checkBinding(
|
|||||||
const isFirstCheck = view.numberOfChecks === 0;
|
const isFirstCheck = view.numberOfChecks === 0;
|
||||||
if (view.throwOnChange) {
|
if (view.throwOnChange) {
|
||||||
if (isFirstCheck || !devModeEqual(oldValue, newValue)) {
|
if (isFirstCheck || !devModeEqual(oldValue, newValue)) {
|
||||||
throw new ExpressionChangedAfterItHasBeenCheckedError(oldValue, newValue, isFirstCheck);
|
throw expressionChangedAfterItHasBeenCheckedError(oldValue, newValue, isFirstCheck);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -6,12 +6,11 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {BaseError, WrappedError} from '../facade/errors';
|
import {ERROR_DEBUG_CONTEXT, ERROR_ORIGINAL_ERROR, getDebugContext} from '../errors';
|
||||||
|
|
||||||
import {DebugContext, EntryAction, ViewState} from './types';
|
import {DebugContext, EntryAction, ViewState} from './types';
|
||||||
|
|
||||||
export function expressionChangedAfterItHasBeenCheckedError(
|
export function expressionChangedAfterItHasBeenCheckedError(
|
||||||
context: DebugContext, oldValue: any, currValue: any, isFirstCheck: boolean): ViewDebugError {
|
context: DebugContext, oldValue: any, currValue: any, isFirstCheck: boolean): Error {
|
||||||
let msg =
|
let msg =
|
||||||
`Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
|
`Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
|
||||||
if (isFirstCheck) {
|
if (isFirstCheck) {
|
||||||
@ -22,25 +21,22 @@ export function expressionChangedAfterItHasBeenCheckedError(
|
|||||||
return viewDebugError(msg, context);
|
return viewDebugError(msg, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function viewWrappedDebugError(originalError: any, context: DebugContext): WrappedError&
|
export function viewWrappedDebugError(originalError: any, context: DebugContext): Error {
|
||||||
ViewDebugError {
|
const err = viewDebugError(originalError.message, context);
|
||||||
const err = viewDebugError(originalError.message, context) as WrappedError & ViewDebugError;
|
(err as any)[ERROR_ORIGINAL_ERROR] = originalError;
|
||||||
err.originalError = originalError;
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ViewDebugError { context: DebugContext; }
|
export function viewDebugError(msg: string, context: DebugContext): Error {
|
||||||
|
const err = new Error(msg);
|
||||||
export function viewDebugError(msg: string, context: DebugContext): ViewDebugError {
|
(err as any)[ERROR_DEBUG_CONTEXT] = context;
|
||||||
const err = new Error(msg) as any;
|
|
||||||
err.context = context;
|
|
||||||
err.stack = context.source;
|
err.stack = context.source;
|
||||||
context.view.state |= ViewState.Errored;
|
context.view.state |= ViewState.Errored;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isViewDebugError(err: any): boolean {
|
export function isViewDebugError(err: Error): boolean {
|
||||||
return err.context;
|
return !!getDebugContext(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function viewDestroyedError(action: EntryAction): Error {
|
export function viewDestroyedError(action: EntryAction): Error {
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {isDevMode} from '../application_ref';
|
|
||||||
import {RenderComponentType, Renderer} from '../render/api';
|
import {RenderComponentType, Renderer} from '../render/api';
|
||||||
|
|
||||||
import {checkAndUpdateElementDynamic, checkAndUpdateElementInline, createElement} from './element';
|
import {checkAndUpdateElementDynamic, checkAndUpdateElementInline, createElement} from './element';
|
||||||
import {expressionChangedAfterItHasBeenCheckedError} from './errors';
|
import {expressionChangedAfterItHasBeenCheckedError} from './errors';
|
||||||
import {appendNgContent} from './ng_content';
|
import {appendNgContent} from './ng_content';
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import {Inject, Injectable, Injector, Optional, Provider, ReflectiveInjector, ReflectiveKey, Self, forwardRef} from '@angular/core';
|
import {Inject, Injectable, Injector, Optional, Provider, ReflectiveInjector, ReflectiveKey, Self, forwardRef} from '@angular/core';
|
||||||
import {ReflectiveInjector_} from '@angular/core/src/di/reflective_injector';
|
import {ReflectiveInjector_} from '@angular/core/src/di/reflective_injector';
|
||||||
import {ResolvedReflectiveProvider_} from '@angular/core/src/di/reflective_provider';
|
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 {expect} from '@angular/platform-browser/testing/matchers';
|
||||||
|
|
||||||
import {isPresent, stringify} from '../../src/facade/lang';
|
import {isPresent, stringify} from '../../src/facade/lang';
|
||||||
@ -293,8 +294,8 @@ export function main() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toContain(
|
expect(e.message).toContain(
|
||||||
`Error during instantiation of Engine! (${stringify(Car)} -> Engine)`);
|
`Error during instantiation of Engine! (${stringify(Car)} -> Engine)`);
|
||||||
expect(e.originalError instanceof Error).toBeTruthy();
|
expect(getOriginalError(e) instanceof Error).toBeTruthy();
|
||||||
expect(e.causeKey.token).toEqual(Engine);
|
expect(e.keys[0].token).toEqual(Engine);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6,22 +6,17 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* 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 {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 {
|
class MockConsole {
|
||||||
res: any[] = [];
|
res: any[] = [];
|
||||||
error(s: any): void { this.res.push(s); }
|
error(s: any): void { this.res.push(s); }
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CustomException {
|
|
||||||
context = 'some context';
|
|
||||||
toString(): string { return 'custom'; }
|
|
||||||
}
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
function errorToString(error: any) {
|
function errorToString(error: any) {
|
||||||
const logger = new MockConsole();
|
const logger = new MockConsole();
|
||||||
@ -58,12 +53,9 @@ export function main() {
|
|||||||
it('should print nested context', () => {
|
it('should print nested context', () => {
|
||||||
const cause = new Error('message!');
|
const cause = new Error('message!');
|
||||||
const stack = getStack(cause);
|
const stack = getStack(cause);
|
||||||
const context = {
|
const context = { source: 'context!', toString() { return 'Context'; } } as any;
|
||||||
source: 'context!',
|
const original = viewWrappedError(cause, context);
|
||||||
toString() { return 'Context'; }
|
const e = errorToString(wrappedError('message', original));
|
||||||
} as any as DebugContext;
|
|
||||||
const original = new ViewWrappedError(cause, context);
|
|
||||||
const e = errorToString(new WrappedError('message', original));
|
|
||||||
expect(e).toEqual(
|
expect(e).toEqual(
|
||||||
stack ? `EXCEPTION: message caused by: Error in context! caused by: message!
|
stack ? `EXCEPTION: message caused by: Error in context! caused by: message!
|
||||||
ORIGINAL EXCEPTION: message!
|
ORIGINAL EXCEPTION: message!
|
||||||
@ -81,15 +73,15 @@ Context`);
|
|||||||
describe('original exception', () => {
|
describe('original exception', () => {
|
||||||
it('should print original exception message if available (original is Error)', () => {
|
it('should print original exception message if available (original is Error)', () => {
|
||||||
const realOriginal = new Error('inner');
|
const realOriginal = new Error('inner');
|
||||||
const original = new WrappedError('wrapped', realOriginal);
|
const original = wrappedError('wrapped', realOriginal);
|
||||||
const e = errorToString(new WrappedError('wrappedwrapped', original));
|
const e = errorToString(wrappedError('wrappedwrapped', original));
|
||||||
expect(e).toContain('inner');
|
expect(e).toContain('inner');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should print original exception message if available (original is not Error)', () => {
|
it('should print original exception message if available (original is not Error)', () => {
|
||||||
const realOriginal = new _CustomException();
|
const realOriginal = new Error('custom');
|
||||||
const original = new WrappedError('wrapped', realOriginal);
|
const original = wrappedError('wrapped', realOriginal);
|
||||||
const e = errorToString(new WrappedError('wrappedwrapped', original));
|
const e = errorToString(wrappedError('wrappedwrapped', original));
|
||||||
expect(e).toContain('custom');
|
expect(e).toContain('custom');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -99,8 +91,8 @@ Context`);
|
|||||||
const realOriginal = new Error('inner');
|
const realOriginal = new Error('inner');
|
||||||
const stack = getStack(realOriginal);
|
const stack = getStack(realOriginal);
|
||||||
if (stack) {
|
if (stack) {
|
||||||
const original = new WrappedError('wrapped', realOriginal);
|
const original = wrappedError('wrapped', realOriginal);
|
||||||
const e = errorToString(new WrappedError('wrappedwrapped', original));
|
const e = errorToString(wrappedError('wrappedwrapped', original));
|
||||||
expect(e).toContain(stack);
|
expect(e).toContain(stack);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, ComponentFactoryResolver} from '@angular/core';
|
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 {TestBed} from '@angular/core/testing';
|
||||||
|
|
||||||
import {Console} from '../../src/console';
|
import {Console} from '../../src/console';
|
||||||
@ -77,7 +77,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
|||||||
const nestedChildComp: NestedChildComp = nestedChildCompEl.componentInstance;
|
const nestedChildComp: NestedChildComp = nestedChildCompEl.componentInstance;
|
||||||
expect(nestedChildComp.cfr.resolveComponentFactory(ChildComp).componentType).toBe(ChildComp);
|
expect(nestedChildComp.cfr.resolveComponentFactory(ChildComp).componentType).toBe(ChildComp);
|
||||||
expect(() => nestedChildComp.cfr.resolveComponentFactory(NestedChildComp))
|
expect(() => nestedChildComp.cfr.resolveComponentFactory(NestedChildComp))
|
||||||
.toThrow(new NoComponentFactoryError(NestedChildComp));
|
.toThrow(noComponentFactoryError(NestedChildComp));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import {CommonModule} from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
import {ComponentFactory, Host, Inject, Injectable, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, OnDestroy, ReflectiveInjector, SkipSelf} from '@angular/core';
|
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 {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 {ComponentFactoryResolver} from '@angular/core/src/linker/component_factory_resolver';
|
||||||
import {ElementRef} from '@angular/core/src/linker/element_ref';
|
import {ElementRef} from '@angular/core/src/linker/element_ref';
|
||||||
import {QueryList} from '@angular/core/src/linker/query_list';
|
import {QueryList} from '@angular/core/src/linker/query_list';
|
||||||
@ -1295,7 +1296,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
|||||||
TestBed.createComponent(MyComp);
|
TestBed.createComponent(MyComp);
|
||||||
throw 'Should throw';
|
throw 'Should throw';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const c = e.context;
|
const c = getDebugContext(e);
|
||||||
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
||||||
expect((<Injector>c.injector).get).toBeTruthy();
|
expect((<Injector>c.injector).get).toBeTruthy();
|
||||||
}
|
}
|
||||||
@ -1310,7 +1311,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
throw 'Should throw';
|
throw 'Should throw';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const c = e.context;
|
const c = getDebugContext(e);
|
||||||
expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('INPUT');
|
expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('INPUT');
|
||||||
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
||||||
expect((<Injector>c.injector).get).toBeTruthy();
|
expect((<Injector>c.injector).get).toBeTruthy();
|
||||||
@ -1330,7 +1331,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
throw 'Should throw';
|
throw 'Should throw';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const c = e.context;
|
const c = getDebugContext(e);
|
||||||
expect(c.renderNode).toBeTruthy();
|
expect(c.renderNode).toBeTruthy();
|
||||||
expect(c.source).toContain(':0:5');
|
expect(c.source).toContain(':0:5');
|
||||||
}
|
}
|
||||||
@ -1353,7 +1354,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
|||||||
try {
|
try {
|
||||||
tc.injector.get(DirectiveEmittingEvent).fireEvent('boom');
|
tc.injector.get(DirectiveEmittingEvent).fireEvent('boom');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const c = e.context;
|
const c = getDebugContext(e);
|
||||||
expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('SPAN');
|
expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('SPAN');
|
||||||
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
|
||||||
expect((<Injector>c.injector).get).toBeTruthy();
|
expect((<Injector>c.injector).get).toBeTruthy();
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core';
|
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 {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 {inject} from '@angular/core/testing';
|
||||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
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).toBeTruthy();
|
||||||
expect(err.message).toBe('Test');
|
expect(err.message).toBe('Test');
|
||||||
const debugCtx = <DebugContext>err.context;
|
const debugCtx = getDebugContext(err);
|
||||||
expect(debugCtx.view).toBe(view);
|
expect(debugCtx.view).toBe(view);
|
||||||
expect(debugCtx.nodeIndex).toBe(0);
|
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 {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 {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 {inject} from '@angular/core/testing';
|
||||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
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).toBeTruthy();
|
||||||
expect(err.message).toBe('Test');
|
expect(err.message).toBe('Test');
|
||||||
const debugCtx = <DebugContext>err.context;
|
const debugCtx = getDebugContext(err);
|
||||||
expect(debugCtx.view).toBeTruthy();
|
expect(debugCtx.view).toBeTruthy();
|
||||||
// errors should point to the already existing element
|
// errors should point to the already existing element
|
||||||
expect(debugCtx.nodeIndex).toBe(0);
|
expect(debugCtx.nodeIndex).toBe(0);
|
||||||
@ -447,7 +448,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
|||||||
err = e;
|
err = e;
|
||||||
}
|
}
|
||||||
expect(err).toBeTruthy();
|
expect(err).toBeTruthy();
|
||||||
const debugCtx = <DebugContext>err.context;
|
const debugCtx = getDebugContext(err);
|
||||||
expect(debugCtx.view).toBe(view);
|
expect(debugCtx.view).toBe(view);
|
||||||
// events are emitted with the index of the element, not the index of the provider.
|
// events are emitted with the index of the element, not the index of the provider.
|
||||||
expect(debugCtx.nodeIndex).toBe(0);
|
expect(debugCtx.nodeIndex).toBe(0);
|
||||||
@ -576,7 +577,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
|||||||
}
|
}
|
||||||
expect(err).toBeTruthy();
|
expect(err).toBeTruthy();
|
||||||
expect(err.message).toBe('Test');
|
expect(err.message).toBe('Test');
|
||||||
const debugCtx = <DebugContext>err.context;
|
const debugCtx = getDebugContext(err);
|
||||||
expect(debugCtx.view).toBe(view);
|
expect(debugCtx.view).toBe(view);
|
||||||
expect(debugCtx.nodeIndex).toBe(1);
|
expect(debugCtx.nodeIndex).toBe(1);
|
||||||
});
|
});
|
||||||
@ -599,7 +600,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) {
|
|||||||
}
|
}
|
||||||
expect(err).toBeTruthy();
|
expect(err).toBeTruthy();
|
||||||
expect(err.message).toBe('Test');
|
expect(err.message).toBe('Test');
|
||||||
const debugCtx = <DebugContext>err.context;
|
const debugCtx = getDebugContext(err);
|
||||||
expect(debugCtx.view).toBe(view);
|
expect(debugCtx.view).toBe(view);
|
||||||
expect(debugCtx.nodeIndex).toBe(1);
|
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 {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 {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 {inject} from '@angular/core/testing';
|
||||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||||
@ -395,7 +396,7 @@ export function main() {
|
|||||||
expect(err.message)
|
expect(err.message)
|
||||||
.toBe(
|
.toBe(
|
||||||
`Expression has changed after it was checked. Previous value: 'Query query1 not dirty'. Current value: 'Query query1 dirty'.`);
|
`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.view).toBe(view);
|
||||||
expect(debugCtx.nodeIndex).toBe(2);
|
expect(debugCtx.nodeIndex).toBe(2);
|
||||||
});
|
});
|
||||||
@ -421,7 +422,7 @@ export function main() {
|
|||||||
}
|
}
|
||||||
expect(err).toBeTruthy();
|
expect(err).toBeTruthy();
|
||||||
expect(err.message).toBe('Test');
|
expect(err.message).toBe('Test');
|
||||||
const debugCtx = <DebugContext>err.context;
|
const debugCtx = getDebugContext(err);
|
||||||
expect(debugCtx.view).toBe(view);
|
expect(debugCtx.view).toBe(view);
|
||||||
expect(debugCtx.nodeIndex).toBe(2);
|
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 {async, fakeAsync, flushMicrotasks} from '@angular/core/testing';
|
||||||
import {AsyncTestCompleter, Log, beforeEach, describe, expect, inject, it, xit} from '@angular/core/testing/testing_internal';
|
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 {browserDetection} from '@angular/platform-browser/testing/browser_util';
|
||||||
import {BaseError} from '../../src/facade/errors';
|
|
||||||
import {isPresent, scheduleMicroTask} from '../../src/facade/lang';
|
import {isPresent, scheduleMicroTask} from '../../src/facade/lang';
|
||||||
|
|
||||||
const needsLongerTimers = browserDetection.isSlow || browserDetection.isEdge;
|
const needsLongerTimers = browserDetection.isSlow || browserDetection.isEdge;
|
||||||
@ -94,7 +93,7 @@ export function main() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve(null);
|
resolve(null);
|
||||||
throw new BaseError('ccc');
|
throw new Error('ccc');
|
||||||
}, 0);
|
}, 0);
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
@ -117,7 +116,7 @@ export function main() {
|
|||||||
scheduleMicroTask(() => {
|
scheduleMicroTask(() => {
|
||||||
scheduleMicroTask(() => {
|
scheduleMicroTask(() => {
|
||||||
resolve(null);
|
resolve(null);
|
||||||
throw new BaseError('ddd');
|
throw new Error('ddd');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -152,7 +151,7 @@ export function main() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve(null);
|
resolve(null);
|
||||||
throw new BaseError('ccc');
|
throw new Error('ccc');
|
||||||
}, 0);
|
}, 0);
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
@ -719,7 +718,7 @@ function commonTests() {
|
|||||||
it('should call the on error callback when it is invoked via zone.runGuarded',
|
it('should call the on error callback when it is invoked via zone.runGuarded',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
macroTask(() => {
|
macroTask(() => {
|
||||||
const exception = new BaseError('sync');
|
const exception = new Error('sync');
|
||||||
|
|
||||||
_zone.runGuarded(() => { throw exception; });
|
_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',
|
it('should not call the on error callback but rethrow when it is invoked via zone.run',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
macroTask(() => {
|
macroTask(() => {
|
||||||
const exception = new BaseError('sync');
|
const exception = new Error('sync');
|
||||||
expect(() => _zone.run(() => { throw exception; })).toThrowError('sync');
|
expect(() => _zone.run(() => { throw exception; })).toThrowError('sync');
|
||||||
|
|
||||||
expect(_errors.length).toBe(0);
|
expect(_errors.length).toBe(0);
|
||||||
@ -742,7 +741,7 @@ function commonTests() {
|
|||||||
|
|
||||||
it('should call onError for errors from microtasks',
|
it('should call onError for errors from microtasks',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
const exception = new BaseError('async');
|
const exception = new Error('async');
|
||||||
|
|
||||||
macroTask(() => { _zone.run(() => { scheduleMicroTask(() => { throw exception; }); }); });
|
macroTask(() => { _zone.run(() => { scheduleMicroTask(() => { throw exception; }); }); });
|
||||||
|
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CompilerOptions, Component, Directive, InjectionToken, Injector, ModuleWithComponentFactories, NgModule, NgModuleRef, NgZone, Pipe, PlatformRef, Provider, ReflectiveInjector, SchemaMetadata, Type} from '@angular/core';
|
import {CompilerOptions, Component, Directive, InjectionToken, Injector, ModuleWithComponentFactories, NgModule, NgModuleRef, NgZone, Pipe, PlatformRef, Provider, ReflectiveInjector, SchemaMetadata, Type, __core_private__} from '@angular/core';
|
||||||
|
|
||||||
import {AsyncTestCompleter} from './async_test_completer';
|
import {AsyncTestCompleter} from './async_test_completer';
|
||||||
import {ComponentFixture} from './component_fixture';
|
import {ComponentFixture} from './component_fixture';
|
||||||
import {stringify} from './facade/lang';
|
import {stringify} from './facade/lang';
|
||||||
@ -266,9 +265,9 @@ export class TestBed implements Injector {
|
|||||||
this._moduleWithComponentFactories =
|
this._moduleWithComponentFactories =
|
||||||
this._compiler.compileModuleAndAllComponentsSync(moduleType);
|
this._compiler.compileModuleAndAllComponentsSync(moduleType);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.compType) {
|
if (getComponentType(e)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`This test module uses the component ${stringify(e.compType)} which is using a "templateUrl" or "styleUrls", but they were never compiled. ` +
|
`This test module uses the component ${stringify(getComponentType(e))} which is using a "templateUrl" or "styleUrls", but they were never compiled. ` +
|
||||||
`Please call "TestBed.compileComponents" before your test.`);
|
`Please call "TestBed.compileComponents" before your test.`);
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
@ -471,3 +470,7 @@ export function withModule(moduleDef: TestModuleMetadata, fn: Function = null):
|
|||||||
}
|
}
|
||||||
return new InjectSetupWrapper(() => moduleDef);
|
return new InjectSetupWrapper(() => moduleDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getComponentType(error: Error): Function {
|
||||||
|
return (error as any)[__core_private__.ERROR_COMPONENT_TYPE];
|
||||||
|
}
|
||||||
|
@ -8,9 +8,11 @@
|
|||||||
|
|
||||||
import {Compiler, CompilerOptions, Component, Directive, Injector, NgModule, Pipe, Type} from '@angular/core';
|
import {Compiler, CompilerOptions, Component, Directive, Injector, NgModule, Pipe, Type} from '@angular/core';
|
||||||
|
|
||||||
import {unimplemented} from './facade/errors';
|
|
||||||
import {MetadataOverride} from './metadata_override';
|
import {MetadataOverride} from './metadata_override';
|
||||||
|
|
||||||
|
function unimplemented(): any {
|
||||||
|
throw Error('unimplemented');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special interface to the compiler only used by testing
|
* Special interface to the compiler only used by testing
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience to throw an Error with 'unimplemented' as the message.
|
|
||||||
*/
|
|
||||||
export function unimplemented(): any {
|
|
||||||
throw new Error('unimplemented');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @stable
|
|
||||||
*/
|
|
||||||
export class BaseError extends Error {
|
|
||||||
/** @internal **/
|
|
||||||
_nativeError: Error;
|
|
||||||
|
|
||||||
constructor(message: string) {
|
|
||||||
super(message);
|
|
||||||
// Errors don't use current this, instead they create a new instance.
|
|
||||||
// We have to do forward all of our api to the nativeInstance.
|
|
||||||
// TODO(bradfordcsmith): Remove this hack when
|
|
||||||
// google/closure-compiler/issues/2102 is fixed.
|
|
||||||
const nativeError = new Error(message) as any as Error;
|
|
||||||
this._nativeError = nativeError;
|
|
||||||
}
|
|
||||||
|
|
||||||
get message() { return this._nativeError.message; }
|
|
||||||
set message(message) { this._nativeError.message = message; }
|
|
||||||
get name() { return this._nativeError.name; }
|
|
||||||
get stack() { return (this._nativeError as any).stack; }
|
|
||||||
set stack(value) { (this._nativeError as any).stack = value; }
|
|
||||||
toString() { return this._nativeError.toString(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @stable
|
|
||||||
*/
|
|
||||||
export class WrappedError extends BaseError {
|
|
||||||
originalError: any;
|
|
||||||
|
|
||||||
constructor(message: string, error: any) {
|
|
||||||
super(`${message} caused by: ${error instanceof Error ? error.message: error }`);
|
|
||||||
this.originalError = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
get stack() {
|
|
||||||
return ((this.originalError instanceof Error ? this.originalError : this._nativeError) as any)
|
|
||||||
.stack;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1436,21 +1436,21 @@ export function main() {
|
|||||||
|
|
||||||
bootstrap(platformBrowserDynamic(), Ng2Module, elementA, ng1Module).then(() => {
|
bootstrap(platformBrowserDynamic(), Ng2Module, elementA, ng1Module).then(() => {
|
||||||
expect(mockExceptionHandler).toHaveBeenCalledWith(jasmine.objectContaining({
|
expect(mockExceptionHandler).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||||
originalError: new Error(
|
ngOriginalError: new Error(
|
||||||
'Unable to find required \'iDoNotExist\' in upgraded directive \'ng1A\'.')
|
'Unable to find required \'iDoNotExist\' in upgraded directive \'ng1A\'.')
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
bootstrap(platformBrowserDynamic(), Ng2Module, elementB, ng1Module).then(() => {
|
bootstrap(platformBrowserDynamic(), Ng2Module, elementB, ng1Module).then(() => {
|
||||||
expect(mockExceptionHandler).toHaveBeenCalledWith(jasmine.objectContaining({
|
expect(mockExceptionHandler).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||||
originalError: new Error(
|
ngOriginalError: new Error(
|
||||||
'Unable to find required \'^iDoNotExist\' in upgraded directive \'ng1B\'.')
|
'Unable to find required \'^iDoNotExist\' in upgraded directive \'ng1B\'.')
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
bootstrap(platformBrowserDynamic(), Ng2Module, elementC, ng1Module).then(() => {
|
bootstrap(platformBrowserDynamic(), Ng2Module, elementC, ng1Module).then(() => {
|
||||||
expect(mockExceptionHandler).toHaveBeenCalledWith(jasmine.objectContaining({
|
expect(mockExceptionHandler).toHaveBeenCalledWith(jasmine.objectContaining({
|
||||||
originalError: new Error(
|
ngOriginalError: new Error(
|
||||||
'Unable to find required \'^^iDoNotExist\' in upgraded directive \'ng1C\'.')
|
'Unable to find required \'^^iDoNotExist\' in upgraded directive \'ng1C\'.')
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import {ComponentFactory, ComponentRef, ElementRef, Injector, TemplateRef, ViewContainerRef, ViewRef} from '@angular/core';
|
import {ComponentFactory, ComponentRef, ElementRef, Injector, TemplateRef, ViewContainerRef, ViewRef} from '@angular/core';
|
||||||
import {devModeEqual, looseIdentical} from '@angular/core/src/change_detection/change_detection_util';
|
import {devModeEqual, looseIdentical} from '@angular/core/src/change_detection/change_detection_util';
|
||||||
import {ExpressionChangedAfterItHasBeenCheckedError} from '@angular/core/src/linker/errors';
|
import {expressionChangedAfterItHasBeenCheckedError} from '@angular/core/src/linker/errors';
|
||||||
|
|
||||||
|
|
||||||
export function unimplemented(): any {
|
export function unimplemented(): any {
|
||||||
@ -212,7 +212,7 @@ export function createAnchorAndAppend(parent: any) {
|
|||||||
export function checkBinding(throwOnChange: boolean, oldValue: any, newValue: any): boolean {
|
export function checkBinding(throwOnChange: boolean, oldValue: any, newValue: any): boolean {
|
||||||
if (throwOnChange) {
|
if (throwOnChange) {
|
||||||
if (!devModeEqual(oldValue, newValue)) {
|
if (!devModeEqual(oldValue, newValue)) {
|
||||||
throw new ExpressionChangedAfterItHasBeenCheckedError(oldValue, newValue, false);
|
throw expressionChangedAfterItHasBeenCheckedError(oldValue, newValue, false);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {devModeEqual, looseIdentical} from '@angular/core/src/change_detection/change_detection_util';
|
import {devModeEqual, looseIdentical} from '@angular/core/src/change_detection/change_detection_util';
|
||||||
import {ExpressionChangedAfterItHasBeenCheckedError} from '@angular/core/src/linker/errors';
|
import {expressionChangedAfterItHasBeenCheckedError} from '@angular/core/src/linker/errors';
|
||||||
|
|
||||||
export function createElementAndAppend(parent: any, name: string) {
|
export function createElementAndAppend(parent: any, name: string) {
|
||||||
const el = document.createElement(name);
|
const el = document.createElement(name);
|
||||||
@ -29,7 +29,7 @@ export function createAnchorAndAppend(parent: any) {
|
|||||||
export function checkBinding(throwOnChange: boolean, oldValue: any, newValue: any): boolean {
|
export function checkBinding(throwOnChange: boolean, oldValue: any, newValue: any): boolean {
|
||||||
if (throwOnChange) {
|
if (throwOnChange) {
|
||||||
if (!devModeEqual(oldValue, newValue)) {
|
if (!devModeEqual(oldValue, newValue)) {
|
||||||
throw new ExpressionChangedAfterItHasBeenCheckedError(oldValue, newValue, false);
|
throw expressionChangedAfterItHasBeenCheckedError(oldValue, newValue, false);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user