style(compiler): reformat of codebase with new clang-format version (#36520)

This commit reformats the packages/compiler tree using the new version of
clang-format.

PR Close #36520
This commit is contained in:
Alex Rickabaugh 2020-04-08 10:14:18 -07:00 committed by atscott
parent 0a69a2832b
commit 83a9159063
193 changed files with 5904 additions and 4574 deletions

View File

@ -11,7 +11,7 @@ import {CompilerConfig} from '../config';
import {ConstantPool} from '../constant_pool'; import {ConstantPool} from '../constant_pool';
import {ViewEncapsulation} from '../core'; import {ViewEncapsulation} from '../core';
import {MessageBundle} from '../i18n/message_bundle'; import {MessageBundle} from '../i18n/message_bundle';
import {Identifiers, createTokenForExternalReference} from '../identifiers'; import {createTokenForExternalReference, Identifiers} from '../identifiers';
import {InjectableCompiler} from '../injectable_compiler'; import {InjectableCompiler} from '../injectable_compiler';
import {CompileMetadataResolver} from '../metadata_resolver'; import {CompileMetadataResolver} from '../metadata_resolver';
import {HtmlParser} from '../ml_parser/html_parser'; import {HtmlParser} from '../ml_parser/html_parser';
@ -31,9 +31,9 @@ import {SummaryResolver} from '../summary_resolver';
import {BindingParser} from '../template_parser/binding_parser'; import {BindingParser} from '../template_parser/binding_parser';
import {TemplateAst} from '../template_parser/template_ast'; import {TemplateAst} from '../template_parser/template_ast';
import {TemplateParser} from '../template_parser/template_parser'; import {TemplateParser} from '../template_parser/template_parser';
import {OutputContext, ValueVisitor, error, newArray, syntaxError, visitValue} from '../util'; import {error, newArray, OutputContext, syntaxError, ValueVisitor, visitValue} from '../util';
import {TypeCheckCompiler} from '../view_compiler/type_check_compiler'; import {TypeCheckCompiler} from '../view_compiler/type_check_compiler';
import {ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler'; import {ViewCompiler, ViewCompileResult} from '../view_compiler/view_compiler';
import {AotCompilerHost} from './compiler_host'; import {AotCompilerHost} from './compiler_host';
import {AotCompilerOptions} from './compiler_options'; import {AotCompilerOptions} from './compiler_options';
@ -46,7 +46,11 @@ import {StaticSymbolResolver} from './static_symbol_resolver';
import {createForJitStub, serializeSummaries} from './summary_serializer'; import {createForJitStub, serializeSummaries} from './summary_serializer';
import {ngfactoryFilePath, normalizeGenFileSuffix, splitTypescriptSuffix, summaryFileName, summaryForJitFileName} from './util'; import {ngfactoryFilePath, normalizeGenFileSuffix, splitTypescriptSuffix, summaryFileName, summaryForJitFileName} from './util';
const enum StubEmitFlags { Basic = 1 << 0, TypeCheck = 1 << 1, All = TypeCheck | Basic } const enum StubEmitFlags {
Basic = 1 << 0,
TypeCheck = 1 << 1,
All = TypeCheck | Basic
}
export class AotCompiler { export class AotCompiler {
private _templateAstCache = private _templateAstCache =
@ -64,7 +68,9 @@ export class AotCompiler {
private _summaryResolver: SummaryResolver<StaticSymbol>, private _summaryResolver: SummaryResolver<StaticSymbol>,
private _symbolResolver: StaticSymbolResolver) {} private _symbolResolver: StaticSymbolResolver) {}
clearCache() { this._metadataResolver.clearCache(); } clearCache() {
this._metadataResolver.clearCache();
}
analyzeModulesSync(rootFiles: string[]): NgAnalyzedModules { analyzeModulesSync(rootFiles: string[]): NgAnalyzedModules {
const analyzeResult = analyzeAndValidateNgModules( const analyzeResult = analyzeAndValidateNgModules(
@ -149,7 +155,8 @@ export class AotCompiler {
if (genFileName.endsWith('.ngfactory.ts')) { if (genFileName.endsWith('.ngfactory.ts')) {
if (!originalFileName) { if (!originalFileName) {
throw new Error( throw new Error(
`Assertion error: require the original file for .ngfactory.ts stubs. File: ${genFileName}`); `Assertion error: require the original file for .ngfactory.ts stubs. File: ${
genFileName}`);
} }
const originalFile = this._analyzeFile(originalFileName); const originalFile = this._analyzeFile(originalFileName);
this._createNgFactoryStub(outputCtx, originalFile, StubEmitFlags.Basic); this._createNgFactoryStub(outputCtx, originalFile, StubEmitFlags.Basic);
@ -157,7 +164,8 @@ export class AotCompiler {
if (this._options.enableSummariesForJit) { if (this._options.enableSummariesForJit) {
if (!originalFileName) { if (!originalFileName) {
throw new Error( throw new Error(
`Assertion error: require the original file for .ngsummary.ts stubs. File: ${genFileName}`); `Assertion error: require the original file for .ngsummary.ts stubs. File: ${
genFileName}`);
} }
const originalFile = this._analyzeFile(originalFileName); const originalFile = this._analyzeFile(originalFileName);
_createEmptyStub(outputCtx); _createEmptyStub(outputCtx);
@ -383,8 +391,8 @@ export class AotCompiler {
if (directiveMetadata.isComponent) { if (directiveMetadata.isComponent) {
const module = ngModuleByPipeOrDirective.get(directiveType)!; const module = ngModuleByPipeOrDirective.get(directiveType)!;
module || module ||
error( error(`Cannot determine the module for component '${
`Cannot determine the module for component '${identifierName(directiveMetadata.type)}'`); identifierName(directiveMetadata.type)}'`);
let htmlAst = directiveMetadata.template !.htmlAst!; let htmlAst = directiveMetadata.template !.htmlAst!;
const preserveWhitespaces = directiveMetadata!.template !.preserveWhitespaces; const preserveWhitespaces = directiveMetadata!.template !.preserveWhitespaces;
@ -412,7 +420,9 @@ export class AotCompiler {
const pipes = module.transitiveModule.pipes.map( const pipes = module.transitiveModule.pipes.map(
pipe => this._metadataResolver.getPipeSummary(pipe.reference)); pipe => this._metadataResolver.getPipeSummary(pipe.reference));
pipes.forEach(pipe => { pipeTypeByName.set(pipe.name, pipe.type.reference); }); pipes.forEach(pipe => {
pipeTypeByName.set(pipe.name, pipe.type.reference);
});
compileR3Component( compileR3Component(
context, directiveMetadata, render3Ast, this.reflector, hostBindingParser, context, directiveMetadata, render3Ast, this.reflector, hostBindingParser,
@ -484,8 +494,8 @@ export class AotCompiler {
} }
const ngModule = ngModuleByPipeOrDirective.get(dirType); const ngModule = ngModuleByPipeOrDirective.get(dirType);
if (!ngModule) { if (!ngModule) {
throw new Error( throw new Error(`Internal Error: cannot determine the module for component ${
`Internal Error: cannot determine the module for component ${identifierName(compMeta.type)}!`); identifierName(compMeta.type)}!`);
} }
// compile styles // compile styles
@ -664,8 +674,7 @@ export class AotCompiler {
private _createOutputContext(genFilePath: string): OutputContext { private _createOutputContext(genFilePath: string): OutputContext {
const importExpr = const importExpr =
(symbol: StaticSymbol, typeParams: o.Type[] | null = null, (symbol: StaticSymbol, typeParams: o.Type[]|null = null, useSummaries: boolean = true) => {
useSummaries: boolean = true) => {
if (!(symbol instanceof StaticSymbol)) { if (!(symbol instanceof StaticSymbol)) {
throw new Error(`Internal error: unknown identifier ${JSON.stringify(symbol)}`); throw new Error(`Internal error: unknown identifier ${JSON.stringify(symbol)}`);
} }
@ -748,8 +757,8 @@ export class AotCompiler {
return allLazyRoutes; return allLazyRoutes;
} }
seenRoutes.add(symbol); seenRoutes.add(symbol);
const lazyRoutes = listLazyRoutes( const lazyRoutes =
self._metadataResolver.getNgModuleMetadata(symbol, true) !, self.reflector); listLazyRoutes(self._metadataResolver.getNgModuleMetadata(symbol, true)!, self.reflector);
for (const lazyRoute of lazyRoutes) { for (const lazyRoute of lazyRoutes) {
allLazyRoutes.push(lazyRoute); allLazyRoutes.push(lazyRoute);
visitLazyRoute(lazyRoute.referencedModule, seenRoutes, allLazyRoutes); visitLazyRoute(lazyRoute.referencedModule, seenRoutes, allLazyRoutes);
@ -803,7 +812,9 @@ export interface NgAnalyzedFile {
exportsNonSourceFiles: boolean; exportsNonSourceFiles: boolean;
} }
export interface NgAnalyzeModulesHost { isSourceFile(filePath: string): boolean; } export interface NgAnalyzeModulesHost {
isSourceFile(filePath: string): boolean;
}
export function analyzeNgModules( export function analyzeNgModules(
fileNames: string[], host: NgAnalyzeModulesHost, staticSymbolResolver: StaticSymbolResolver, fileNames: string[], host: NgAnalyzeModulesHost, staticSymbolResolver: StaticSymbolResolver,
@ -823,8 +834,8 @@ export function analyzeAndValidateNgModules(
function validateAnalyzedModules(analyzedModules: NgAnalyzedModules): NgAnalyzedModules { function validateAnalyzedModules(analyzedModules: NgAnalyzedModules): NgAnalyzedModules {
if (analyzedModules.symbolsMissingModule && analyzedModules.symbolsMissingModule.length) { if (analyzedModules.symbolsMissingModule && analyzedModules.symbolsMissingModule.length) {
const messages = analyzedModules.symbolsMissingModule.map( const messages = analyzedModules.symbolsMissingModule.map(
s => s => `Cannot determine the module for class ${s.name} in ${s.filePath}! Add ${
`Cannot determine the module for class ${s.name} in ${s.filePath}! Add ${s.name} to the NgModule to fix it.`); s.name} to the NgModule to fix it.`);
throw syntaxError(messages.join('\n')); throw syntaxError(messages.join('\n'));
} }
return analyzedModules; return analyzedModules;
@ -918,8 +929,13 @@ export function analyzeFile(
}); });
} }
return { return {
fileName, directives, abstractDirectives, pipes, fileName,
ngModules, injectables, exportsNonSourceFiles, directives,
abstractDirectives,
pipes,
ngModules,
injectables,
exportsNonSourceFiles,
}; };
} }
@ -957,7 +973,9 @@ function isValueExportingNonSourceFile(host: NgAnalyzeModulesHost, metadata: any
let exportsNonSourceFiles = false; let exportsNonSourceFiles = false;
class Visitor implements ValueVisitor { class Visitor implements ValueVisitor {
visitArray(arr: any[], context: any): any { arr.forEach(v => visitValue(v, this, context)); } visitArray(arr: any[], context: any): any {
arr.forEach(v => visitValue(v, this, context));
}
visitStringMap(map: {[key: string]: any}, context: any): any { visitStringMap(map: {[key: string]: any}, context: any): any {
Object.keys(map).forEach((key) => visitValue(map[key], this, context)); Object.keys(map).forEach((key) => visitValue(map[key], this, context));
} }

View File

@ -36,9 +36,9 @@ import {StaticSymbol, StaticSymbolCache} from './static_symbol';
import {StaticSymbolResolver} from './static_symbol_resolver'; import {StaticSymbolResolver} from './static_symbol_resolver';
import {AotSummaryResolver} from './summary_resolver'; import {AotSummaryResolver} from './summary_resolver';
export function createAotUrlResolver(host: { export function createAotUrlResolver(
resourceNameToFileName(resourceName: string, containingFileName: string): string | null; host: {resourceNameToFileName(resourceName: string, containingFileName: string): string|null;}):
}): UrlResolver { UrlResolver {
return { return {
resolve: (basePath: string, url: string) => { resolve: (basePath: string, url: string) => {
const filePath = host.resourceNameToFileName(url, basePath); const filePath = host.resourceNameToFileName(url, basePath);

View File

@ -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 {Statement, areAllEquivalent} from '../output/output_ast'; import {areAllEquivalent, Statement} from '../output/output_ast';
import {TypeScriptEmitter} from '../output/ts_emitter'; import {TypeScriptEmitter} from '../output/ts_emitter';
export class GeneratedFile { export class GeneratedFile {

View File

@ -8,12 +8,12 @@
import {CompileSummaryKind} from '../compile_metadata'; import {CompileSummaryKind} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector'; import {CompileReflector} from '../compile_reflector';
import {MetadataFactory, createAttribute, createComponent, createContentChild, createContentChildren, createDirective, createHost, createHostBinding, createHostListener, createInject, createInjectable, createInput, createNgModule, createOptional, createOutput, createPipe, createSelf, createSkipSelf, createViewChild, createViewChildren} from '../core'; import {createAttribute, createComponent, createContentChild, createContentChildren, createDirective, createHost, createHostBinding, createHostListener, createInject, createInjectable, createInput, createNgModule, createOptional, createOutput, createPipe, createSelf, createSkipSelf, createViewChild, createViewChildren, MetadataFactory} from '../core';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {SummaryResolver} from '../summary_resolver'; import {SummaryResolver} from '../summary_resolver';
import {syntaxError} from '../util'; import {syntaxError} from '../util';
import {FormattedMessageChain, formattedError} from './formatted_error'; import {formattedError, FormattedMessageChain} from './formatted_error';
import {StaticSymbol} from './static_symbol'; import {StaticSymbol} from './static_symbol';
import {StaticSymbolResolver} from './static_symbol_resolver'; import {StaticSymbolResolver} from './static_symbol_resolver';
@ -199,9 +199,13 @@ export class StaticReflector implements CompileReflector {
this.reportError( this.reportError(
formatMetadataError( formatMetadataError(
metadataError( metadataError(
`Class ${type.name} in ${type.filePath} extends from a ${CompileSummaryKind[summary.type.summaryKind!]} in another compilation unit without duplicating the decorator`, `Class ${type.name} in ${type.filePath} extends from a ${
CompileSummaryKind[summary.type.summaryKind!
]} in another compilation unit without duplicating the decorator`,
/* summary */ undefined, /* summary */ undefined,
`Please add a ${requiredAnnotationTypes.map((type) => type.ngMetadataName).join(' or ')} decorator to the class`), `Please add a ${
requiredAnnotationTypes.map((type) => type.ngMetadataName)
.join(' or ')} decorator to the class`),
type), type),
type); type);
} }
@ -494,7 +498,8 @@ export class StaticReflector implements CompileReflector {
{ {
message: e.message, message: e.message,
advise: e.advise, advise: e.advise,
context: e.context, chain, context: e.context,
chain,
symbol: nestedContext symbol: nestedContext
}, },
context); context);
@ -566,7 +571,8 @@ export class StaticReflector implements CompileReflector {
{ {
message: FUNCTION_CALL_NOT_SUPPORTED, message: FUNCTION_CALL_NOT_SUPPORTED,
context: functionSymbol, context: functionSymbol,
value: targetFunction, position value: targetFunction,
position
}, },
context); context);
} }
@ -916,7 +922,8 @@ function expandedMessage(message: string, context: any): string {
switch (message) { switch (message) {
case REFERENCE_TO_NONEXPORTED_CLASS: case REFERENCE_TO_NONEXPORTED_CLASS:
if (context && context.className) { if (context && context.className) {
return `References to a non-exported class are not supported in decorators but ${context.className} was referenced.`; return `References to a non-exported class are not supported in decorators but ${
context.className} was referenced.`;
} }
break; break;
case VARIABLE_NOT_INITIALIZED: case VARIABLE_NOT_INITIALIZED:
@ -935,7 +942,8 @@ function expandedMessage(message: string, context: any): string {
return 'Function calls are not supported in decorators'; return 'Function calls are not supported in decorators';
case REFERENCE_TO_LOCAL_SYMBOL: case REFERENCE_TO_LOCAL_SYMBOL:
if (context && context.name) { if (context && context.name) {
return `Reference to a local (non-exported) symbols are not supported in decorators but '${context.name}' was referenced`; return `Reference to a local (non-exported) symbols are not supported in decorators but '${
context.name}' was referenced`;
} }
break; break;
case LAMBDA_NOT_SUPPORTED: case LAMBDA_NOT_SUPPORTED:
@ -1040,7 +1048,9 @@ abstract class BindingScope {
} }
class PopulatedScope extends BindingScope { class PopulatedScope extends BindingScope {
constructor(private bindings: Map<string, any>) { super(); } constructor(private bindings: Map<string, any>) {
super();
}
resolve(name: string): any { resolve(name: string): any {
return this.bindings.has(name) ? this.bindings.get(name) : BindingScope.missing; return this.bindings.has(name) ? this.bindings.get(name) : BindingScope.missing;

View File

@ -119,10 +119,9 @@ export class StaticSymbolResolver {
const baseSymbol = const baseSymbol =
this.getStaticSymbol(summarizedFileName, summarizedName, staticSymbol.members); this.getStaticSymbol(summarizedFileName, summarizedName, staticSymbol.members);
const baseImportAs = this.getImportAs(baseSymbol, useSummaries); const baseImportAs = this.getImportAs(baseSymbol, useSummaries);
return baseImportAs ? return baseImportAs ? this.getStaticSymbol(
this.getStaticSymbol( summaryForJitFileName(baseImportAs.filePath),
summaryForJitFileName(baseImportAs.filePath), summaryForJitName(baseImportAs.name), summaryForJitName(baseImportAs.name), baseSymbol.members) :
baseSymbol.members) :
null; null;
} }
let result = (useSummaries && this.summaryResolver.getImportAs(staticSymbol)) || null; let result = (useSummaries && this.summaryResolver.getImportAs(staticSymbol)) || null;
@ -347,8 +346,8 @@ export class StaticSymbolResolver {
// correctly. // correctly.
const originFilePath = this.resolveModule(origin, filePath); const originFilePath = this.resolveModule(origin, filePath);
if (!originFilePath) { if (!originFilePath) {
this.reportError(new Error( this.reportError(new Error(`Couldn't resolve original symbol for ${origin} from ${
`Couldn't resolve original symbol for ${origin} from ${this.host.getOutputName(filePath)}`)); this.host.getOutputName(filePath)}`));
} else { } else {
this.symbolResourcePaths.set(symbol, originFilePath); this.symbolResourcePaths.set(symbol, originFilePath);
} }
@ -501,8 +500,11 @@ export class StaticSymbolResolver {
} }
if (moduleMetadata['version'] != SUPPORTED_SCHEMA_VERSION) { if (moduleMetadata['version'] != SUPPORTED_SCHEMA_VERSION) {
const errorMessage = moduleMetadata['version'] == 2 ? const errorMessage = moduleMetadata['version'] == 2 ?
`Unsupported metadata version ${moduleMetadata['version']} for module ${module}. This module should be compiled with a newer version of ngc` : `Unsupported metadata version ${moduleMetadata['version']} for module ${
`Metadata version mismatch for module ${this.host.getOutputName(module)}, found version ${moduleMetadata['version']}, expected ${SUPPORTED_SCHEMA_VERSION}`; module}. This module should be compiled with a newer version of ngc` :
`Metadata version mismatch for module ${
this.host.getOutputName(module)}, found version ${
moduleMetadata['version']}, expected ${SUPPORTED_SCHEMA_VERSION}`;
this.reportError(new Error(errorMessage)); this.reportError(new Error(errorMessage));
} }
this.metadataCache.set(module, moduleMetadata); this.metadataCache.set(module, moduleMetadata);
@ -514,9 +516,8 @@ export class StaticSymbolResolver {
getSymbolByModule(module: string, symbolName: string, containingFile?: string): StaticSymbol { getSymbolByModule(module: string, symbolName: string, containingFile?: string): StaticSymbol {
const filePath = this.resolveModule(module, containingFile); const filePath = this.resolveModule(module, containingFile);
if (!filePath) { if (!filePath) {
this.reportError( this.reportError(new Error(`Could not resolve module ${module}${
new Error(`Could not resolve module ${module}${containingFile ? ' relative to ' + containingFile ? ' relative to ' + this.host.getOutputName(containingFile) : ''}`));
this.host.getOutputName(containingFile) : ''}`));
return this.getStaticSymbol(`ERROR:${module}`, symbolName); return this.getStaticSymbol(`ERROR:${module}`, symbolName);
} }
return this.getStaticSymbol(filePath, symbolName); return this.getStaticSymbol(filePath, symbolName);

View File

@ -95,7 +95,9 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
return this.knownFileNameToModuleNames.get(importedFilePath) || null; return this.knownFileNameToModuleNames.get(importedFilePath) || null;
} }
addSummary(summary: Summary<StaticSymbol>) { this.summaryCache.set(summary.symbol, summary); } addSummary(summary: Summary<StaticSymbol>) {
this.summaryCache.set(summary.symbol, summary);
}
private _loadSummaryFile(filePath: string): boolean { private _loadSummaryFile(filePath: string): boolean {
let hasSummary = this.loadedFilePaths.get(filePath); let hasSummary = this.loadedFilePaths.get(filePath);
@ -121,7 +123,9 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
if (moduleName) { if (moduleName) {
this.knownFileNameToModuleNames.set(filePath, moduleName); this.knownFileNameToModuleNames.set(filePath, moduleName);
} }
importAs.forEach((importAs) => { this.importAs.set(importAs.symbol, importAs.importAs); }); importAs.forEach((importAs) => {
this.importAs.set(importAs.symbol, importAs.importAs);
});
} }
return hasSummary; return hasSummary;
} }

View File

@ -41,7 +41,9 @@ export function serializeSummaries(
const {json, exportAs} = toJsonSerializer.serialize(createExternalSymbolReexports); const {json, exportAs} = toJsonSerializer.serialize(createExternalSymbolReexports);
if (forJitCtx) { if (forJitCtx) {
const forJitSerializer = new ForJitSerializer(forJitCtx, symbolResolver, summaryResolver); const forJitSerializer = new ForJitSerializer(forJitCtx, symbolResolver, summaryResolver);
types.forEach(({summary, metadata}) => { forJitSerializer.addSourceType(summary, metadata); }); types.forEach(({summary, metadata}) => {
forJitSerializer.addSourceType(summary, metadata);
});
toJsonSerializer.unprocessedSymbolSummariesBySymbol.forEach((summary) => { toJsonSerializer.unprocessedSymbolSummariesBySymbol.forEach((summary) => {
if (summaryResolver.isLibraryFile(summary.symbol.filePath) && summary.type) { if (summaryResolver.isLibraryFile(summary.symbol.filePath) && summary.type) {
forJitSerializer.addLibType(summary.type); forJitSerializer.addLibType(summary.type);
@ -324,8 +326,9 @@ class ForJitSerializer {
private summaryResolver: SummaryResolver<StaticSymbol>) {} private summaryResolver: SummaryResolver<StaticSymbol>) {}
addSourceType( addSourceType(
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata| summary: CompileTypeSummary,
CompilePipeMetadata|CompileTypeMetadata) { metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|CompilePipeMetadata|
CompileTypeMetadata) {
this.data.push({summary, metadata, isLibrary: false}); this.data.push({summary, metadata, isLibrary: false});
} }
@ -372,8 +375,9 @@ class ForJitSerializer {
} }
private serializeSummaryWithDeps( private serializeSummaryWithDeps(
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata| summary: CompileTypeSummary,
CompilePipeMetadata|CompileTypeMetadata): o.Expression { metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|CompilePipeMetadata|
CompileTypeMetadata): o.Expression {
const expressions: o.Expression[] = [this.serializeSummary(summary)]; const expressions: o.Expression[] = [this.serializeSummary(summary)];
let providers: CompileProviderMetadata[] = []; let providers: CompileProviderMetadata[] = [];
if (metadata instanceof CompileNgModuleMetadata) { if (metadata instanceof CompileNgModuleMetadata) {
@ -403,7 +407,8 @@ class ForJitSerializer {
// i.e. we didn't generate .ngsummary.ts files for these. // i.e. we didn't generate .ngsummary.ts files for these.
expressions.push( expressions.push(
...providers.filter(provider => !!provider.useClass).map(provider => this.serializeSummary({ ...providers.filter(provider => !!provider.useClass).map(provider => this.serializeSummary({
summaryKind: CompileSummaryKind.Injectable, type: provider.useClass summaryKind: CompileSummaryKind.Injectable,
type: provider.useClass
} as CompileTypeSummary))); } as CompileTypeSummary)));
return o.literalArr(expressions); return o.literalArr(expressions);
} }
@ -425,7 +430,9 @@ class ForJitSerializer {
return new o.LiteralMapExpr(Object.keys(map).map( return new o.LiteralMapExpr(Object.keys(map).map(
(key) => new o.LiteralMapEntry(key, visitValue(map[key], this, context), false))); (key) => new o.LiteralMapEntry(key, visitValue(map[key], this, context), false)));
} }
visitPrimitive(value: any, context: any): any { return o.literal(value); } visitPrimitive(value: any, context: any): any {
return o.literal(value);
}
visitOther(value: any, context: any): any { visitOther(value: any, context: any): any {
if (value instanceof StaticSymbol) { if (value instanceof StaticSymbol) {
return outputCtx.importExpr(value); return outputCtx.importExpr(value);

View File

@ -26,14 +26,22 @@
export class AstPath<T> { export class AstPath<T> {
constructor(private path: T[], public position: number = -1) {} constructor(private path: T[], public position: number = -1) {}
get empty(): boolean { return !this.path || !this.path.length; } get empty(): boolean {
get head(): T|undefined { return this.path[0]; } return !this.path || !this.path.length;
get tail(): T|undefined { return this.path[this.path.length - 1]; } }
get head(): T|undefined {
return this.path[0];
}
get tail(): T|undefined {
return this.path[this.path.length - 1];
}
parentOf(node: T|undefined): T|undefined { parentOf(node: T|undefined): T|undefined {
return node && this.path[this.path.indexOf(node) - 1]; return node && this.path[this.path.indexOf(node) - 1];
} }
childOf(node: T): T|undefined { return this.path[this.path.indexOf(node) + 1]; } childOf(node: T): T|undefined {
return this.path[this.path.indexOf(node) + 1];
}
first<N extends T>(ctor: {new(...args: any[]): N}): N|undefined { first<N extends T>(ctor: {new(...args: any[]): N}): N|undefined {
for (let i = this.path.length - 1; i >= 0; i--) { for (let i = this.path.length - 1; i >= 0; i--) {
@ -42,7 +50,11 @@ export class AstPath<T> {
} }
} }
push(node: T) { this.path.push(node); } push(node: T) {
this.path.push(node);
pop(): T { return this.path.pop() !; } }
pop(): T {
return this.path.pop()!;
}
} }

View File

@ -24,8 +24,8 @@ export function sanitizeIdentifier(name: string): string {
let _anonymousTypeIndex = 0; let _anonymousTypeIndex = 0;
export function identifierName(compileIdentifier: CompileIdentifierMetadata | null | undefined): export function identifierName(compileIdentifier: CompileIdentifierMetadata|null|undefined): string|
string|null { null {
if (!compileIdentifier || !compileIdentifier.reference) { if (!compileIdentifier || !compileIdentifier.reference) {
return null; return null;
} }
@ -72,9 +72,13 @@ export function componentFactoryName(compType: any): string {
return `${identifierName({reference: compType})}NgFactory`; return `${identifierName({reference: compType})}NgFactory`;
} }
export interface ProxyClass { setDelegate(delegate: any): void; } export interface ProxyClass {
setDelegate(delegate: any): void;
}
export interface CompileIdentifierMetadata { reference: any; } export interface CompileIdentifierMetadata {
reference: any;
}
export enum CompileSummaryKind { export enum CompileSummaryKind {
Pipe, Pipe,
@ -175,8 +179,8 @@ export class CompileStylesheetMetadata {
styles: string[]; styles: string[];
styleUrls: string[]; styleUrls: string[];
constructor( constructor(
{moduleUrl, styles, {moduleUrl, styles, styleUrls}:
styleUrls}: {moduleUrl?: string, styles?: string[], styleUrls?: string[]} = {}) { {moduleUrl?: string, styles?: string[], styleUrls?: string[]} = {}) {
this.moduleUrl = moduleUrl || null; this.moduleUrl = moduleUrl || null;
this.styles = _normalizeArray(styles); this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls); this.styleUrls = _normalizeArray(styleUrls);
@ -209,9 +213,20 @@ export class CompileTemplateMetadata {
ngContentSelectors: string[]; ngContentSelectors: string[];
interpolation: [string, string]|null; interpolation: [string, string]|null;
preserveWhitespaces: boolean; preserveWhitespaces: boolean;
constructor({encapsulation, template, templateUrl, htmlAst, styles, styleUrls, constructor({
externalStylesheets, animations, ngContentSelectors, interpolation, isInline, encapsulation,
preserveWhitespaces}: { template,
templateUrl,
htmlAst,
styles,
styleUrls,
externalStylesheets,
animations,
ngContentSelectors,
interpolation,
isInline,
preserveWhitespaces
}: {
encapsulation: ViewEncapsulation|null, encapsulation: ViewEncapsulation|null,
template: string|null, template: string|null,
templateUrl: string|null, templateUrl: string|null,
@ -286,9 +301,27 @@ export interface CompileDirectiveSummary extends CompileTypeSummary {
* Metadata regarding compilation of a directive. * Metadata regarding compilation of a directive.
*/ */
export class CompileDirectiveMetadata { export class CompileDirectiveMetadata {
static create({isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, static create({
host, providers, viewProviders, queries, guards, viewQueries, entryComponents, isHost,
template, componentViewType, rendererType, componentFactory}: { type,
isComponent,
selector,
exportAs,
changeDetection,
inputs,
outputs,
host,
providers,
viewProviders,
queries,
guards,
viewQueries,
entryComponents,
template,
componentViewType,
rendererType,
componentFactory
}: {
isHost: boolean, isHost: boolean,
type: CompileTypeMetadata, type: CompileTypeMetadata,
isComponent: boolean, isComponent: boolean,
@ -347,7 +380,10 @@ export class CompileDirectiveMetadata {
return new CompileDirectiveMetadata({ return new CompileDirectiveMetadata({
isHost, isHost,
type, type,
isComponent: !!isComponent, selector, exportAs, changeDetection, isComponent: !!isComponent,
selector,
exportAs,
changeDetection,
inputs: inputsMap, inputs: inputsMap,
outputs: outputsMap, outputs: outputsMap,
hostListeners, hostListeners,
@ -389,7 +425,8 @@ export class CompileDirectiveMetadata {
rendererType: StaticSymbol|object|null; rendererType: StaticSymbol|object|null;
componentFactory: StaticSymbol|object|null; componentFactory: StaticSymbol|object|null;
constructor({isHost, constructor({
isHost,
type, type,
isComponent, isComponent,
selector, selector,
@ -409,7 +446,8 @@ export class CompileDirectiveMetadata {
template, template,
componentViewType, componentViewType,
rendererType, rendererType,
componentFactory}: { componentFactory
}: {
isHost: boolean, isHost: boolean,
type: CompileTypeMetadata, type: CompileTypeMetadata,
isComponent: boolean, isComponent: boolean,
@ -562,9 +600,21 @@ export class CompileNgModuleMetadata {
transitiveModule: TransitiveCompileNgModuleMetadata; transitiveModule: TransitiveCompileNgModuleMetadata;
constructor({type, providers, declaredDirectives, exportedDirectives, declaredPipes, constructor({
exportedPipes, entryComponents, bootstrapComponents, importedModules, type,
exportedModules, schemas, transitiveModule, id}: { providers,
declaredDirectives,
exportedDirectives,
declaredPipes,
exportedPipes,
entryComponents,
bootstrapComponents,
importedModules,
exportedModules,
schemas,
transitiveModule,
id
}: {
type: CompileTypeMetadata, type: CompileTypeMetadata,
providers: CompileProviderMetadata[], providers: CompileProviderMetadata[],
declaredDirectives: CompileIdentifierMetadata[], declaredDirectives: CompileIdentifierMetadata[],

View File

@ -22,7 +22,9 @@
* ``` * ```
*/ */
export interface ExportedCompilerFacade { ɵcompilerFacade: CompilerFacade; } export interface ExportedCompilerFacade {
ɵcompilerFacade: CompilerFacade;
}
export interface CompilerFacade { export interface CompilerFacade {
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3PipeMetadataFacade): compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3PipeMetadataFacade):
@ -47,7 +49,9 @@ export interface CompilerFacade {
ResourceLoader: {new(): ResourceLoader}; ResourceLoader: {new(): ResourceLoader};
} }
export interface CoreEnvironment { [name: string]: Function; } export interface CoreEnvironment {
[name: string]: Function;
}
export type ResourceLoader = { export type ResourceLoader = {
get(url: string): Promise<string>|string; get(url: string): Promise<string>|string;

View File

@ -11,7 +11,9 @@ import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {ParseSourceSpan} from '../parse_util'; import {ParseSourceSpan} from '../parse_util';
export class EventHandlerVars { static event = o.variable('$event'); } export class EventHandlerVars {
static event = o.variable('$event');
}
export interface LocalResolver { export interface LocalResolver {
getLocal(name: string): o.Expression|null; getLocal(name: string): o.Expression|null;
@ -126,7 +128,9 @@ export function convertActionBinding(
return new ConvertActionBindingResult(actionStmts, preventDefaultVar); return new ConvertActionBindingResult(actionStmts, preventDefaultVar);
} }
export interface BuiltinConverter { (args: o.Expression[]): o.Expression; } export interface BuiltinConverter {
(args: o.Expression[]): o.Expression;
}
export interface BuiltinConverterFactory { export interface BuiltinConverterFactory {
createLiteralArrayConverter(argCount: number): BuiltinConverter; createLiteralArrayConverter(argCount: number): BuiltinConverter;
@ -284,7 +288,9 @@ function convertToStatementIfNeeded(mode: _Mode, expr: o.Expression): o.Expressi
} }
class _BuiltinAstConverter extends cdAst.AstTransformer { class _BuiltinAstConverter extends cdAst.AstTransformer {
constructor(private _converterFactory: BuiltinConverterFactory) { super(); } constructor(private _converterFactory: BuiltinConverterFactory) {
super();
}
visitPipe(ast: cdAst.BindingPipe, context: any): any { visitPipe(ast: cdAst.BindingPipe, context: any): any {
const args = [ast.exp, ...ast.args].map(ast => ast.visit(this, context)); const args = [ast.exp, ...ast.args].map(ast => ast.visit(this, context));
return new BuiltinFunctionCall( return new BuiltinFunctionCall(
@ -384,9 +390,10 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
visitConditional(ast: cdAst.Conditional, mode: _Mode): any { visitConditional(ast: cdAst.Conditional, mode: _Mode): any {
const value: o.Expression = this._visit(ast.condition, _Mode.Expression); const value: o.Expression = this._visit(ast.condition, _Mode.Expression);
return convertToStatementIfNeeded( return convertToStatementIfNeeded(
mode, value.conditional( mode,
this._visit(ast.trueExp, _Mode.Expression), value.conditional(
this._visit(ast.falseExp, _Mode.Expression), this.convertSourceSpan(ast.span))); this._visit(ast.trueExp, _Mode.Expression), this._visit(ast.falseExp, _Mode.Expression),
this.convertSourceSpan(ast.span)));
} }
visitPipe(ast: cdAst.BindingPipe, mode: _Mode): any { visitPipe(ast: cdAst.BindingPipe, mode: _Mode): any {
@ -467,7 +474,9 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
mode, o.literal(ast.value, type, this.convertSourceSpan(ast.span))); mode, o.literal(ast.value, type, this.convertSourceSpan(ast.span)));
} }
private _getLocal(name: string): o.Expression|null { return this._localResolver.getLocal(name); } private _getLocal(name: string): o.Expression|null {
return this._localResolver.getLocal(name);
}
visitMethodCall(ast: cdAst.MethodCall, mode: _Mode): any { visitMethodCall(ast: cdAst.MethodCall, mode: _Mode): any {
if (ast.receiver instanceof cdAst.ImplicitReceiver && ast.name == '$any') { if (ast.receiver instanceof cdAst.ImplicitReceiver && ast.name == '$any') {
@ -558,8 +567,8 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
// Otherwise it's an error. // Otherwise it's an error.
const receiver = ast.name; const receiver = ast.name;
const value = (ast.value instanceof cdAst.PropertyRead) ? ast.value.name : undefined; const value = (ast.value instanceof cdAst.PropertyRead) ? ast.value.name : undefined;
throw new Error( throw new Error(`Cannot assign value "${value}" to template variable "${
`Cannot assign value "${value}" to template variable "${receiver}". Template variables are read-only.`); receiver}". Template variables are read-only.`);
} }
} }
} }
@ -579,7 +588,9 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode); return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
} }
visitAll(asts: cdAst.AST[], mode: _Mode): any { return asts.map(ast => this._visit(ast, mode)); } visitAll(asts: cdAst.AST[], mode: _Mode): any {
return asts.map(ast => this._visit(ast, mode));
}
visitQuote(ast: cdAst.Quote, mode: _Mode): any { visitQuote(ast: cdAst.Quote, mode: _Mode): any {
throw new Error(`Quotes are not supported for evaluation! throw new Error(`Quotes are not supported for evaluation!
@ -652,12 +663,14 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
// leftMostNode with its unguarded version in the call to `this.visit()`. // leftMostNode with its unguarded version in the call to `this.visit()`.
if (leftMostSafe instanceof cdAst.SafeMethodCall) { if (leftMostSafe instanceof cdAst.SafeMethodCall) {
this._nodeMap.set( this._nodeMap.set(
leftMostSafe, new cdAst.MethodCall( leftMostSafe,
leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, new cdAst.MethodCall(
leftMostSafe.name, leftMostSafe.args)); leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.name,
leftMostSafe.args));
} else { } else {
this._nodeMap.set( this._nodeMap.set(
leftMostSafe, new cdAst.PropertyRead( leftMostSafe,
new cdAst.PropertyRead(
leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver,
leftMostSafe.name)); leftMostSafe.name));
} }
@ -690,25 +703,63 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
return (this._nodeMap.get(ast) || ast).visit(visitor); return (this._nodeMap.get(ast) || ast).visit(visitor);
}; };
return ast.visit({ return ast.visit({
visitBinary(ast: cdAst.Binary) { return null; }, visitBinary(ast: cdAst.Binary) {
visitChain(ast: cdAst.Chain) { return null; }, return null;
visitConditional(ast: cdAst.Conditional) { return null; }, },
visitFunctionCall(ast: cdAst.FunctionCall) { return null; }, visitChain(ast: cdAst.Chain) {
visitImplicitReceiver(ast: cdAst.ImplicitReceiver) { return null; }, return null;
visitInterpolation(ast: cdAst.Interpolation) { return null; }, },
visitKeyedRead(ast: cdAst.KeyedRead) { return visit(this, ast.obj); }, visitConditional(ast: cdAst.Conditional) {
visitKeyedWrite(ast: cdAst.KeyedWrite) { return null; }, return null;
visitLiteralArray(ast: cdAst.LiteralArray) { return null; }, },
visitLiteralMap(ast: cdAst.LiteralMap) { return null; }, visitFunctionCall(ast: cdAst.FunctionCall) {
visitLiteralPrimitive(ast: cdAst.LiteralPrimitive) { return null; }, return null;
visitMethodCall(ast: cdAst.MethodCall) { return visit(this, ast.receiver); }, },
visitPipe(ast: cdAst.BindingPipe) { return null; }, visitImplicitReceiver(ast: cdAst.ImplicitReceiver) {
visitPrefixNot(ast: cdAst.PrefixNot) { return null; }, return null;
visitNonNullAssert(ast: cdAst.NonNullAssert) { return null; }, },
visitPropertyRead(ast: cdAst.PropertyRead) { return visit(this, ast.receiver); }, visitInterpolation(ast: cdAst.Interpolation) {
visitPropertyWrite(ast: cdAst.PropertyWrite) { return null; }, return null;
visitQuote(ast: cdAst.Quote) { return null; }, },
visitSafeMethodCall(ast: cdAst.SafeMethodCall) { return visit(this, ast.receiver) || ast; }, visitKeyedRead(ast: cdAst.KeyedRead) {
return visit(this, ast.obj);
},
visitKeyedWrite(ast: cdAst.KeyedWrite) {
return null;
},
visitLiteralArray(ast: cdAst.LiteralArray) {
return null;
},
visitLiteralMap(ast: cdAst.LiteralMap) {
return null;
},
visitLiteralPrimitive(ast: cdAst.LiteralPrimitive) {
return null;
},
visitMethodCall(ast: cdAst.MethodCall) {
return visit(this, ast.receiver);
},
visitPipe(ast: cdAst.BindingPipe) {
return null;
},
visitPrefixNot(ast: cdAst.PrefixNot) {
return null;
},
visitNonNullAssert(ast: cdAst.NonNullAssert) {
return null;
},
visitPropertyRead(ast: cdAst.PropertyRead) {
return visit(this, ast.receiver);
},
visitPropertyWrite(ast: cdAst.PropertyWrite) {
return null;
},
visitQuote(ast: cdAst.Quote) {
return null;
},
visitSafeMethodCall(ast: cdAst.SafeMethodCall) {
return visit(this, ast.receiver) || ast;
},
visitSafePropertyRead(ast: cdAst.SafePropertyRead) { visitSafePropertyRead(ast: cdAst.SafePropertyRead) {
return visit(this, ast.receiver) || ast; return visit(this, ast.receiver) || ast;
} }
@ -726,29 +777,66 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
return ast.some(ast => visit(visitor, ast)); return ast.some(ast => visit(visitor, ast));
}; };
return ast.visit({ return ast.visit({
visitBinary(ast: cdAst.Binary): visitBinary(ast: cdAst.Binary): boolean {
boolean{return visit(this, ast.left) || visit(this, ast.right);}, return visit(this, ast.left) || visit(this, ast.right);
visitChain(ast: cdAst.Chain) { return false; }, },
visitConditional(ast: cdAst.Conditional): visitChain(ast: cdAst.Chain) {
boolean{return visit(this, ast.condition) || visit(this, ast.trueExp) || return false;
visit(this, ast.falseExp);}, },
visitFunctionCall(ast: cdAst.FunctionCall) { return true; }, visitConditional(ast: cdAst.Conditional): boolean {
visitImplicitReceiver(ast: cdAst.ImplicitReceiver) { return false; }, return visit(this, ast.condition) || visit(this, ast.trueExp) || visit(this, ast.falseExp);
visitInterpolation(ast: cdAst.Interpolation) { return visitSome(this, ast.expressions); }, },
visitKeyedRead(ast: cdAst.KeyedRead) { return false; }, visitFunctionCall(ast: cdAst.FunctionCall) {
visitKeyedWrite(ast: cdAst.KeyedWrite) { return false; }, return true;
visitLiteralArray(ast: cdAst.LiteralArray) { return true; }, },
visitLiteralMap(ast: cdAst.LiteralMap) { return true; }, visitImplicitReceiver(ast: cdAst.ImplicitReceiver) {
visitLiteralPrimitive(ast: cdAst.LiteralPrimitive) { return false; }, return false;
visitMethodCall(ast: cdAst.MethodCall) { return true; }, },
visitPipe(ast: cdAst.BindingPipe) { return true; }, visitInterpolation(ast: cdAst.Interpolation) {
visitPrefixNot(ast: cdAst.PrefixNot) { return visit(this, ast.expression); }, return visitSome(this, ast.expressions);
visitNonNullAssert(ast: cdAst.PrefixNot) { return visit(this, ast.expression); }, },
visitPropertyRead(ast: cdAst.PropertyRead) { return false; }, visitKeyedRead(ast: cdAst.KeyedRead) {
visitPropertyWrite(ast: cdAst.PropertyWrite) { return false; }, return false;
visitQuote(ast: cdAst.Quote) { return false; }, },
visitSafeMethodCall(ast: cdAst.SafeMethodCall) { return true; }, visitKeyedWrite(ast: cdAst.KeyedWrite) {
visitSafePropertyRead(ast: cdAst.SafePropertyRead) { return false; } return false;
},
visitLiteralArray(ast: cdAst.LiteralArray) {
return true;
},
visitLiteralMap(ast: cdAst.LiteralMap) {
return true;
},
visitLiteralPrimitive(ast: cdAst.LiteralPrimitive) {
return false;
},
visitMethodCall(ast: cdAst.MethodCall) {
return true;
},
visitPipe(ast: cdAst.BindingPipe) {
return true;
},
visitPrefixNot(ast: cdAst.PrefixNot) {
return visit(this, ast.expression);
},
visitNonNullAssert(ast: cdAst.PrefixNot) {
return visit(this, ast.expression);
},
visitPropertyRead(ast: cdAst.PropertyRead) {
return false;
},
visitPropertyWrite(ast: cdAst.PropertyWrite) {
return false;
},
visitQuote(ast: cdAst.Quote) {
return false;
},
visitSafeMethodCall(ast: cdAst.SafeMethodCall) {
return true;
},
visitSafePropertyRead(ast: cdAst.SafePropertyRead) {
return false;
}
}); });
} }

View File

@ -20,9 +20,14 @@ export class CompilerConfig {
public preserveWhitespaces: boolean; public preserveWhitespaces: boolean;
public strictInjectionParameters: boolean; public strictInjectionParameters: boolean;
constructor( constructor({
{defaultEncapsulation = ViewEncapsulation.Emulated, useJit = true, jitDevMode = false, defaultEncapsulation = ViewEncapsulation.Emulated,
missingTranslation = null, preserveWhitespaces, strictInjectionParameters}: { useJit = true,
jitDevMode = false,
missingTranslation = null,
preserveWhitespaces,
strictInjectionParameters
}: {
defaultEncapsulation?: ViewEncapsulation, defaultEncapsulation?: ViewEncapsulation,
useJit?: boolean, useJit?: boolean,
jitDevMode?: boolean, jitDevMode?: boolean,

View File

@ -7,7 +7,7 @@
*/ */
import * as o from './output/output_ast'; import * as o from './output/output_ast';
import {OutputContext, error} from './util'; import {error, OutputContext} from './util';
const CONSTANT_PREFIX = '_c'; const CONSTANT_PREFIX = '_c';
@ -21,7 +21,12 @@ const CONSTANT_PREFIX = '_c';
*/ */
const UNKNOWN_VALUE_KEY = o.variable('<unknown>'); const UNKNOWN_VALUE_KEY = o.variable('<unknown>');
export const enum DefinitionKind {Injector, Directive, Component, Pipe} export const enum DefinitionKind {
Injector,
Directive,
Component,
Pipe
}
/** /**
* Context to use when producing a key. * Context to use when producing a key.
@ -64,7 +69,9 @@ class FixupExpression extends o.Expression {
return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved); return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved);
} }
isConstant() { return true; } isConstant() {
return true;
}
fixup(expression: o.Expression) { fixup(expression: o.Expression) {
this.resolved = expression; this.resolved = expression;
@ -190,7 +197,9 @@ export class ConstantPool {
* a digit so the prefix should be a constant string (not based on user input) and * a digit so the prefix should be a constant string (not based on user input) and
* must not end in a digit. * must not end in a digit.
*/ */
uniqueName(prefix: string): string { return `${prefix}${this.nextNameIndex++}`; } uniqueName(prefix: string): string {
return `${prefix}${this.nextNameIndex++}`;
}
private definitionsOf(kind: DefinitionKind): Map<any, FixupExpression> { private definitionsOf(kind: DefinitionKind): Map<any, FixupExpression> {
switch (kind) { switch (kind) {
@ -222,7 +231,9 @@ export class ConstantPool {
return '<unknown>'; return '<unknown>';
} }
private freshName(): string { return this.uniqueName(CONSTANT_PREFIX); } private freshName(): string {
return this.uniqueName(CONSTANT_PREFIX);
}
private keyOf(expression: o.Expression) { private keyOf(expression: o.Expression) {
return expression.visitExpression(new KeyVisitor(), KEY_CONTEXT); return expression.visitExpression(new KeyVisitor(), KEY_CONTEXT);
@ -259,7 +270,9 @@ class KeyVisitor implements o.ExpressionVisitor {
`EX:${ast.value.runtime.name}`; `EX:${ast.value.runtime.name}`;
} }
visitReadVarExpr(node: o.ReadVarExpr) { return `VAR:${node.name}`; } visitReadVarExpr(node: o.ReadVarExpr) {
return `VAR:${node.name}`;
}
visitTypeofExpr(node: o.TypeofExpr, context: any): string { visitTypeofExpr(node: o.TypeofExpr, context: any): string {
return `TYPEOF:${node.expr.visitExpression(this, context)}`; return `TYPEOF:${node.expr.visitExpression(this, context)}`;

View File

@ -14,12 +14,16 @@
import {CssSelector} from './selector'; import {CssSelector} from './selector';
export interface Inject { token: any; } export interface Inject {
token: any;
}
export const createInject = makeMetadataFactory<Inject>('Inject', (token: any) => ({token})); export const createInject = makeMetadataFactory<Inject>('Inject', (token: any) => ({token}));
export const createInjectionToken = makeMetadataFactory<object>( export const createInjectionToken = makeMetadataFactory<object>(
'InjectionToken', (desc: string) => ({_desc: desc, ɵprov: undefined})); 'InjectionToken', (desc: string) => ({_desc: desc, ɵprov: undefined}));
export interface Attribute { attributeName?: string; } export interface Attribute {
attributeName?: string;
}
export const createAttribute = export const createAttribute =
makeMetadataFactory<Attribute>('Attribute', (attributeName?: string) => ({attributeName})); makeMetadataFactory<Attribute>('Attribute', (attributeName?: string) => ({attributeName}));
@ -37,13 +41,16 @@ export const createContentChildren = makeMetadataFactory<Query>(
(selector?: any, data: any = {}) => (selector?: any, data: any = {}) =>
({selector, first: false, isViewQuery: false, descendants: false, ...data})); ({selector, first: false, isViewQuery: false, descendants: false, ...data}));
export const createContentChild = makeMetadataFactory<Query>( export const createContentChild = makeMetadataFactory<Query>(
'ContentChild', (selector?: any, data: any = {}) => 'ContentChild',
(selector?: any, data: any = {}) =>
({selector, first: true, isViewQuery: false, descendants: true, ...data})); ({selector, first: true, isViewQuery: false, descendants: true, ...data}));
export const createViewChildren = makeMetadataFactory<Query>( export const createViewChildren = makeMetadataFactory<Query>(
'ViewChildren', (selector?: any, data: any = {}) => 'ViewChildren',
(selector?: any, data: any = {}) =>
({selector, first: false, isViewQuery: true, descendants: true, ...data})); ({selector, first: false, isViewQuery: true, descendants: true, ...data}));
export const createViewChild = makeMetadataFactory<Query>( export const createViewChild = makeMetadataFactory<Query>(
'ViewChild', (selector: any, data: any) => 'ViewChild',
(selector: any, data: any) =>
({selector, first: true, isViewQuery: true, descendants: true, ...data})); ({selector, first: true, isViewQuery: true, descendants: true, ...data}));
export interface Directive { export interface Directive {
@ -94,15 +101,21 @@ export interface Pipe {
} }
export const createPipe = makeMetadataFactory<Pipe>('Pipe', (p: Pipe) => ({pure: true, ...p})); export const createPipe = makeMetadataFactory<Pipe>('Pipe', (p: Pipe) => ({pure: true, ...p}));
export interface Input { bindingPropertyName?: string; } export interface Input {
bindingPropertyName?: string;
}
export const createInput = export const createInput =
makeMetadataFactory<Input>('Input', (bindingPropertyName?: string) => ({bindingPropertyName})); makeMetadataFactory<Input>('Input', (bindingPropertyName?: string) => ({bindingPropertyName}));
export interface Output { bindingPropertyName?: string; } export interface Output {
bindingPropertyName?: string;
}
export const createOutput = makeMetadataFactory<Output>( export const createOutput = makeMetadataFactory<Output>(
'Output', (bindingPropertyName?: string) => ({bindingPropertyName})); 'Output', (bindingPropertyName?: string) => ({bindingPropertyName}));
export interface HostBinding { hostPropertyName?: string; } export interface HostBinding {
hostPropertyName?: string;
}
export const createHostBinding = makeMetadataFactory<HostBinding>( export const createHostBinding = makeMetadataFactory<HostBinding>(
'HostBinding', (hostPropertyName?: string) => ({hostPropertyName})); 'HostBinding', (hostPropertyName?: string) => ({hostPropertyName}));
@ -140,7 +153,9 @@ export interface Injectable {
} }
export const createInjectable = export const createInjectable =
makeMetadataFactory('Injectable', (injectable: Injectable = {}) => injectable); makeMetadataFactory('Injectable', (injectable: Injectable = {}) => injectable);
export interface SchemaMetadata { name: string; } export interface SchemaMetadata {
name: string;
}
export const CUSTOM_ELEMENTS_SCHEMA: SchemaMetadata = { export const CUSTOM_ELEMENTS_SCHEMA: SchemaMetadata = {
name: 'custom-elements' name: 'custom-elements'
@ -155,7 +170,9 @@ export const createSelf = makeMetadataFactory('Self');
export const createSkipSelf = makeMetadataFactory('SkipSelf'); export const createSkipSelf = makeMetadataFactory('SkipSelf');
export const createHost = makeMetadataFactory('Host'); export const createHost = makeMetadataFactory('Host');
export interface Type extends Function { new (...args: any[]): any; } export interface Type extends Function {
new(...args: any[]): any;
}
export const Type = Function; export const Type = Function;
export enum SecurityContext { export enum SecurityContext {
@ -240,7 +257,10 @@ export const enum InjectFlags {
Optional = 1 << 3, Optional = 1 << 3,
} }
export const enum ArgumentType {Inline = 0, Dynamic = 1} export const enum ArgumentType {
Inline = 0,
Dynamic = 1
}
export const enum BindingFlags { export const enum BindingFlags {
TypeElementAttribute = 1 << 0, TypeElementAttribute = 1 << 0,
@ -255,7 +275,10 @@ export const enum BindingFlags {
Types = TypeElementAttribute | TypeElementClass | TypeElementStyle | TypeProperty Types = TypeElementAttribute | TypeElementClass | TypeElementStyle | TypeProperty
} }
export const enum QueryBindingType {First = 0, All = 1} export const enum QueryBindingType {
First = 0,
All = 1
}
export const enum QueryValueType { export const enum QueryValueType {
ElementRef = 0, ElementRef = 0,

View File

@ -46,8 +46,12 @@ export interface CssAstVisitor {
export abstract class CssAst { export abstract class CssAst {
constructor(public location: ParseSourceSpan) {} constructor(public location: ParseSourceSpan) {}
get start(): ParseLocation { return this.location.start; } get start(): ParseLocation {
get end(): ParseLocation { return this.location.end; } return this.location.start;
}
get end(): ParseLocation {
return this.location.end;
}
abstract visit(visitor: CssAstVisitor, context?: any): any; abstract visit(visitor: CssAstVisitor, context?: any): any;
} }
@ -55,11 +59,15 @@ export class CssStyleValueAst extends CssAst {
constructor(location: ParseSourceSpan, public tokens: CssToken[], public strValue: string) { constructor(location: ParseSourceSpan, public tokens: CssToken[], public strValue: string) {
super(location); super(location);
} }
visit(visitor: CssAstVisitor, context?: any): any { return visitor.visitCssValue(this); } visit(visitor: CssAstVisitor, context?: any): any {
return visitor.visitCssValue(this);
}
} }
export abstract class CssRuleAst extends CssAst { export abstract class CssRuleAst extends CssAst {
constructor(location: ParseSourceSpan) { super(location); } constructor(location: ParseSourceSpan) {
super(location);
}
} }
export class CssBlockRuleAst extends CssRuleAst { export class CssBlockRuleAst extends CssRuleAst {
@ -158,7 +166,9 @@ export class CssDefinitionAst extends CssAst {
} }
export abstract class CssSelectorPartAst extends CssAst { export abstract class CssSelectorPartAst extends CssAst {
constructor(location: ParseSourceSpan) { super(location); } constructor(location: ParseSourceSpan) {
super(location);
}
} }
export class CssSelectorAst extends CssSelectorPartAst { export class CssSelectorAst extends CssSelectorPartAst {
@ -195,8 +205,12 @@ export class CssPseudoSelectorAst extends CssSelectorPartAst {
} }
export class CssBlockAst extends CssAst { export class CssBlockAst extends CssAst {
constructor(location: ParseSourceSpan, public entries: CssAst[]) { super(location); } constructor(location: ParseSourceSpan, public entries: CssAst[]) {
visit(visitor: CssAstVisitor, context?: any): any { return visitor.visitCssBlock(this, context); } super(location);
}
visit(visitor: CssAstVisitor, context?: any): any {
return visitor.visitCssBlock(this, context);
}
} }
/* /*
@ -213,7 +227,9 @@ export class CssStylesBlockAst extends CssBlockAst {
} }
export class CssStyleSheetAst extends CssAst { export class CssStyleSheetAst extends CssAst {
constructor(location: ParseSourceSpan, public rules: CssAst[]) { super(location); } constructor(location: ParseSourceSpan, public rules: CssAst[]) {
super(location);
}
visit(visitor: CssAstVisitor, context?: any): any { visit(visitor: CssAstVisitor, context?: any): any {
return visitor.visitCssStyleSheet(this, context); return visitor.visitCssStyleSheet(this, context);
} }

View File

@ -135,7 +135,9 @@ export class CssScanner {
this.advance(); this.advance();
} }
getMode(): CssLexerMode { return this._currentMode; } getMode(): CssLexerMode {
return this._currentMode;
}
setMode(mode: CssLexerMode) { setMode(mode: CssLexerMode) {
if (this._currentMode != mode) { if (this._currentMode != mode) {
@ -236,7 +238,8 @@ export class CssScanner {
} }
error = cssScannerError( error = cssScannerError(
next, generateErrorMessage( next,
generateErrorMessage(
this.input, errorMessage, next.strValue, previousIndex, previousLine, this.input, errorMessage, next.strValue, previousIndex, previousLine,
previousColumn)); previousColumn));
} }

View File

@ -9,7 +9,7 @@
import * as chars from '../chars'; import * as chars from '../chars';
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, CssStylesBlockAst, CssStyleSheetAst, CssStyleValueAst, CssUnknownRuleAst, CssUnknownTokenListAst, mergeTokens} from './css_ast';
import {CssLexer, CssLexerMode, CssScanner, CssToken, CssTokenType, generateErrorMessage, getRawMessage, isNewline} from './css_lexer'; import {CssLexer, CssLexerMode, CssScanner, CssToken, CssTokenType, generateErrorMessage, getRawMessage, isNewline} from './css_lexer';
const SPACE_OPERATOR = ' '; const SPACE_OPERATOR = ' ';
@ -129,7 +129,9 @@ export class CssParser {
} }
/** @internal */ /** @internal */
_getSourceContent(): string { return this._scanner != null ? this._scanner.input : ''; } _getSourceContent(): string {
return this._scanner != null ? this._scanner.input : '';
}
/** @internal */ /** @internal */
_extractSourceContent(start: number, end: number): string { _extractSourceContent(start: number, end: number): string {
@ -310,11 +312,15 @@ export class CssParser {
token); token);
this._collectUntilDelim(delimiters | LBRACE_DELIM_FLAG | SEMICOLON_DELIM_FLAG) this._collectUntilDelim(delimiters | LBRACE_DELIM_FLAG | SEMICOLON_DELIM_FLAG)
.forEach((token) => { listOfTokens.push(token); }); .forEach((token) => {
listOfTokens.push(token);
});
if (this._scanner.peek == chars.$LBRACE) { if (this._scanner.peek == chars.$LBRACE) {
listOfTokens.push(this._consume(CssTokenType.Character, '{')); listOfTokens.push(this._consume(CssTokenType.Character, '{'));
this._collectUntilDelim(delimiters | RBRACE_DELIM_FLAG | LBRACE_DELIM_FLAG) this._collectUntilDelim(delimiters | RBRACE_DELIM_FLAG | LBRACE_DELIM_FLAG)
.forEach((token) => { listOfTokens.push(token); }); .forEach((token) => {
listOfTokens.push(token);
});
listOfTokens.push(this._consume(CssTokenType.Character, '}')); listOfTokens.push(this._consume(CssTokenType.Character, '}'));
} }
endToken = listOfTokens[listOfTokens.length - 1]; endToken = listOfTokens[listOfTokens.length - 1];
@ -339,7 +345,9 @@ export class CssParser {
const innerTokens: CssToken[] = []; const innerTokens: CssToken[] = [];
selectors.forEach((selector: CssSelectorAst) => { selectors.forEach((selector: CssSelectorAst) => {
selector.selectorParts.forEach((part: CssSimpleSelectorAst) => { selector.selectorParts.forEach((part: CssSimpleSelectorAst) => {
part.tokens.forEach((token: CssToken) => { innerTokens.push(token); }); part.tokens.forEach((token: CssToken) => {
innerTokens.push(token);
});
}); });
}); });
const endToken = innerTokens[innerTokens.length - 1]; const endToken = innerTokens[innerTokens.length - 1];
@ -387,7 +395,9 @@ export class CssParser {
} }
/** @internal */ /** @internal */
_getScannerIndex(): number { return this._scanner.index; } _getScannerIndex(): number {
return this._scanner.index;
}
/** @internal */ /** @internal */
_consume(type: CssTokenType, value: string|null = null): CssToken { _consume(type: CssTokenType, value: string|null = null): CssToken {
@ -576,7 +586,8 @@ export class CssParser {
hasAttributeError || this._scanner.getMode() == CssLexerMode.ATTRIBUTE_SELECTOR; hasAttributeError || this._scanner.getMode() == CssLexerMode.ATTRIBUTE_SELECTOR;
if (hasAttributeError) { if (hasAttributeError) {
this._error( this._error(
`Unbalanced CSS attribute selector at column ${previousToken.line}:${previousToken.column}`, `Unbalanced CSS attribute selector at column ${previousToken.line}:${
previousToken.column}`,
previousToken); previousToken);
} }
@ -841,7 +852,9 @@ export class CssParser {
const remainingTokens = this._collectUntilDelim( const remainingTokens = this._collectUntilDelim(
delimiters | COLON_DELIM_FLAG | SEMICOLON_DELIM_FLAG, CssTokenType.Identifier); delimiters | COLON_DELIM_FLAG | SEMICOLON_DELIM_FLAG, CssTokenType.Identifier);
if (remainingTokens.length > 0) { if (remainingTokens.length > 0) {
remainingTokens.forEach((token) => { propStr.push(token.strValue); }); remainingTokens.forEach((token) => {
propStr.push(token.strValue);
});
} }
endToken = prop = endToken = prop =
@ -899,5 +912,7 @@ export class CssParseError extends ParseError {
return new CssParseError(span, 'CSS Parse Error: ' + errMsg); return new CssParseError(span, 'CSS Parse Error: ' + errMsg);
} }
constructor(span: ParseSourceSpan, message: string) { super(span, message); } constructor(span: ParseSourceSpan, message: string) {
super(span, message);
}
} }

View File

@ -17,7 +17,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 {SyncAsync, isDefined, stringify, syntaxError} from './util'; import {isDefined, stringify, SyncAsync, syntaxError} from './util';
export interface PrenormalizedTemplateMetadata { export interface PrenormalizedTemplateMetadata {
ngModuleType: any; ngModuleType: any;
@ -40,7 +40,9 @@ export class DirectiveNormalizer {
private _resourceLoader: ResourceLoader, private _urlResolver: UrlResolver, private _resourceLoader: ResourceLoader, private _urlResolver: UrlResolver,
private _htmlParser: HtmlParser, private _config: CompilerConfig) {} private _htmlParser: HtmlParser, private _config: CompilerConfig) {}
clearCache(): void { this._resourceLoaderCache.clear(); } clearCache(): void {
this._resourceLoaderCache.clear();
}
clearCacheFor(normalizedDirective: CompileDirectiveMetadata): void { clearCacheFor(normalizedDirective: CompileDirectiveMetadata): void {
if (!normalizedDirective.isComponent) { if (!normalizedDirective.isComponent) {
@ -48,8 +50,9 @@ export class DirectiveNormalizer {
} }
const template = normalizedDirective.template !; const template = normalizedDirective.template !;
this._resourceLoaderCache.delete(template.templateUrl!); this._resourceLoaderCache.delete(template.templateUrl!);
template.externalStylesheets.forEach( template.externalStylesheets.forEach((stylesheet) => {
(stylesheet) => { this._resourceLoaderCache.delete(stylesheet.moduleUrl !); }); this._resourceLoaderCache.delete(stylesheet.moduleUrl!);
});
} }
private _fetch(url: string): SyncAsync<string> { private _fetch(url: string): SyncAsync<string> {
@ -65,17 +68,18 @@ export class DirectiveNormalizer {
SyncAsync<CompileTemplateMetadata> { SyncAsync<CompileTemplateMetadata> {
if (isDefined(prenormData.template)) { if (isDefined(prenormData.template)) {
if (isDefined(prenormData.templateUrl)) { if (isDefined(prenormData.templateUrl)) {
throw syntaxError( throw syntaxError(`'${
`'${stringify(prenormData.componentType)}' component cannot define both template and templateUrl`); stringify(prenormData
.componentType)}' component cannot define both template and templateUrl`);
} }
if (typeof prenormData.template !== 'string') { if (typeof prenormData.template !== 'string') {
throw syntaxError( throw syntaxError(`The template specified for component ${
`The template specified for component ${stringify(prenormData.componentType)} is not a string`); stringify(prenormData.componentType)} is not a string`);
} }
} else if (isDefined(prenormData.templateUrl)) { } else if (isDefined(prenormData.templateUrl)) {
if (typeof prenormData.templateUrl !== 'string') { if (typeof prenormData.templateUrl !== 'string') {
throw syntaxError( throw syntaxError(`The templateUrl specified for component ${
`The templateUrl specified for component ${stringify(prenormData.componentType)} is not a string`); stringify(prenormData.componentType)} is not a string`);
} }
} else { } else {
throw syntaxError( throw syntaxError(
@ -84,8 +88,8 @@ export class DirectiveNormalizer {
if (isDefined(prenormData.preserveWhitespaces) && if (isDefined(prenormData.preserveWhitespaces) &&
typeof prenormData.preserveWhitespaces !== 'boolean') { typeof prenormData.preserveWhitespaces !== 'boolean') {
throw syntaxError( throw syntaxError(`The preserveWhitespaces option for component ${
`The preserveWhitespaces option for component ${stringify(prenormData.componentType)} must be a boolean`); stringify(prenormData.componentType)} must be a boolean`);
} }
return SyncAsync.then( return SyncAsync.then(
@ -140,8 +144,12 @@ export class DirectiveNormalizer {
.styleUrls; .styleUrls;
return { return {
template, template,
templateUrl: templateAbsUrl, isInline, templateUrl: templateAbsUrl,
htmlAst: rootNodesAndErrors, styles, inlineStyleUrls, styleUrls, isInline,
htmlAst: rootNodesAndErrors,
styles,
inlineStyleUrls,
styleUrls,
ngContentSelectors: visitor.ngContentSelectors, ngContentSelectors: visitor.ngContentSelectors,
}; };
} }
@ -190,11 +198,14 @@ export class DirectiveNormalizer {
encapsulation, encapsulation,
template: preparsedTemplate.template, template: preparsedTemplate.template,
templateUrl: preparsedTemplate.templateUrl, templateUrl: preparsedTemplate.templateUrl,
htmlAst: preparsedTemplate.htmlAst, styles, styleUrls, htmlAst: preparsedTemplate.htmlAst,
styles,
styleUrls,
ngContentSelectors: preparsedTemplate.ngContentSelectors, ngContentSelectors: preparsedTemplate.ngContentSelectors,
animations: prenormData.animations, animations: prenormData.animations,
interpolation: prenormData.interpolation, interpolation: prenormData.interpolation,
isInline: preparsedTemplate.isInline, externalStylesheets, isInline: preparsedTemplate.isInline,
externalStylesheets,
preserveWhitespaces: preserveWhitespacesDefault( preserveWhitespaces: preserveWhitespacesDefault(
prenormData.preserveWhitespaces, this._config.preserveWhitespaces), prenormData.preserveWhitespaces, this._config.preserveWhitespaces),
}); });
@ -297,13 +308,21 @@ class TemplatePreparseVisitor implements html.Visitor {
return null; return null;
} }
visitExpansion(ast: html.Expansion, context: any): any { html.visitAll(this, ast.cases); } visitExpansion(ast: html.Expansion, context: any): any {
html.visitAll(this, ast.cases);
}
visitExpansionCase(ast: html.ExpansionCase, context: any): any { visitExpansionCase(ast: html.ExpansionCase, context: any): any {
html.visitAll(this, ast.expression); html.visitAll(this, ast.expression);
} }
visitComment(ast: html.Comment, context: any): any { return null; } visitComment(ast: html.Comment, context: any): any {
visitAttribute(ast: html.Attribute, context: any): any { return null; } return null;
visitText(ast: html.Text, context: any): any { return null; } }
visitAttribute(ast: html.Attribute, context: any): any {
return null;
}
visitText(ast: html.Text, context: any): any {
return null;
}
} }

View File

@ -7,7 +7,7 @@
*/ */
import {CompileReflector} from './compile_reflector'; import {CompileReflector} from './compile_reflector';
import {Component, Directive, Type, createComponent, createContentChild, createContentChildren, createDirective, createHostBinding, createHostListener, createInput, createOutput, createViewChild, createViewChildren} from './core'; import {Component, createComponent, createContentChild, createContentChildren, createDirective, createHostBinding, createHostListener, createInput, createOutput, createViewChild, createViewChildren, Directive, Type} from './core';
import {resolveForwardRef, splitAtColon, stringify} from './util'; import {resolveForwardRef, splitAtColon, stringify} from './util';
const QUERY_METADATA_IDENTIFIERS = [ const QUERY_METADATA_IDENTIFIERS = [
@ -109,7 +109,9 @@ export class DirectiveResolver {
return this._merge(dm, inputs, outputs, host, queries, guards, directiveType); return this._merge(dm, inputs, outputs, host, queries, guards, directiveType);
} }
private _extractPublicName(def: string) { return splitAtColon(def, [null !, def])[1].trim(); } private _extractPublicName(def: string) {
return splitAtColon(def, [null!, def])[1].trim();
}
private _dedupeBindings(bindings: string[]): string[] { private _dedupeBindings(bindings: string[]): string[] {
const names = new Set<string>(); const names = new Set<string>();
@ -168,7 +170,8 @@ export class DirectiveResolver {
host: mergedHost, host: mergedHost,
exportAs: directive.exportAs, exportAs: directive.exportAs,
queries: mergedQueries, queries: mergedQueries,
providers: directive.providers, guards providers: directive.providers,
guards
}); });
} }
} }

View File

@ -31,8 +31,12 @@ export class AST {
* Absolute location of the expression AST in a source code file. * Absolute location of the expression AST in a source code file.
*/ */
public sourceSpan: AbsoluteSourceSpan) {} public sourceSpan: AbsoluteSourceSpan) {}
visit(visitor: AstVisitor, context: any = null): any { return null; } visit(visitor: AstVisitor, context: any = null): any {
toString(): string { return 'AST'; } return null;
}
toString(): string {
return 'AST';
}
} }
/** /**
@ -54,8 +58,12 @@ export class Quote extends AST {
public uninterpretedExpression: string, public location: any) { public uninterpretedExpression: string, public location: any) {
super(span, sourceSpan); super(span, sourceSpan);
} }
visit(visitor: AstVisitor, context: any = null): any { return visitor.visitQuote(this, context); } visit(visitor: AstVisitor, context: any = null): any {
toString(): string { return 'Quote'; } return visitor.visitQuote(this, context);
}
toString(): string {
return 'Quote';
}
} }
export class EmptyExpr extends AST { export class EmptyExpr extends AST {
@ -77,7 +85,9 @@ export class Chain extends AST {
constructor(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public expressions: any[]) { constructor(span: ParseSpan, sourceSpan: AbsoluteSourceSpan, public expressions: any[]) {
super(span, sourceSpan); super(span, sourceSpan);
} }
visit(visitor: AstVisitor, context: any = null): any { return visitor.visitChain(this, context); } visit(visitor: AstVisitor, context: any = null): any {
return visitor.visitChain(this, context);
}
} }
export class Conditional extends AST { export class Conditional extends AST {
@ -148,7 +158,9 @@ export class BindingPipe extends AST {
public args: any[], public nameSpan: AbsoluteSourceSpan) { public args: any[], public nameSpan: AbsoluteSourceSpan) {
super(span, sourceSpan); super(span, sourceSpan);
} }
visit(visitor: AstVisitor, context: any = null): any { return visitor.visitPipe(this, context); } visit(visitor: AstVisitor, context: any = null): any {
return visitor.visitPipe(this, context);
}
} }
export class LiteralPrimitive extends AST { export class LiteralPrimitive extends AST {
@ -280,7 +292,9 @@ export class ASTWithSource extends AST {
} }
return this.ast.visit(visitor, context); return this.ast.visit(visitor, context);
} }
toString(): string { return `${this.source} in ${this.location}`; } toString(): string {
return `${this.source} in ${this.location}`;
}
} }
/** /**
@ -379,7 +393,9 @@ export class RecursiveAstVisitor implements AstVisitor {
this.visit(ast.left, context); this.visit(ast.left, context);
this.visit(ast.right, context); this.visit(ast.right, context);
} }
visitChain(ast: Chain, context: any): any { this.visitAll(ast.expressions, context); } visitChain(ast: Chain, context: any): any {
this.visitAll(ast.expressions, context);
}
visitConditional(ast: Conditional, context: any): any { visitConditional(ast: Conditional, context: any): any {
this.visit(ast.condition, context); this.visit(ast.condition, context);
this.visit(ast.trueExp, context); this.visit(ast.trueExp, context);
@ -411,15 +427,23 @@ export class RecursiveAstVisitor implements AstVisitor {
visitLiteralArray(ast: LiteralArray, context: any): any { visitLiteralArray(ast: LiteralArray, context: any): any {
this.visitAll(ast.expressions, context); this.visitAll(ast.expressions, context);
} }
visitLiteralMap(ast: LiteralMap, context: any): any { this.visitAll(ast.values, context); } visitLiteralMap(ast: LiteralMap, context: any): any {
this.visitAll(ast.values, context);
}
visitLiteralPrimitive(ast: LiteralPrimitive, context: any): any {} visitLiteralPrimitive(ast: LiteralPrimitive, context: any): any {}
visitMethodCall(ast: MethodCall, context: any): any { visitMethodCall(ast: MethodCall, context: any): any {
this.visit(ast.receiver, context); this.visit(ast.receiver, context);
this.visitAll(ast.args, context); this.visitAll(ast.args, context);
} }
visitPrefixNot(ast: PrefixNot, context: any): any { this.visit(ast.expression, context); } visitPrefixNot(ast: PrefixNot, context: any): any {
visitNonNullAssert(ast: NonNullAssert, context: any): any { this.visit(ast.expression, context); } this.visit(ast.expression, context);
visitPropertyRead(ast: PropertyRead, context: any): any { this.visit(ast.receiver, context); } }
visitNonNullAssert(ast: NonNullAssert, context: any): any {
this.visit(ast.expression, context);
}
visitPropertyRead(ast: PropertyRead, context: any): any {
this.visit(ast.receiver, context);
}
visitPropertyWrite(ast: PropertyWrite, context: any): any { visitPropertyWrite(ast: PropertyWrite, context: any): any {
this.visit(ast.receiver, context); this.visit(ast.receiver, context);
this.visit(ast.value, context); this.visit(ast.value, context);
@ -441,7 +465,9 @@ export class RecursiveAstVisitor implements AstVisitor {
} }
export class AstTransformer implements AstVisitor { export class AstTransformer implements AstVisitor {
visitImplicitReceiver(ast: ImplicitReceiver, context: any): AST { return ast; } visitImplicitReceiver(ast: ImplicitReceiver, context: any): AST {
return ast;
}
visitInterpolation(ast: Interpolation, context: any): AST { visitInterpolation(ast: Interpolation, context: any): AST {
return new Interpolation(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions)); return new Interpolation(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions));
@ -542,7 +568,9 @@ export class AstTransformer implements AstVisitor {
// A transformer that only creates new nodes if the transformer makes a change or // A transformer that only creates new nodes if the transformer makes a change or
// a change is made a child node. // a change is made a child node.
export class AstMemoryEfficientTransformer implements AstVisitor { export class AstMemoryEfficientTransformer implements AstVisitor {
visitImplicitReceiver(ast: ImplicitReceiver, context: any): AST { return ast; } visitImplicitReceiver(ast: ImplicitReceiver, context: any): AST {
return ast;
}
visitInterpolation(ast: Interpolation, context: any): Interpolation { visitInterpolation(ast: Interpolation, context: any): Interpolation {
const expressions = this.visitAll(ast.expressions); const expressions = this.visitAll(ast.expressions);
@ -551,7 +579,9 @@ export class AstMemoryEfficientTransformer implements AstVisitor {
return ast; return ast;
} }
visitLiteralPrimitive(ast: LiteralPrimitive, context: any): AST { return ast; } visitLiteralPrimitive(ast: LiteralPrimitive, context: any): AST {
return ast;
}
visitPropertyRead(ast: PropertyRead, context: any): AST { visitPropertyRead(ast: PropertyRead, context: any): AST {
const receiver = ast.receiver.visit(this); const receiver = ast.receiver.visit(this);
@ -704,7 +734,9 @@ export class AstMemoryEfficientTransformer implements AstVisitor {
return ast; return ast;
} }
visitQuote(ast: Quote, context: any): AST { return ast; } visitQuote(ast: Quote, context: any): AST {
return ast;
}
} }
// Bindings // Bindings

View File

@ -42,37 +42,61 @@ export class Token {
return this.type == TokenType.Character && this.numValue == code; return this.type == TokenType.Character && this.numValue == code;
} }
isNumber(): boolean { return this.type == TokenType.Number; } isNumber(): boolean {
return this.type == TokenType.Number;
}
isString(): boolean { return this.type == TokenType.String; } isString(): boolean {
return this.type == TokenType.String;
}
isOperator(operator: string): boolean { isOperator(operator: string): boolean {
return this.type == TokenType.Operator && this.strValue == operator; return this.type == TokenType.Operator && this.strValue == operator;
} }
isIdentifier(): boolean { return this.type == TokenType.Identifier; } isIdentifier(): boolean {
return this.type == TokenType.Identifier;
}
isKeyword(): boolean { return this.type == TokenType.Keyword; } isKeyword(): boolean {
return this.type == TokenType.Keyword;
}
isKeywordLet(): boolean { return this.type == TokenType.Keyword && this.strValue == 'let'; } isKeywordLet(): boolean {
return this.type == TokenType.Keyword && this.strValue == 'let';
}
isKeywordAs(): boolean { return this.type == TokenType.Keyword && this.strValue == 'as'; } isKeywordAs(): boolean {
return this.type == TokenType.Keyword && this.strValue == 'as';
}
isKeywordNull(): boolean { return this.type == TokenType.Keyword && this.strValue == 'null'; } isKeywordNull(): boolean {
return this.type == TokenType.Keyword && this.strValue == 'null';
}
isKeywordUndefined(): boolean { isKeywordUndefined(): boolean {
return this.type == TokenType.Keyword && this.strValue == 'undefined'; return this.type == TokenType.Keyword && this.strValue == 'undefined';
} }
isKeywordTrue(): boolean { return this.type == TokenType.Keyword && this.strValue == 'true'; } isKeywordTrue(): boolean {
return this.type == TokenType.Keyword && this.strValue == 'true';
}
isKeywordFalse(): boolean { return this.type == TokenType.Keyword && this.strValue == 'false'; } isKeywordFalse(): boolean {
return this.type == TokenType.Keyword && this.strValue == 'false';
}
isKeywordThis(): boolean { return this.type == TokenType.Keyword && this.strValue == 'this'; } isKeywordThis(): boolean {
return this.type == TokenType.Keyword && this.strValue == 'this';
}
isError(): boolean { return this.type == TokenType.Error; } isError(): boolean {
return this.type == TokenType.Error;
}
toNumber(): number { return this.type == TokenType.Number ? this.numValue : -1; } toNumber(): number {
return this.type == TokenType.Number ? this.numValue : -1;
}
toString(): string|null { toString(): string|null {
switch (this.type) { switch (this.type) {

View File

@ -10,8 +10,8 @@ import * as chars from '../chars';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../ml_parser/interpolation_config'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../ml_parser/interpolation_config';
import {escapeRegExp} from '../util'; import {escapeRegExp} from '../util';
import {AST, ASTWithSource, AbsoluteSourceSpan, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, ExpressionBinding, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralMapKey, LiteralPrimitive, MethodCall, NonNullAssert, ParseSpan, ParserError, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, TemplateBinding, TemplateBindingIdentifier, VariableBinding} from './ast'; import {AbsoluteSourceSpan, AST, AstVisitor, ASTWithSource, Binary, BindingPipe, Chain, Conditional, EmptyExpr, ExpressionBinding, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralMapKey, LiteralPrimitive, MethodCall, NonNullAssert, ParserError, ParseSpan, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, TemplateBinding, TemplateBindingIdentifier, VariableBinding} from './ast';
import {EOF, Lexer, Token, TokenType, isIdentifier, isQuote} from './lexer'; import {EOF, isIdentifier, isQuote, Lexer, Token, TokenType} from './lexer';
export class SplitInterpolation { export class SplitInterpolation {
constructor(public strings: string[], public expressions: string[], public offsets: number[]) {} constructor(public strings: string[], public expressions: string[], public offsets: number[]) {}
@ -253,7 +253,8 @@ export class Parser {
const parts = input.split(regexp); const parts = input.split(regexp);
if (parts.length > 1) { if (parts.length > 1) {
this._reportError( this._reportError(
`Got interpolation (${interpolationConfig.start}${interpolationConfig.end}) where expression was expected`, `Got interpolation (${interpolationConfig.start}${
interpolationConfig.end}) where expression was expected`,
input, input,
`at column ${this._findInterpolationErrorColumn(parts, 1, interpolationConfig)} in`, `at column ${this._findInterpolationErrorColumn(parts, 1, interpolationConfig)} in`,
location); location);
@ -300,7 +301,9 @@ export class _ParseAST {
return i < this.tokens.length ? this.tokens[i] : EOF; return i < this.tokens.length ? this.tokens[i] : EOF;
} }
get next(): Token { return this.peek(0); } get next(): Token {
return this.peek(0);
}
get inputIndex(): number { get inputIndex(): number {
return (this.index < this.tokens.length) ? this.next.index + this.offset : return (this.index < this.tokens.length) ? this.next.index + this.offset :
@ -310,7 +313,9 @@ export class _ParseAST {
/** /**
* Returns the absolute offset of the start of the current token. * Returns the absolute offset of the start of the current token.
*/ */
get currentAbsoluteOffset(): number { return this.absoluteOffset + this.inputIndex; } get currentAbsoluteOffset(): number {
return this.absoluteOffset + this.inputIndex;
}
span(start: number) { span(start: number) {
// `end` is either the // `end` is either the
@ -329,7 +334,9 @@ export class _ParseAST {
return this.sourceSpanCache.get(serial)!; return this.sourceSpanCache.get(serial)!;
} }
advance() { this.index++; } advance() {
this.index++;
}
consumeOptionalCharacter(code: number): boolean { consumeOptionalCharacter(code: number): boolean {
if (this.next.isCharacter(code)) { if (this.next.isCharacter(code)) {
@ -340,8 +347,12 @@ export class _ParseAST {
} }
} }
peekKeywordLet(): boolean { return this.next.isKeywordLet(); } peekKeywordLet(): boolean {
peekKeywordAs(): boolean { return this.next.isKeywordAs(); } return this.next.isKeywordLet();
}
peekKeywordAs(): boolean {
return this.next.isKeywordAs();
}
expectCharacter(code: number) { expectCharacter(code: number) {
if (this.consumeOptionalCharacter(code)) return; if (this.consumeOptionalCharacter(code)) return;
@ -428,7 +439,9 @@ export class _ParseAST {
return result; return result;
} }
parseExpression(): AST { return this.parseConditional(); } parseExpression(): AST {
return this.parseConditional();
}
parseConditional(): AST { parseConditional(): AST {
const start = this.inputIndex; const start = this.inputIndex;
@ -984,8 +997,8 @@ export class _ParseAST {
(this.rbracesExpected <= 0 || !n.isCharacter(chars.$RBRACE)) && (this.rbracesExpected <= 0 || !n.isCharacter(chars.$RBRACE)) &&
(this.rbracketsExpected <= 0 || !n.isCharacter(chars.$RBRACKET))) { (this.rbracketsExpected <= 0 || !n.isCharacter(chars.$RBRACKET))) {
if (this.next.isError()) { if (this.next.isError()) {
this.errors.push(new ParserError( this.errors.push(
this.next.toString() !, this.input, this.locationText(), this.location)); new ParserError(this.next.toString()!, this.input, this.locationText(), this.location));
} }
this.advance(); this.advance();
n = this.next; n = this.next;
@ -1014,9 +1027,13 @@ class SimpleExpressionChecker implements AstVisitor {
visitFunctionCall(ast: FunctionCall, context: any) {} visitFunctionCall(ast: FunctionCall, context: any) {}
visitLiteralArray(ast: LiteralArray, context: any) { this.visitAll(ast.expressions); } visitLiteralArray(ast: LiteralArray, context: any) {
this.visitAll(ast.expressions);
}
visitLiteralMap(ast: LiteralMap, context: any) { this.visitAll(ast.values); } visitLiteralMap(ast: LiteralMap, context: any) {
this.visitAll(ast.values);
}
visitBinary(ast: Binary, context: any) {} visitBinary(ast: Binary, context: any) {}
@ -1026,13 +1043,17 @@ class SimpleExpressionChecker implements AstVisitor {
visitConditional(ast: Conditional, context: any) {} visitConditional(ast: Conditional, context: any) {}
visitPipe(ast: BindingPipe, context: any) { this.errors.push('pipes'); } visitPipe(ast: BindingPipe, context: any) {
this.errors.push('pipes');
}
visitKeyedRead(ast: KeyedRead, context: any) {} visitKeyedRead(ast: KeyedRead, context: any) {}
visitKeyedWrite(ast: KeyedWrite, context: any) {} visitKeyedWrite(ast: KeyedWrite, context: any) {}
visitAll(asts: any[]): any[] { return asts.map(node => node.visit(this)); } visitAll(asts: any[]): any[] {
return asts.map(node => node.visit(this));
}
visitChain(ast: Chain, context: any) {} visitChain(ast: Chain, context: any) {}
@ -1052,5 +1073,7 @@ class IvySimpleExpressionChecker extends SimpleExpressionChecker {
ast.right.visit(this); ast.right.visit(this);
} }
visitPrefixNot(ast: PrefixNot, context: any) { ast.expression.visit(this); } visitPrefixNot(ast: PrefixNot, context: any) {
ast.expression.visit(this);
}
} }

View File

@ -48,7 +48,9 @@ export function computeDecimalDigest(message: i18n.Message): string {
* @internal * @internal
*/ */
class _SerializerVisitor implements i18n.Visitor { class _SerializerVisitor implements i18n.Visitor {
visitText(text: i18n.Text, context: any): any { return text.value; } visitText(text: i18n.Text, context: any): any {
return text.value;
}
visitContainer(container: i18n.Container, context: any): any { visitContainer(container: i18n.Container, context: any): any {
return `[${container.children.map(child => child.visit(this)).join(', ')}]`; return `[${container.children.map(child => child.visit(this)).join(', ')}]`;
@ -63,7 +65,8 @@ class _SerializerVisitor implements i18n.Visitor {
visitTagPlaceholder(ph: i18n.TagPlaceholder, context: any): any { visitTagPlaceholder(ph: i18n.TagPlaceholder, context: any): any {
return ph.isVoid ? return ph.isVoid ?
`<ph tag name="${ph.startName}"/>` : `<ph tag name="${ph.startName}"/>` :
`<ph tag name="${ph.startName}">${ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`; `<ph tag name="${ph.startName}">${
ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`;
} }
visitPlaceholder(ph: i18n.Placeholder, context: any): any { visitPlaceholder(ph: i18n.Placeholder, context: any): any {

View File

@ -9,8 +9,9 @@
import * as html from '../ml_parser/ast'; import * as html from '../ml_parser/ast';
import {InterpolationConfig} from '../ml_parser/interpolation_config'; import {InterpolationConfig} from '../ml_parser/interpolation_config';
import {ParseTreeResult} from '../ml_parser/parser'; import {ParseTreeResult} from '../ml_parser/parser';
import * as i18n from './i18n_ast'; import * as i18n from './i18n_ast';
import {I18nMessageFactory, createI18nMessageFactory} from './i18n_parser'; import {createI18nMessageFactory, I18nMessageFactory} from './i18n_parser';
import {I18nError} from './parse_util'; import {I18nError} from './parse_util';
import {TranslationBundle} from './translation_bundle'; import {TranslationBundle} from './translation_bundle';
@ -193,8 +194,8 @@ class _Visitor implements html.Visitor {
i18nCommentsWarned = true; i18nCommentsWarned = true;
const details = comment.sourceSpan.details ? `, ${comment.sourceSpan.details}` : ''; const details = comment.sourceSpan.details ? `, ${comment.sourceSpan.details}` : '';
// TODO(ocombe): use a log service once there is a public one available // TODO(ocombe): use a log service once there is a public one available
console.warn( console.warn(`I18n comments are deprecated, use an <ng-container> element instead (${
`I18n comments are deprecated, use an <ng-container> element instead (${comment.sourceSpan.start}${details})`); comment.sourceSpan.start}${details})`);
} }
this._inI18nBlock = true; this._inI18nBlock = true;
this._blockStartDepth = this._depth; this._blockStartDepth = this._depth;
@ -400,12 +401,14 @@ class _Visitor implements html.Visitor {
} else { } else {
this._reportError( this._reportError(
el, el,
`Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`); `Unexpected translation for attribute "${attr.name}" (id="${
id || this._translations.digest(message)}")`);
} }
} else { } else {
this._reportError( this._reportError(
el, el,
`Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`); `Translation unavailable for attribute "${attr.name}" (id="${
id || this._translations.digest(message)}")`);
} }
} else { } else {
translatedAttributes.push(attr); translatedAttributes.push(attr);

View File

@ -57,14 +57,18 @@ export interface Node {
export class Text implements Node { export class Text implements Node {
constructor(public value: string, public sourceSpan: ParseSourceSpan) {} constructor(public value: string, public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context?: any): any { return visitor.visitText(this, context); } visit(visitor: Visitor, context?: any): any {
return visitor.visitText(this, context);
}
} }
// TODO(vicb): do we really need this node (vs an array) ? // TODO(vicb): do we really need this node (vs an array) ?
export class Container implements Node { export class Container implements Node {
constructor(public children: Node[], public sourceSpan: ParseSourceSpan) {} constructor(public children: Node[], public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context?: any): any { return visitor.visitContainer(this, context); } visit(visitor: Visitor, context?: any): any {
return visitor.visitContainer(this, context);
}
} }
export class Icu implements Node { export class Icu implements Node {
@ -74,7 +78,9 @@ export class Icu implements Node {
public expression: string, public type: string, public cases: {[k: string]: Node}, public expression: string, public type: string, public cases: {[k: string]: Node},
public sourceSpan: ParseSourceSpan) {} public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context?: any): any { return visitor.visitIcu(this, context); } visit(visitor: Visitor, context?: any): any {
return visitor.visitIcu(this, context);
}
} }
export class TagPlaceholder implements Node { export class TagPlaceholder implements Node {
@ -83,13 +89,17 @@ export class TagPlaceholder implements Node {
public closeName: string, public children: Node[], public isVoid: boolean, public closeName: string, public children: Node[], public isVoid: boolean,
public sourceSpan: ParseSourceSpan) {} public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context?: any): any { return visitor.visitTagPlaceholder(this, context); } visit(visitor: Visitor, context?: any): any {
return visitor.visitTagPlaceholder(this, context);
}
} }
export class Placeholder implements Node { export class Placeholder implements Node {
constructor(public value: string, public name: string, public sourceSpan: ParseSourceSpan) {} constructor(public value: string, public name: string, public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context?: any): any { return visitor.visitPlaceholder(this, context); } visit(visitor: Visitor, context?: any): any {
return visitor.visitPlaceholder(this, context);
}
} }
export class IcuPlaceholder implements Node { export class IcuPlaceholder implements Node {
@ -97,7 +107,9 @@ export class IcuPlaceholder implements Node {
previousMessage?: Message; previousMessage?: Message;
constructor(public value: Icu, public name: string, public sourceSpan: ParseSourceSpan) {} constructor(public value: Icu, public name: string, public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context?: any): any { return visitor.visitIcuPlaceholder(this, context); } visit(visitor: Visitor, context?: any): any {
return visitor.visitIcuPlaceholder(this, context);
}
} }
/** /**
@ -119,7 +131,9 @@ export interface Visitor {
// Clone the AST // Clone the AST
export class CloneVisitor implements Visitor { export class CloneVisitor implements Visitor {
visitText(text: Text, context?: any): Text { return new Text(text.value, text.sourceSpan); } visitText(text: Text, context?: any): Text {
return new Text(text.value, text.sourceSpan);
}
visitContainer(container: Container, context?: any): Container { visitContainer(container: Container, context?: any): Container {
const children = container.children.map(n => n.visit(this, context)); const children = container.children.map(n => n.visit(this, context));
@ -158,7 +172,9 @@ export class RecurseVisitor implements Visitor {
} }
visitIcu(icu: Icu, context?: any): any { visitIcu(icu: Icu, context?: any): any {
Object.keys(icu.cases).forEach(k => { icu.cases[k].visit(this); }); Object.keys(icu.cases).forEach(k => {
icu.cases[k].visit(this);
});
} }
visitTagPlaceholder(ph: TagPlaceholder, context?: any): any { visitTagPlaceholder(ph: TagPlaceholder, context?: any): any {

View File

@ -47,7 +47,9 @@ export class MessageBundle {
// Return the message in the internal format // Return the message in the internal format
// The public (serialized) format might be different, see the `write` method. // The public (serialized) format might be different, see the `write` method.
getMessages(): i18n.Message[] { return this._messages; } getMessages(): i18n.Message[] {
return this._messages;
}
write(serializer: Serializer, filterSources?: (path: string) => string): string { write(serializer: Serializer, filterSources?: (path: string) => string): string {
const messages: {[id: string]: i18n.Message} = {}; const messages: {[id: string]: i18n.Message} = {};

View File

@ -12,5 +12,7 @@ import {ParseError, ParseSourceSpan} from '../parse_util';
* An i18n error. * An i18n error.
*/ */
export class I18nError extends ParseError { export class I18nError extends ParseError {
constructor(span: ParseSourceSpan, msg: string) { super(span, msg); } constructor(span: ParseSourceSpan, msg: string) {
super(span, msg);
}
} }

View File

@ -106,7 +106,9 @@ export class PlaceholderRegistry {
return start + strAttrs + end; return start + strAttrs + end;
} }
private _hashClosingTag(tag: string): string { return this._hashTag(`/${tag}`, {}, false); } private _hashClosingTag(tag: string): string {
return this._hashTag(`/${tag}`, {}, false);
}
private _generateUniqueName(base: string): string { private _generateUniqueName(base: string): string {
const seen = this._placeHolderNameCounts.hasOwnProperty(base); const seen = this._placeHolderNameCounts.hasOwnProperty(base);

View File

@ -21,7 +21,9 @@ export abstract class Serializer {
// Creates a name mapper, see `PlaceholderMapper` // Creates a name mapper, see `PlaceholderMapper`
// Returning `null` means that no name mapping is used. // Returning `null` means that no name mapping is used.
createNameMapper(message: i18n.Message): PlaceholderMapper|null { return null; } createNameMapper(message: i18n.Message): PlaceholderMapper|null {
return null;
}
} }
/** /**
@ -61,7 +63,9 @@ export class SimplePlaceholderMapper extends i18n.RecurseVisitor implements Plac
null; null;
} }
visitText(text: i18n.Text, context?: any): any { return null; } visitText(text: i18n.Text, context?: any): any {
return null;
}
visitTagPlaceholder(ph: i18n.TagPlaceholder, context?: any): any { visitTagPlaceholder(ph: i18n.TagPlaceholder, context?: any): any {
this.visitPlaceholderName(ph.startName); this.visitPlaceholderName(ph.startName);
@ -69,7 +73,9 @@ export class SimplePlaceholderMapper extends i18n.RecurseVisitor implements Plac
this.visitPlaceholderName(ph.closeName); this.visitPlaceholderName(ph.closeName);
} }
visitPlaceholder(ph: i18n.Placeholder, context?: any): any { this.visitPlaceholderName(ph.name); } visitPlaceholder(ph: i18n.Placeholder, context?: any): any {
this.visitPlaceholderName(ph.name);
}
visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): any { visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): any {
this.visitPlaceholderName(ph.name); this.visitPlaceholderName(ph.name);

View File

@ -46,9 +46,9 @@ export class Xliff extends Serializer {
new xml.CR(10), new xml.CR(10),
new xml.Tag( new xml.Tag(
_CONTEXT_TAG, {'context-type': 'sourcefile'}, [new xml.Text(source.filePath)]), _CONTEXT_TAG, {'context-type': 'sourcefile'}, [new xml.Text(source.filePath)]),
new xml.CR(10), new xml.Tag( new xml.CR(10),
_CONTEXT_TAG, {'context-type': 'linenumber'}, new xml.Tag(_CONTEXT_TAG, {'context-type': 'linenumber'}, [new xml.Text(
[new xml.Text(`${source.startLine}`)]), `${source.startLine}`)]),
new xml.CR(8)); new xml.CR(8));
contextTags.push(new xml.CR(8), contextGroupTag); contextTags.push(new xml.CR(8), contextGroupTag);
}); });
@ -115,11 +115,15 @@ export class Xliff extends Serializer {
return {locale: locale!, i18nNodesByMsgId}; return {locale: locale!, i18nNodesByMsgId};
} }
digest(message: i18n.Message): string { return digest(message); } digest(message: i18n.Message): string {
return digest(message);
}
} }
class _WriteVisitor implements i18n.Visitor { class _WriteVisitor implements i18n.Visitor {
visitText(text: i18n.Text, context?: any): xml.Node[] { return [new xml.Text(text.value)]; } visitText(text: i18n.Text, context?: any): xml.Node[] {
return [new xml.Text(text.value)];
}
visitContainer(container: i18n.Container, context?: any): xml.Node[] { visitContainer(container: i18n.Container, context?: any): xml.Node[] {
const nodes: xml.Node[] = []; const nodes: xml.Node[] = [];
@ -161,8 +165,8 @@ class _WriteVisitor implements i18n.Visitor {
} }
visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): xml.Node[] { visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): xml.Node[] {
const equivText = const equivText = `{${ph.value.expression}, ${ph.value.type}, ${
`{${ph.value.expression}, ${ph.value.type}, ${Object.keys(ph.value.cases).map((value: string) => value + ' {...}').join(' ')}}`; Object.keys(ph.value.cases).map((value: string) => value + ' {...}').join(' ')}}`;
return [new xml.Tag(_PLACEHOLDER_TAG, {id: ph.name, 'equiv-text': equivText})]; return [new xml.Tag(_PLACEHOLDER_TAG, {id: ph.name, 'equiv-text': equivText})];
} }
@ -283,7 +287,9 @@ class XmlToI18n implements ml.Visitor {
}; };
} }
visitText(text: ml.Text, context: any) { return new i18n.Text(text.value, text.sourceSpan !); } visitText(text: ml.Text, context: any) {
return new i18n.Text(text.value, text.sourceSpan!);
}
visitElement(el: ml.Element, context: any): i18n.Placeholder|ml.Node[]|null { visitElement(el: ml.Element, context: any): i18n.Placeholder|ml.Node[]|null {
if (el.name === _PLACEHOLDER_TAG) { if (el.name === _PLACEHOLDER_TAG) {

View File

@ -54,8 +54,8 @@ export class Xliff2 extends Serializer {
message.sources.forEach((source: i18n.MessageSpan) => { message.sources.forEach((source: i18n.MessageSpan) => {
notes.children.push(new xml.CR(8), new xml.Tag('note', {category: 'location'}, [ notes.children.push(new xml.CR(8), new xml.Tag('note', {category: 'location'}, [
new xml.Text( new xml.Text(`${source.filePath}:${source.startLine}${
`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`) source.endLine !== source.startLine ? ',' + source.endLine : ''}`)
])); ]));
}); });
@ -108,14 +108,18 @@ export class Xliff2 extends Serializer {
return {locale: locale!, i18nNodesByMsgId}; return {locale: locale!, i18nNodesByMsgId};
} }
digest(message: i18n.Message): string { return decimalDigest(message); } digest(message: i18n.Message): string {
return decimalDigest(message);
}
} }
class _WriteVisitor implements i18n.Visitor { class _WriteVisitor implements i18n.Visitor {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
private _nextPlaceholderId!: number; private _nextPlaceholderId!: number;
visitText(text: i18n.Text, context?: any): xml.Node[] { return [new xml.Text(text.value)]; } visitText(text: i18n.Text, context?: any): xml.Node[] {
return [new xml.Text(text.value)];
}
visitContainer(container: i18n.Container, context?: any): xml.Node[] { visitContainer(container: i18n.Container, context?: any): xml.Node[] {
const nodes: xml.Node[] = []; const nodes: xml.Node[] = [];
@ -306,7 +310,9 @@ class XmlToI18n implements ml.Visitor {
}; };
} }
visitText(text: ml.Text, context: any) { return new i18n.Text(text.value, text.sourceSpan); } visitText(text: ml.Text, context: any) {
return new i18n.Text(text.value, text.sourceSpan);
}
visitElement(el: ml.Element, context: any): i18n.Node[]|null { visitElement(el: ml.Element, context: any): i18n.Node[]|null {
switch (el.name) { switch (el.name) {

View File

@ -57,10 +57,10 @@ export class Xmb extends Serializer {
let sourceTags: xml.Tag[] = []; let sourceTags: xml.Tag[] = [];
message.sources.forEach((source: i18n.MessageSpan) => { message.sources.forEach((source: i18n.MessageSpan) => {
sourceTags.push(new xml.Tag(_SOURCE_TAG, {}, [ sourceTags.push(new xml.Tag(
new xml.Text( _SOURCE_TAG, {},
`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`) [new xml.Text(`${source.filePath}:${source.startLine}${
])); source.endLine !== source.startLine ? ',' + source.endLine : ''}`)]));
}); });
rootNode.children.push( rootNode.children.push(
@ -85,7 +85,9 @@ export class Xmb extends Serializer {
throw new Error('Unsupported'); throw new Error('Unsupported');
} }
digest(message: i18n.Message): string { return digest(message); } digest(message: i18n.Message): string {
return digest(message);
}
createNameMapper(message: i18n.Message): PlaceholderMapper { createNameMapper(message: i18n.Message): PlaceholderMapper {
@ -94,7 +96,9 @@ export class Xmb extends Serializer {
} }
class _Visitor implements i18n.Visitor { class _Visitor implements i18n.Visitor {
visitText(text: i18n.Text, context?: any): xml.Node[] { return [new xml.Text(text.value)]; } visitText(text: i18n.Text, context?: any): xml.Node[] {
return [new xml.Text(text.value)];
}
visitContainer(container: i18n.Container, context: any): xml.Node[] { visitContainer(container: i18n.Container, context: any): xml.Node[] {
const nodes: xml.Node[] = []; const nodes: xml.Node[] = [];

View File

@ -25,7 +25,9 @@ class _Visitor implements IVisitor {
return `<${tag.name}${strAttrs}>${strChildren.join('')}</${tag.name}>`; return `<${tag.name}${strAttrs}>${strChildren.join('')}</${tag.name}>`;
} }
visitText(text: Text): string { return text.value; } visitText(text: Text): string {
return text.value;
}
visitDeclaration(decl: Declaration): string { visitDeclaration(decl: Declaration): string {
return `<?xml${this._serializeAttributes(decl.attrs)} ?>`; return `<?xml${this._serializeAttributes(decl.attrs)} ?>`;
@ -47,7 +49,9 @@ export function serialize(nodes: Node[]): string {
return nodes.map((node: Node): string => node.visit(_visitor)).join(''); return nodes.map((node: Node): string => node.visit(_visitor)).join('');
} }
export interface Node { visit(visitor: IVisitor): any; } export interface Node {
visit(visitor: IVisitor): any;
}
export class Declaration implements Node { export class Declaration implements Node {
public attrs: {[k: string]: string} = {}; public attrs: {[k: string]: string} = {};
@ -58,13 +62,17 @@ export class Declaration implements Node {
}); });
} }
visit(visitor: IVisitor): any { return visitor.visitDeclaration(this); } visit(visitor: IVisitor): any {
return visitor.visitDeclaration(this);
}
} }
export class Doctype implements Node { export class Doctype implements Node {
constructor(public rootTag: string, public dtd: string) {} constructor(public rootTag: string, public dtd: string) {}
visit(visitor: IVisitor): any { return visitor.visitDoctype(this); } visit(visitor: IVisitor): any {
return visitor.visitDoctype(this);
}
} }
export class Tag implements Node { export class Tag implements Node {
@ -78,18 +86,26 @@ export class Tag implements Node {
}); });
} }
visit(visitor: IVisitor): any { return visitor.visitTag(this); } visit(visitor: IVisitor): any {
return visitor.visitTag(this);
}
} }
export class Text implements Node { export class Text implements Node {
value: string; value: string;
constructor(unescapedValue: string) { this.value = escapeXml(unescapedValue); } constructor(unescapedValue: string) {
this.value = escapeXml(unescapedValue);
}
visit(visitor: IVisitor): any { return visitor.visitText(this); } visit(visitor: IVisitor): any {
return visitor.visitText(this);
}
} }
export class CR extends Text { export class CR extends Text {
constructor(ws: number = 0) { super(`\n${new Array(ws + 1).join(' ')}`); } constructor(ws: number = 0) {
super(`\n${new Array(ws + 1).join(' ')}`);
}
} }
const _ESCAPED_CHARS: [RegExp, string][] = [ const _ESCAPED_CHARS: [RegExp, string][] = [

View File

@ -19,7 +19,9 @@ const _TRANSLATION_TAG = 'translation';
const _PLACEHOLDER_TAG = 'ph'; const _PLACEHOLDER_TAG = 'ph';
export class Xtb extends Serializer { export class Xtb extends Serializer {
write(messages: i18n.Message[], locale: string|null): string { throw new Error('Unsupported'); } write(messages: i18n.Message[], locale: string|null): string {
throw new Error('Unsupported');
}
load(content: string, url: string): load(content: string, url: string):
{locale: string, i18nNodesByMsgId: {[msgId: string]: i18n.Node[]}} { {locale: string, i18nNodesByMsgId: {[msgId: string]: i18n.Node[]}} {
@ -52,7 +54,9 @@ export class Xtb extends Serializer {
return {locale: locale!, i18nNodesByMsgId}; return {locale: locale!, i18nNodesByMsgId};
} }
digest(message: i18n.Message): string { return digest(message); } digest(message: i18n.Message): string {
return digest(message);
}
createNameMapper(message: i18n.Message): PlaceholderMapper { createNameMapper(message: i18n.Message): PlaceholderMapper {
return new SimplePlaceholderMapper(message, toPublicName); return new SimplePlaceholderMapper(message, toPublicName);
@ -68,7 +72,9 @@ function createLazyProperty(messages: any, id: string, valueFn: () => any) {
Object.defineProperty(messages, id, {enumerable: true, value}); Object.defineProperty(messages, id, {enumerable: true, value});
return value; return value;
}, },
set: _ => { throw new Error('Could not overwrite an XTB translation'); }, set: _ => {
throw new Error('Could not overwrite an XTB translation');
},
}); });
} }
@ -172,7 +178,9 @@ class XmlToI18n implements ml.Visitor {
}; };
} }
visitText(text: ml.Text, context: any) { return new i18n.Text(text.value, text.sourceSpan !); } visitText(text: ml.Text, context: any) {
return new i18n.Text(text.value, text.sourceSpan!);
}
visitExpansion(icu: ml.Expansion, context: any) { visitExpansion(icu: ml.Expansion, context: any) {
const caseMap: {[value: string]: i18n.Node} = {}; const caseMap: {[value: string]: i18n.Node} = {};

View File

@ -56,7 +56,9 @@ export class TranslationBundle {
return html.nodes; return html.nodes;
} }
has(srcMsg: i18n.Message): boolean { return this.digest(srcMsg) in this._i18nNodesByMsgId; } has(srcMsg: i18n.Message): boolean {
return this.digest(srcMsg) in this._i18nNodesByMsgId;
}
} }
class I18nToHtmlVisitor implements i18n.Visitor { class I18nToHtmlVisitor implements i18n.Visitor {

View File

@ -8,8 +8,8 @@
import {Identifiers} from './identifiers'; import {Identifiers} from './identifiers';
import * as o from './output/output_ast'; import * as o from './output/output_ast';
import {R3DependencyMetadata, R3FactoryDelegateType, R3FactoryMetadata, R3FactoryTarget, compileFactoryFunction} from './render3/r3_factory'; import {compileFactoryFunction, R3DependencyMetadata, R3FactoryDelegateType, R3FactoryMetadata, R3FactoryTarget} from './render3/r3_factory';
import {R3Reference, mapToMapExpression, typeWithParameters} from './render3/util'; import {mapToMapExpression, R3Reference, typeWithParameters} from './render3/util';
export interface InjectableDef { export interface InjectableDef {
expression: o.Expression; expression: o.Expression;

View File

@ -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 {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeSummary, CompileProviderMetadata, CompileStylesheetMetadata, CompileTypeSummary, ProviderMeta, ProxyClass, identifierName, ngModuleJitUrl, sharedStylesheetJitUrl, templateJitUrl, templateSourceUrl} from '../compile_metadata'; import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeSummary, CompileProviderMetadata, CompileStylesheetMetadata, CompileTypeSummary, identifierName, ngModuleJitUrl, ProviderMeta, ProxyClass, sharedStylesheetJitUrl, templateJitUrl, templateSourceUrl} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector'; import {CompileReflector} from '../compile_reflector';
import {CompilerConfig} from '../config'; import {CompilerConfig} from '../config';
import {ConstantPool} from '../constant_pool'; import {ConstantPool} from '../constant_pool';
@ -20,7 +20,7 @@ import {CompiledStylesheet, StyleCompiler} from '../style_compiler';
import {SummaryResolver} from '../summary_resolver'; import {SummaryResolver} from '../summary_resolver';
import {TemplateAst} from '../template_parser/template_ast'; import {TemplateAst} from '../template_parser/template_ast';
import {TemplateParser} from '../template_parser/template_parser'; import {TemplateParser} from '../template_parser/template_parser';
import {Console, OutputContext, SyncAsync, stringify} from '../util'; import {Console, OutputContext, stringify, SyncAsync} from '../util';
import {ViewCompiler} from '../view_compiler/view_compiler'; import {ViewCompiler} from '../view_compiler/view_compiler';
export interface ModuleWithComponentFactories { export interface ModuleWithComponentFactories {
@ -97,7 +97,9 @@ export class JitCompiler {
} }
} }
hasAotSummary(ref: Type) { return !!this._summaryResolver.resolveSummary(ref); } hasAotSummary(ref: Type) {
return !!this._summaryResolver.resolveSummary(ref);
}
private _filterJitIdentifiers(ids: CompileIdentifierMetadata[]): any[] { private _filterJitIdentifiers(ids: CompileIdentifierMetadata[]): any[] {
return ids.map(mod => mod.reference).filter((ref) => !this.hasAotSummary(ref)); return ids.map(mod => mod.reference).filter((ref) => !this.hasAotSummary(ref));
@ -227,8 +229,9 @@ export class JitCompiler {
private _createCompiledHostTemplate(compType: Type, ngModule: CompileNgModuleMetadata): private _createCompiledHostTemplate(compType: Type, ngModule: CompileNgModuleMetadata):
CompiledTemplate { CompiledTemplate {
if (!ngModule) { if (!ngModule) {
throw new Error( throw new Error(`Component ${
`Component ${stringify(compType)} is not part of any NgModule or the module has not been imported into your module.`); stringify(
compType)} is not part of any NgModule or the module has not been imported into your module.`);
} }
let compiledTemplate = this._compiledHostTemplateCache.get(compType); let compiledTemplate = this._compiledHostTemplateCache.get(compType);
if (!compiledTemplate) { if (!compiledTemplate) {

View File

@ -16,13 +16,13 @@ import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './ml_parser/int
import {DeclareVarStmt, Expression, LiteralExpr, Statement, StmtModifier, WrappedNodeExpr} from './output/output_ast'; import {DeclareVarStmt, Expression, LiteralExpr, Statement, StmtModifier, WrappedNodeExpr} from './output/output_ast';
import {JitEvaluator} from './output/output_jit'; import {JitEvaluator} from './output/output_jit';
import {ParseError, ParseSourceSpan, r3JitTypeSourceSpan} from './parse_util'; import {ParseError, ParseSourceSpan, r3JitTypeSourceSpan} from './parse_util';
import {R3DependencyMetadata, R3FactoryTarget, R3ResolvedDependencyType, compileFactoryFunction} from './render3/r3_factory'; import {compileFactoryFunction, R3DependencyMetadata, R3FactoryTarget, R3ResolvedDependencyType} from './render3/r3_factory';
import {R3JitReflector} from './render3/r3_jit'; import {R3JitReflector} from './render3/r3_jit';
import {R3InjectorMetadata, R3NgModuleMetadata, compileInjector, compileNgModule} from './render3/r3_module_compiler'; import {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler';
import {R3PipeMetadata, compilePipeFromMetadata} from './render3/r3_pipe_compiler'; import {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler';
import {R3Reference} from './render3/util'; import {R3Reference} from './render3/util';
import {R3DirectiveMetadata, R3QueryMetadata} from './render3/view/api'; import {R3DirectiveMetadata, R3QueryMetadata} from './render3/view/api';
import {ParsedHostBindings, compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings, verifyHostBindings} from './render3/view/compiler'; import {compileComponentFromMetadata, compileDirectiveFromMetadata, ParsedHostBindings, parseHostBindings, verifyHostBindings} from './render3/view/compiler';
import {makeBindingParser, parseTemplate} from './render3/view/template'; import {makeBindingParser, parseTemplate} from './render3/view/template';
import {ResourceLoader} from './resource_loader'; import {ResourceLoader} from './resource_loader';
import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry'; import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry';
@ -305,8 +305,8 @@ function convertR3DependencyMetadata(facade: R3DependencyMetadataFacade): R3Depe
}; };
} }
function convertR3DependencyMetadataArray(facades: R3DependencyMetadataFacade[] | null | undefined): function convertR3DependencyMetadataArray(facades: R3DependencyMetadataFacade[]|null|
R3DependencyMetadata[]|null { undefined): R3DependencyMetadata[]|null {
return facades == null ? null : facades.map(convertR3DependencyMetadata); return facades == null ? null : facades.map(convertR3DependencyMetadata);
} }
@ -356,13 +356,11 @@ function isOutput(value: any): value is Output {
} }
function parseInputOutputs(values: string[]): StringMap { function parseInputOutputs(values: string[]): StringMap {
return values.reduce( return values.reduce((map, value) => {
(map, value) => {
const [field, property] = value.split(',').map(piece => piece.trim()); const [field, property] = value.split(',').map(piece => piece.trim());
map[field] = property || field; map[field] = property || field;
return map; return map;
}, }, {} as StringMap);
{} as StringMap);
} }
export function publishFacade(global: any) { export function publishFacade(global: any) {

View File

@ -12,7 +12,7 @@ import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions';
import * as cpl from './compile_metadata'; import * as cpl from './compile_metadata';
import {CompileReflector} from './compile_reflector'; import {CompileReflector} from './compile_reflector';
import {CompilerConfig} from './config'; import {CompilerConfig} from './config';
import {ChangeDetectionStrategy, Component, Directive, Injectable, ModuleWithProviders, Provider, Query, SchemaMetadata, Type, ViewEncapsulation, createAttribute, createComponent, createHost, createInject, createInjectable, createInjectionToken, createNgModule, createOptional, createSelf, createSkipSelf} from './core'; import {ChangeDetectionStrategy, Component, createAttribute, createComponent, createHost, createInject, createInjectable, createInjectionToken, createNgModule, createOptional, createSelf, createSkipSelf, Directive, Injectable, ModuleWithProviders, Provider, Query, SchemaMetadata, Type, ViewEncapsulation} from './core';
import {DirectiveNormalizer} from './directive_normalizer'; import {DirectiveNormalizer} from './directive_normalizer';
import {DirectiveResolver, findLast} from './directive_resolver'; import {DirectiveResolver, findLast} from './directive_resolver';
import {Identifiers} from './identifiers'; import {Identifiers} from './identifiers';
@ -23,7 +23,7 @@ import {PipeResolver} from './pipe_resolver';
import {ElementSchemaRegistry} from './schema/element_schema_registry'; import {ElementSchemaRegistry} from './schema/element_schema_registry';
import {CssSelector} from './selector'; import {CssSelector} from './selector';
import {SummaryResolver} from './summary_resolver'; import {SummaryResolver} from './summary_resolver';
import {Console, SyncAsync, ValueTransformer, isPromise, noUndefined, resolveForwardRef, stringify, syntaxError, visitValue} from './util'; import {Console, isPromise, noUndefined, resolveForwardRef, stringify, SyncAsync, syntaxError, ValueTransformer, visitValue} from './util';
export type ErrorCollector = (error: any, type?: any) => void; export type ErrorCollector = (error: any, type?: any) => void;
@ -55,7 +55,9 @@ export class CompileMetadataResolver {
private _staticSymbolCache: StaticSymbolCache, private _reflector: CompileReflector, private _staticSymbolCache: StaticSymbolCache, private _reflector: CompileReflector,
private _errorCollector?: ErrorCollector) {} private _errorCollector?: ErrorCollector) {}
getReflector(): CompileReflector { return this._reflector; } getReflector(): CompileReflector {
return this._reflector;
}
clearCacheFor(type: Type) { clearCacheFor(type: Type) {
const dirMeta = this._directiveCache.get(type); const dirMeta = this._directiveCache.get(type);
@ -209,8 +211,8 @@ export class CompileMetadataResolver {
guards: {}, guards: {},
viewQueries: [], viewQueries: [],
componentViewType: hostViewType, componentViewType: hostViewType,
rendererType: rendererType: {id: '__Host__', encapsulation: ViewEncapsulation.None, styles: [], data: {}} as
{id: '__Host__', encapsulation: ViewEncapsulation.None, styles: [], data: {}} as object, object,
entryComponents: [], entryComponents: [],
componentFactory: null componentFactory: null
}); });
@ -405,7 +407,8 @@ export class CompileMetadataResolver {
if (!dirMeta) { if (!dirMeta) {
this._reportError( this._reportError(
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);
} }
return dirMeta; return dirMeta;
@ -549,8 +552,9 @@ export class CompileMetadataResolver {
if (!alreadyCollecting) alreadyCollecting = new Set(); if (!alreadyCollecting) alreadyCollecting = new Set();
if (alreadyCollecting.has(importedModuleType)) { if (alreadyCollecting.has(importedModuleType)) {
this._reportError( this._reportError(
syntaxError( syntaxError(`${this._getTypeDescriptor(importedModuleType)} '${
`${this._getTypeDescriptor(importedModuleType)} '${stringifyType(importedType)}' is imported recursively by the module '${stringifyType(moduleType)}'.`), stringifyType(importedType)}' is imported recursively by the module '${
stringifyType(moduleType)}'.`),
moduleType); moduleType);
return; return;
} }
@ -560,8 +564,9 @@ export class CompileMetadataResolver {
alreadyCollecting.delete(importedModuleType); alreadyCollecting.delete(importedModuleType);
if (!importedModuleSummary) { if (!importedModuleSummary) {
this._reportError( this._reportError(
syntaxError( syntaxError(`Unexpected ${this._getTypeDescriptor(importedType)} '${
`Unexpected ${this._getTypeDescriptor(importedType)} '${stringifyType(importedType)}' imported by the module '${stringifyType(moduleType)}'. Please add a @NgModule annotation.`), stringifyType(importedType)}' imported by the module '${
stringifyType(moduleType)}'. Please add a @NgModule annotation.`),
moduleType); moduleType);
return; return;
} }
@ -569,7 +574,8 @@ export class CompileMetadataResolver {
} else { } else {
this._reportError( this._reportError(
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;
} }
@ -581,15 +587,17 @@ export class CompileMetadataResolver {
if (!isValidType(exportedType)) { if (!isValidType(exportedType)) {
this._reportError( this._reportError(
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;
} }
if (!alreadyCollecting) alreadyCollecting = new Set(); if (!alreadyCollecting) alreadyCollecting = new Set();
if (alreadyCollecting.has(exportedType)) { if (alreadyCollecting.has(exportedType)) {
this._reportError( this._reportError(
syntaxError( syntaxError(`${this._getTypeDescriptor(exportedType)} '${
`${this._getTypeDescriptor(exportedType)} '${stringify(exportedType)}' is exported recursively by the module '${stringifyType(moduleType)}'`), stringify(exportedType)}' is exported recursively by the module '${
stringifyType(moduleType)}'`),
moduleType); moduleType);
return; return;
} }
@ -612,7 +620,8 @@ export class CompileMetadataResolver {
if (!isValidType(declaredType)) { if (!isValidType(declaredType)) {
this._reportError( this._reportError(
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;
} }
@ -634,8 +643,10 @@ export class CompileMetadataResolver {
this._addTypeToModule(declaredType, moduleType); this._addTypeToModule(declaredType, moduleType);
} else { } else {
this._reportError( this._reportError(
syntaxError( syntaxError(`Unexpected ${this._getTypeDescriptor(declaredType)} '${
`Unexpected ${this._getTypeDescriptor(declaredType)} '${stringifyType(declaredType)}' declared by the module '${stringifyType(moduleType)}'. Please add a @Pipe/@Directive/@Component annotation.`), stringifyType(declaredType)}' declared by the module '${
stringifyType(
moduleType)}'. Please add a @Pipe/@Directive/@Component annotation.`),
moduleType); moduleType);
return; return;
} }
@ -653,8 +664,9 @@ export class CompileMetadataResolver {
transitiveModule.addExportedPipe(exportedId); transitiveModule.addExportedPipe(exportedId);
} else { } else {
this._reportError( this._reportError(
syntaxError( syntaxError(`Can't export ${this._getTypeDescriptor(exportedId.reference)} ${
`Can't export ${this._getTypeDescriptor(exportedId.reference)} ${stringifyType(exportedId.reference)} from ${stringifyType(moduleType)} as it was neither declared nor imported!`), stringifyType(exportedId.reference)} from ${
stringifyType(moduleType)} as it was neither declared nor imported!`),
moduleType); moduleType);
return; return;
} }
@ -677,8 +689,9 @@ export class CompileMetadataResolver {
flattenAndDedupeArray(meta.bootstrap).forEach(type => { flattenAndDedupeArray(meta.bootstrap).forEach(type => {
if (!isValidType(type)) { if (!isValidType(type)) {
this._reportError( this._reportError(
syntaxError( syntaxError(`Unexpected value '${
`Unexpected value '${stringifyType(type)}' used in the bootstrap property of module '${stringifyType(moduleType)}'`), stringifyType(type)}' used in the bootstrap property of module '${
stringifyType(moduleType)}'`),
moduleType); moduleType);
return; return;
} }
@ -753,9 +766,13 @@ export class CompileMetadataResolver {
if (oldModule && oldModule !== moduleType) { if (oldModule && oldModule !== moduleType) {
this._reportError( this._reportError(
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: ${
`Please consider moving ${stringifyType(type)} to a higher module that imports ${stringifyType(oldModule)} and ${stringifyType(moduleType)}. ` + 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)}.`), `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)}.`),
moduleType); moduleType);
return; return;
} }
@ -870,7 +887,8 @@ export class CompileMetadataResolver {
if (!pipeMeta) { if (!pipeMeta) {
this._reportError( this._reportError(
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);
} }
return pipeMeta || null; return pipeMeta || null;
@ -962,7 +980,6 @@ export class CompileMetadataResolver {
isOptional, isOptional,
token: this._getTokenMetadata(token) token: this._getTokenMetadata(token)
}; };
}); });
if (hasUnknownDeps) { if (hasUnknownDeps) {
@ -1027,8 +1044,11 @@ export class CompileMetadataResolver {
[]) [])
.join(', '); .join(', ');
this._reportError( this._reportError(
syntaxError( syntaxError(`Invalid ${
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`), debugInfo ?
debugInfo :
'provider'} - only instances of Provider and Type are allowed, got: [${
providersInfo}]`),
type); type);
return; return;
} }
@ -1045,8 +1065,8 @@ 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(syntaxError( this._reportError(syntaxError(`Invalid provider for ${
`Invalid provider for ${stringifyType(provider.provide)}. useClass cannot be ${provider.useClass}. 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).
2. Class was used before it was declared. Use forwardRef in this case.`)); 2. Class was used before it was declared. Use forwardRef in this case.`));
@ -1152,7 +1172,9 @@ export class CompileMetadataResolver {
return res; return res;
} }
private _queryVarBindings(selector: any): string[] { return selector.split(/\s*,\s*/); } private _queryVarBindings(selector: any): string[] {
return selector.split(/\s*,\s*/);
}
private _getQueryMetadata(q: Query, propertyName: string, typeOrFunc: Type|Function): private _getQueryMetadata(q: Query, propertyName: string, typeOrFunc: Type|Function):
cpl.CompileQueryMetadata { cpl.CompileQueryMetadata {
@ -1163,8 +1185,8 @@ export class CompileMetadataResolver {
} else { } else {
if (!q.selector) { if (!q.selector) {
this._reportError( this._reportError(
syntaxError( syntaxError(`Can't construct a query for the property "${propertyName}" of "${
`Can't construct a query for the property "${propertyName}" of "${stringifyType(typeOrFunc)}" since the query selector wasn't defined.`), stringifyType(typeOrFunc)}" since the query selector wasn't defined.`),
typeOrFunc); typeOrFunc);
selectors = []; selectors = [];
} else { } else {
@ -1175,7 +1197,8 @@ export class CompileMetadataResolver {
return { return {
selectors, selectors,
first: q.first, first: q.first,
descendants: q.descendants, propertyName, descendants: q.descendants,
propertyName,
read: q.read ? this._getTokenMetadata(q.read) : null!, read: q.read ? this._getTokenMetadata(q.read) : null!,
static: q.static static: q.static
}; };

View File

@ -24,7 +24,9 @@ export class Text extends NodeWithI18n {
constructor(public value: string, sourceSpan: ParseSourceSpan, i18n?: I18nMeta) { constructor(public value: string, sourceSpan: ParseSourceSpan, i18n?: I18nMeta) {
super(sourceSpan, i18n); super(sourceSpan, i18n);
} }
visit(visitor: Visitor, context: any): any { return visitor.visitText(this, context); } visit(visitor: Visitor, context: any): any {
return visitor.visitText(this, context);
}
} }
export class Expansion extends NodeWithI18n { export class Expansion extends NodeWithI18n {
@ -33,7 +35,9 @@ export class Expansion extends NodeWithI18n {
sourceSpan: ParseSourceSpan, public switchValueSourceSpan: ParseSourceSpan, i18n?: I18nMeta) { sourceSpan: ParseSourceSpan, public switchValueSourceSpan: ParseSourceSpan, i18n?: I18nMeta) {
super(sourceSpan, i18n); super(sourceSpan, i18n);
} }
visit(visitor: Visitor, context: any): any { return visitor.visitExpansion(this, context); } visit(visitor: Visitor, context: any): any {
return visitor.visitExpansion(this, context);
}
} }
export class ExpansionCase implements Node { export class ExpansionCase implements Node {
@ -41,7 +45,9 @@ export class ExpansionCase implements Node {
public value: string, public expression: Node[], public sourceSpan: ParseSourceSpan, public value: string, public expression: Node[], public sourceSpan: ParseSourceSpan,
public valueSourceSpan: ParseSourceSpan, public expSourceSpan: ParseSourceSpan) {} public valueSourceSpan: ParseSourceSpan, public expSourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context: any): any { return visitor.visitExpansionCase(this, context); } visit(visitor: Visitor, context: any): any {
return visitor.visitExpansionCase(this, context);
}
} }
export class Attribute extends NodeWithI18n { export class Attribute extends NodeWithI18n {
@ -50,7 +56,9 @@ export class Attribute extends NodeWithI18n {
public valueSpan?: ParseSourceSpan, i18n?: I18nMeta) { public valueSpan?: ParseSourceSpan, i18n?: I18nMeta) {
super(sourceSpan, i18n); super(sourceSpan, i18n);
} }
visit(visitor: Visitor, context: any): any { return visitor.visitAttribute(this, context); } visit(visitor: Visitor, context: any): any {
return visitor.visitAttribute(this, context);
}
} }
export class Element extends NodeWithI18n { export class Element extends NodeWithI18n {
@ -60,12 +68,16 @@ export class Element extends NodeWithI18n {
public endSourceSpan: ParseSourceSpan|null = null, i18n?: I18nMeta) { public endSourceSpan: ParseSourceSpan|null = null, i18n?: I18nMeta) {
super(sourceSpan, i18n); super(sourceSpan, i18n);
} }
visit(visitor: Visitor, context: any): any { return visitor.visitElement(this, context); } visit(visitor: Visitor, context: any): any {
return visitor.visitElement(this, context);
}
} }
export class Comment implements Node { export class Comment implements Node {
constructor(public value: string|null, public sourceSpan: ParseSourceSpan) {} constructor(public value: string|null, public sourceSpan: ParseSourceSpan) {}
visit(visitor: Visitor, context: any): any { return visitor.visitComment(this, context); } visit(visitor: Visitor, context: any): any {
return visitor.visitComment(this, context);
}
} }
export interface Visitor { export interface Visitor {
@ -111,7 +123,9 @@ export class RecursiveVisitor implements Visitor {
visitComment(ast: Comment, context: any): any {} visitComment(ast: Comment, context: any): any {}
visitExpansion(ast: Expansion, context: any): any { visitExpansion(ast: Expansion, context: any): any {
return this.visitChildren(context, visit => { visit(ast.cases); }); return this.visitChildren(context, visit => {
visit(ast.cases);
});
} }
visitExpansionCase(ast: ExpansionCase, context: any): any {} visitExpansionCase(ast: ExpansionCase, context: any): any {}

View File

@ -8,12 +8,14 @@
import {getHtmlTagDefinition} from './html_tags'; import {getHtmlTagDefinition} from './html_tags';
import {TokenizeOptions} from './lexer'; import {TokenizeOptions} from './lexer';
import {ParseTreeResult, Parser} from './parser'; import {Parser, ParseTreeResult} from './parser';
export {ParseTreeResult, TreeError} from './parser'; export {ParseTreeResult, TreeError} from './parser';
export class HtmlParser extends Parser { export class HtmlParser extends Parser {
constructor() { super(getHtmlTagDefinition); } constructor() {
super(getHtmlTagDefinition);
}
parse(source: string, url: string, options?: TokenizeOptions): ParseTreeResult { parse(source: string, url: string, options?: TokenizeOptions): ParseTreeResult {
return super.parse(source, url, options); return super.parse(source, url, options);

View File

@ -18,9 +18,14 @@ export class HtmlTagDefinition implements TagDefinition {
ignoreFirstLf: boolean; ignoreFirstLf: boolean;
canSelfClose: boolean = false; canSelfClose: boolean = false;
constructor( constructor({
{closedByChildren, implicitNamespacePrefix, contentType = TagContentType.PARSABLE_DATA, closedByChildren,
closedByParent = false, isVoid = false, ignoreFirstLf = false}: { implicitNamespacePrefix,
contentType = TagContentType.PARSABLE_DATA,
closedByParent = false,
isVoid = false,
ignoreFirstLf = false
}: {
closedByChildren?: string[], closedByChildren?: string[],
closedByParent?: boolean, closedByParent?: boolean,
implicitNamespacePrefix?: string, implicitNamespacePrefix?: string,

View File

@ -81,11 +81,17 @@ export class WhitespaceVisitor implements html.Visitor {
return null; return null;
} }
visitComment(comment: html.Comment, context: any): any { return comment; } visitComment(comment: html.Comment, context: any): any {
return comment;
}
visitExpansion(expansion: html.Expansion, context: any): any { return expansion; } visitExpansion(expansion: html.Expansion, context: any): any {
return expansion;
}
visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any { return expansionCase; } visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any {
return expansionCase;
}
} }
export function removeWhitespaces(htmlAstWithErrors: ParseTreeResult): ParseTreeResult { export function removeWhitespaces(htmlAstWithErrors: ParseTreeResult): ParseTreeResult {

View File

@ -46,7 +46,9 @@ export class ExpansionResult {
} }
export class ExpansionError extends ParseError { export class ExpansionError extends ParseError {
constructor(span: ParseSourceSpan, errorMsg: string) { super(span, errorMsg); } constructor(span: ParseSourceSpan, errorMsg: string) {
super(span, errorMsg);
}
} }
/** /**
@ -64,11 +66,17 @@ class _Expander implements html.Visitor {
element.startSourceSpan, element.endSourceSpan); element.startSourceSpan, element.endSourceSpan);
} }
visitAttribute(attribute: html.Attribute, context: any): any { return attribute; } visitAttribute(attribute: html.Attribute, context: any): any {
return attribute;
}
visitText(text: html.Text, context: any): any { return text; } visitText(text: html.Text, context: any): any {
return text;
}
visitComment(comment: html.Comment, context: any): any { return comment; } visitComment(comment: html.Comment, context: any): any {
return comment;
}
visitExpansion(icu: html.Expansion, context: any): any { visitExpansion(icu: html.Expansion, context: any): any {
this.isExpanded = true; this.isExpanded = true;
@ -87,7 +95,7 @@ function _expandPluralForm(ast: html.Expansion, errors: ParseError[]): html.Elem
if (PLURAL_CASES.indexOf(c.value) == -1 && !c.value.match(/^=\d+$/)) { if (PLURAL_CASES.indexOf(c.value) == -1 && !c.value.match(/^=\d+$/)) {
errors.push(new ExpansionError( errors.push(new ExpansionError(
c.valueSourceSpan, c.valueSourceSpan,
`Plural cases should be "=<number>" or one of ${PLURAL_CASES.join(", ")}`)); `Plural cases should be "=<number>" or one of ${PLURAL_CASES.join(', ')}`));
} }
const expansionResult = expandNodes(c.expression); const expansionResult = expandNodes(c.expression);

View File

@ -849,15 +849,27 @@ class PlainCharacterCursor implements CharacterCursor {
} }
} }
clone(): PlainCharacterCursor { return new PlainCharacterCursor(this); } clone(): PlainCharacterCursor {
return new PlainCharacterCursor(this);
}
peek() { return this.state.peek; } peek() {
charsLeft() { return this.end - this.state.offset; } return this.state.peek;
diff(other: this) { return this.state.offset - other.state.offset; } }
charsLeft() {
return this.end - this.state.offset;
}
diff(other: this) {
return this.state.offset - other.state.offset;
}
advance(): void { this.advanceState(this.state); } advance(): void {
this.advanceState(this.state);
}
init(): void { this.updatePeek(this.state); } init(): void {
this.updatePeek(this.state);
}
getSpan(start?: this, leadingTriviaCodePoints?: number[]): ParseSourceSpan { getSpan(start?: this, leadingTriviaCodePoints?: number[]): ParseSourceSpan {
start = start || this; start = start || this;
@ -880,7 +892,9 @@ class PlainCharacterCursor implements CharacterCursor {
return this.input.substring(start.state.offset, this.state.offset); return this.input.substring(start.state.offset, this.state.offset);
} }
charAt(pos: number): number { return this.input.charCodeAt(pos); } charAt(pos: number): number {
return this.input.charCodeAt(pos);
}
protected advanceState(state: CursorState) { protected advanceState(state: CursorState) {
if (state.offset >= this.end) { if (state.offset >= this.end) {
@ -929,7 +943,9 @@ class EscapedCharacterCursor extends PlainCharacterCursor {
this.processEscapeSequence(); this.processEscapeSequence();
} }
clone(): EscapedCharacterCursor { return new EscapedCharacterCursor(this); } clone(): EscapedCharacterCursor {
return new EscapedCharacterCursor(this);
}
getChars(start: this): string { getChars(start: this): string {
const cursor = start.clone(); const cursor = start.clone();

View File

@ -10,7 +10,7 @@ import {ParseError, ParseSourceSpan} from '../parse_util';
import * as html from './ast'; import * as html from './ast';
import * as lex from './lexer'; import * as lex from './lexer';
import {TagDefinition, getNsPrefix, isNgContainer, mergeNsAndName} from './tags'; import {getNsPrefix, isNgContainer, mergeNsAndName, TagDefinition} from './tags';
export class TreeError extends ParseError { export class TreeError extends ParseError {
static create(elementName: string|null, span: ParseSourceSpan, msg: string): TreeError { static create(elementName: string|null, span: ParseSourceSpan, msg: string): TreeError {
@ -291,8 +291,8 @@ class _TreeBuilder {
fullName, endTagToken.sourceSpan, fullName, endTagToken.sourceSpan,
`Void elements do not have end tags "${endTagToken.parts[1]}"`)); `Void elements do not have end tags "${endTagToken.parts[1]}"`));
} else if (!this._popElement(fullName)) { } else if (!this._popElement(fullName)) {
const errMsg = const errMsg = `Unexpected closing tag "${
`Unexpected closing tag "${fullName}". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags`; fullName}". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags`;
this._errors.push(TreeError.create(fullName, endTagToken.sourceSpan, errMsg)); this._errors.push(TreeError.create(fullName, endTagToken.sourceSpan, errMsg));
} }
} }

View File

@ -7,13 +7,15 @@
*/ */
import {TokenizeOptions} from './lexer'; import {TokenizeOptions} from './lexer';
import {ParseTreeResult, Parser} from './parser'; import {Parser, ParseTreeResult} from './parser';
import {getXmlTagDefinition} from './xml_tags'; import {getXmlTagDefinition} from './xml_tags';
export {ParseTreeResult, TreeError} from './parser'; export {ParseTreeResult, TreeError} from './parser';
export class XmlParser extends Parser { export class XmlParser extends Parser {
constructor() { super(getXmlTagDefinition); } constructor() {
super(getXmlTagDefinition);
}
parse(source: string, url: string, options?: TokenizeOptions): ParseTreeResult { parse(source: string, url: string, options?: TokenizeOptions): ParseTreeResult {
return super.parse(source, url, options); return super.parse(source, url, options);

View File

@ -21,9 +21,13 @@ export class XmlTagDefinition implements TagDefinition {
ignoreFirstLf: boolean = false; ignoreFirstLf: boolean = false;
canSelfClose: boolean = true; canSelfClose: boolean = true;
requireExtraParent(currentParent: string): boolean { return false; } requireExtraParent(currentParent: string): boolean {
return false;
}
isClosedByChild(name: string): boolean { return false; } isClosedByChild(name: string): boolean {
return false;
}
} }
const _TAG_DEFINITION = new XmlTagDefinition(); const _TAG_DEFINITION = new XmlTagDefinition();

View File

@ -43,8 +43,8 @@ export class NgModuleCompiler {
}); });
const ngModuleDef = o.importExpr(Identifiers.moduleDef).callFn([o.literalArr(providerDefs)]); const ngModuleDef = o.importExpr(Identifiers.moduleDef).callFn([o.literalArr(providerDefs)]);
const ngModuleDefFactory = o.fn( const ngModuleDefFactory =
[new o.FnParam(LOG_VAR.name !)], [new o.ReturnStatement(ngModuleDef)], o.INFERRED_TYPE); o.fn([new o.FnParam(LOG_VAR.name!)], [new o.ReturnStatement(ngModuleDef)], o.INFERRED_TYPE);
const ngModuleFactoryVar = `${identifierName(ngModuleMeta.type)}NgFactory`; const ngModuleFactoryVar = `${identifierName(ngModuleMeta.type)}NgFactory`;
this._createNgModuleFactory( this._createNgModuleFactory(

View File

@ -7,7 +7,7 @@
*/ */
import {CompileReflector} from './compile_reflector'; import {CompileReflector} from './compile_reflector';
import {NgModule, Type, createNgModule} from './core'; import {createNgModule, NgModule, Type} from './core';
import {findLast} from './directive_resolver'; import {findLast} from './directive_resolver';
import {stringify} from './util'; import {stringify} from './util';
@ -18,7 +18,9 @@ import {stringify} from './util';
export class NgModuleResolver { export class NgModuleResolver {
constructor(private _reflector: CompileReflector) {} constructor(private _reflector: CompileReflector) {}
isNgModule(type: any) { return this._reflector.annotations(type).some(createNgModule.isTypeOf); } isNgModule(type: any) {
return this._reflector.annotations(type).some(createNgModule.isTypeOf);
}
resolve(type: Type, throwIfNotFound = true): NgModule|null { resolve(type: Type, throwIfNotFound = true): NgModule|null {
const ngModuleMeta: NgModule = const ngModuleMeta: NgModule =

View File

@ -28,25 +28,33 @@ class _EmittedLine {
} }
export class EmitterVisitorContext { export class EmitterVisitorContext {
static createRoot(): EmitterVisitorContext { return new EmitterVisitorContext(0); } static createRoot(): EmitterVisitorContext {
return new EmitterVisitorContext(0);
}
private _lines: _EmittedLine[]; private _lines: _EmittedLine[];
private _classes: o.ClassStmt[] = []; private _classes: o.ClassStmt[] = [];
private _preambleLineCount = 0; private _preambleLineCount = 0;
constructor(private _indent: number) { this._lines = [new _EmittedLine(_indent)]; } constructor(private _indent: number) {
this._lines = [new _EmittedLine(_indent)];
}
/** /**
* @internal strip this from published d.ts files due to * @internal strip this from published d.ts files due to
* https://github.com/microsoft/TypeScript/issues/36216 * https://github.com/microsoft/TypeScript/issues/36216
*/ */
private get _currentLine(): _EmittedLine { return this._lines[this._lines.length - 1]; } private get _currentLine(): _EmittedLine {
return this._lines[this._lines.length - 1];
}
println(from?: {sourceSpan: ParseSourceSpan|null}|null, lastPart: string = ''): void { println(from?: {sourceSpan: ParseSourceSpan|null}|null, lastPart: string = ''): void {
this.print(from || null, lastPart, true); this.print(from || null, lastPart, true);
} }
lineIsEmpty(): boolean { return this._currentLine.parts.length === 0; } lineIsEmpty(): boolean {
return this._currentLine.parts.length === 0;
}
lineLength(): number { lineLength(): number {
return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength; return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength;
@ -83,9 +91,13 @@ export class EmitterVisitorContext {
} }
} }
pushClass(clazz: o.ClassStmt) { this._classes.push(clazz); } pushClass(clazz: o.ClassStmt) {
this._classes.push(clazz);
}
popClass(): o.ClassStmt { return this._classes.pop() !; } popClass(): o.ClassStmt {
return this._classes.pop()!;
}
get currentClass(): o.ClassStmt|null { get currentClass(): o.ClassStmt|null {
return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null; return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null;
@ -156,7 +168,9 @@ export class EmitterVisitorContext {
return map; return map;
} }
setPreambleLineCount(count: number) { return this._preambleLineCount = count; } setPreambleLineCount(count: number) {
return this._preambleLineCount = count;
}
spanOf(line: number, column: number): ParseSourceSpan|null { spanOf(line: number, column: number): ParseSourceSpan|null {
const emittedLine = this._lines[line - this._preambleLineCount]; const emittedLine = this._lines[line - this._preambleLineCount];
@ -243,7 +257,9 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
if (stmt.multiline) { if (stmt.multiline) {
ctx.println(stmt, `/* ${stmt.comment} */`); ctx.println(stmt, `/* ${stmt.comment} */`);
} else { } else {
stmt.comment.split('\n').forEach((line) => { ctx.println(stmt, `// ${line}`); }); stmt.comment.split('\n').forEach((line) => {
ctx.println(stmt, `// ${line}`);
});
} }
return null; return null;
} }

View File

@ -11,7 +11,9 @@ import {AbstractEmitterVisitor, CATCH_ERROR_VAR, CATCH_STACK_VAR, EmitterVisitor
import * as o from './output_ast'; import * as o from './output_ast';
export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor { export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
constructor() { super(false); } constructor() {
super(false);
}
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any { visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any {
ctx.pushClass(stmt); ctx.pushClass(stmt);
this._visitClassConstructor(stmt, ctx); this._visitClassConstructor(stmt, ctx);

View File

@ -24,7 +24,9 @@ export abstract class Type {
} }
abstract visitType(visitor: TypeVisitor, context: any): any; abstract visitType(visitor: TypeVisitor, context: any): any;
hasModifier(modifier: TypeModifier): boolean { return this.modifiers !.indexOf(modifier) !== -1; } hasModifier(modifier: TypeModifier): boolean {
return this.modifiers!.indexOf(modifier) !== -1;
}
} }
export enum BuiltinTypeName { export enum BuiltinTypeName {
@ -60,7 +62,9 @@ export class ExpressionType extends Type {
export class ArrayType extends Type { export class ArrayType extends Type {
constructor(public of : Type, modifiers: TypeModifier[]|null = null) { super(modifiers); } constructor(public of: Type, modifiers: TypeModifier[]|null = null) {
super(modifiers);
}
visitType(visitor: TypeVisitor, context: any): any { visitType(visitor: TypeVisitor, context: any): any {
return visitor.visitArrayType(this, context); return visitor.visitArrayType(this, context);
} }
@ -73,7 +77,9 @@ export class MapType extends Type {
super(modifiers); super(modifiers);
this.valueType = valueType || null; this.valueType = valueType || null;
} }
visitType(visitor: TypeVisitor, context: any): any { return visitor.visitMapType(this, context); } visitType(visitor: TypeVisitor, context: any): any {
return visitor.visitMapType(this, context);
}
} }
export const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic); export const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic);
@ -243,7 +249,9 @@ export abstract class Expression {
return new CastExpr(this, type, sourceSpan); return new CastExpr(this, type, sourceSpan);
} }
toStmt(): Statement { return new ExpressionStatement(this, null); } toStmt(): Statement {
return new ExpressionStatement(this, null);
}
} }
export enum BuiltinVar { export enum BuiltinVar {
@ -272,7 +280,9 @@ export class ReadVarExpr extends Expression {
return e instanceof ReadVarExpr && this.name === e.name && this.builtin === e.builtin; return e instanceof ReadVarExpr && this.name === e.name && this.builtin === e.builtin;
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitReadVarExpr(this, context); return visitor.visitReadVarExpr(this, context);
@ -299,7 +309,9 @@ export class TypeofExpr extends Expression {
return e instanceof TypeofExpr && e.expr.isEquivalent(this.expr); return e instanceof TypeofExpr && e.expr.isEquivalent(this.expr);
} }
isConstant(): boolean { return this.expr.isConstant(); } isConstant(): boolean {
return this.expr.isConstant();
}
} }
export class WrappedNodeExpr<T> extends Expression { export class WrappedNodeExpr<T> extends Expression {
@ -311,7 +323,9 @@ export class WrappedNodeExpr<T> extends Expression {
return e instanceof WrappedNodeExpr && this.node === e.node; return e instanceof WrappedNodeExpr && this.node === e.node;
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitWrappedNodeExpr(this, context); return visitor.visitWrappedNodeExpr(this, context);
@ -330,7 +344,9 @@ export class WriteVarExpr extends Expression {
return e instanceof WriteVarExpr && this.name === e.name && this.value.isEquivalent(e.value); return e instanceof WriteVarExpr && this.name === e.name && this.value.isEquivalent(e.value);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitWriteVarExpr(this, context); return visitor.visitWriteVarExpr(this, context);
@ -340,7 +356,9 @@ export class WriteVarExpr extends Expression {
return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan); return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan);
} }
toConstDecl(): DeclareVarStmt { return this.toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]); } toConstDecl(): DeclareVarStmt {
return this.toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]);
}
} }
@ -358,7 +376,9 @@ export class WriteKeyExpr extends Expression {
this.index.isEquivalent(e.index) && this.value.isEquivalent(e.value); this.index.isEquivalent(e.index) && this.value.isEquivalent(e.value);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitWriteKeyExpr(this, context); return visitor.visitWriteKeyExpr(this, context);
@ -380,7 +400,9 @@ export class WritePropExpr extends Expression {
this.name === e.name && this.value.isEquivalent(e.value); this.name === e.name && this.value.isEquivalent(e.value);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitWritePropExpr(this, context); return visitor.visitWritePropExpr(this, context);
@ -414,7 +436,9 @@ export class InvokeMethodExpr extends Expression {
this.name === e.name && this.builtin === e.builtin && areAllEquivalent(this.args, e.args); this.name === e.name && this.builtin === e.builtin && areAllEquivalent(this.args, e.args);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitInvokeMethodExpr(this, context); return visitor.visitInvokeMethodExpr(this, context);
@ -434,7 +458,9 @@ export class InvokeFunctionExpr extends Expression {
areAllEquivalent(this.args, e.args) && this.pure === e.pure; areAllEquivalent(this.args, e.args) && this.pure === e.pure;
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitInvokeFunctionExpr(this, context); return visitor.visitInvokeFunctionExpr(this, context);
@ -454,7 +480,9 @@ export class InstantiateExpr extends Expression {
areAllEquivalent(this.args, e.args); areAllEquivalent(this.args, e.args);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitInstantiateExpr(this, context); return visitor.visitInstantiateExpr(this, context);
@ -473,7 +501,9 @@ export class LiteralExpr extends Expression {
return e instanceof LiteralExpr && this.value === e.value; return e instanceof LiteralExpr && this.value === e.value;
} }
isConstant() { return true; } isConstant() {
return true;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitLiteralExpr(this, context); return visitor.visitLiteralExpr(this, context);
@ -494,7 +524,9 @@ export class LocalizedString extends Expression {
return false; return false;
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitLocalizedString(this, context); return visitor.visitLocalizedString(this, context);
@ -521,8 +553,9 @@ export class LocalizedString extends Expression {
metaBlock = `${metaBlock}${ID_SEPARATOR}${this.metaBlock.customId}`; metaBlock = `${metaBlock}${ID_SEPARATOR}${this.metaBlock.customId}`;
} }
if (this.metaBlock.legacyIds) { if (this.metaBlock.legacyIds) {
this.metaBlock.legacyIds.forEach( this.metaBlock.legacyIds.forEach(legacyId => {
legacyId => { metaBlock = `${metaBlock}${LEGACY_ID_INDICATOR}${legacyId}`; }); metaBlock = `${metaBlock}${LEGACY_ID_INDICATOR}${legacyId}`;
});
} }
return createCookedRawString(metaBlock, this.messageParts[0]); return createCookedRawString(metaBlock, this.messageParts[0]);
} }
@ -588,7 +621,9 @@ export class ExternalExpr extends Expression {
this.value.moduleName === e.value.moduleName && this.value.runtime === e.value.runtime; this.value.moduleName === e.value.moduleName && this.value.runtime === e.value.runtime;
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitExternalExpr(this, context); return visitor.visitExternalExpr(this, context);
@ -616,7 +651,9 @@ export class ConditionalExpr extends Expression {
this.trueCase.isEquivalent(e.trueCase) && nullSafeIsEquivalent(this.falseCase, e.falseCase); this.trueCase.isEquivalent(e.trueCase) && nullSafeIsEquivalent(this.falseCase, e.falseCase);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitConditionalExpr(this, context); return visitor.visitConditionalExpr(this, context);
@ -633,7 +670,9 @@ export class NotExpr extends Expression {
return e instanceof NotExpr && this.condition.isEquivalent(e.condition); return e instanceof NotExpr && this.condition.isEquivalent(e.condition);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitNotExpr(this, context); return visitor.visitNotExpr(this, context);
@ -649,7 +688,9 @@ export class AssertNotNull extends Expression {
return e instanceof AssertNotNull && this.condition.isEquivalent(e.condition); return e instanceof AssertNotNull && this.condition.isEquivalent(e.condition);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitAssertNotNullExpr(this, context); return visitor.visitAssertNotNullExpr(this, context);
@ -665,7 +706,9 @@ export class CastExpr extends Expression {
return e instanceof CastExpr && this.value.isEquivalent(e.value); return e instanceof CastExpr && this.value.isEquivalent(e.value);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitCastExpr(this, context); return visitor.visitCastExpr(this, context);
@ -676,7 +719,9 @@ export class CastExpr extends Expression {
export class FnParam { export class FnParam {
constructor(public name: string, public type: Type|null = null) {} constructor(public name: string, public type: Type|null = null) {}
isEquivalent(param: FnParam): boolean { return this.name === param.name; } isEquivalent(param: FnParam): boolean {
return this.name === param.name;
}
} }
@ -692,7 +737,9 @@ export class FunctionExpr extends Expression {
areAllEquivalent(this.statements, e.statements); areAllEquivalent(this.statements, e.statements);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitFunctionExpr(this, context); return visitor.visitFunctionExpr(this, context);
@ -719,7 +766,9 @@ export class BinaryOperatorExpr extends Expression {
this.lhs.isEquivalent(e.lhs) && this.rhs.isEquivalent(e.rhs); this.lhs.isEquivalent(e.lhs) && this.rhs.isEquivalent(e.rhs);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitBinaryOperatorExpr(this, context); return visitor.visitBinaryOperatorExpr(this, context);
@ -739,7 +788,9 @@ export class ReadPropExpr extends Expression {
this.name === e.name; this.name === e.name;
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitReadPropExpr(this, context); return visitor.visitReadPropExpr(this, context);
@ -763,7 +814,9 @@ export class ReadKeyExpr extends Expression {
this.index.isEquivalent(e.index); this.index.isEquivalent(e.index);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitReadKeyExpr(this, context); return visitor.visitReadKeyExpr(this, context);
@ -782,7 +835,9 @@ export class LiteralArrayExpr extends Expression {
this.entries = entries; this.entries = entries;
} }
isConstant() { return this.entries.every(e => e.isConstant()); } isConstant() {
return this.entries.every(e => e.isConstant());
}
isEquivalent(e: Expression): boolean { isEquivalent(e: Expression): boolean {
return e instanceof LiteralArrayExpr && areAllEquivalent(this.entries, e.entries); return e instanceof LiteralArrayExpr && areAllEquivalent(this.entries, e.entries);
@ -813,7 +868,9 @@ export class LiteralMapExpr extends Expression {
return e instanceof LiteralMapExpr && areAllEquivalent(this.entries, e.entries); return e instanceof LiteralMapExpr && areAllEquivalent(this.entries, e.entries);
} }
isConstant() { return this.entries.every(e => e.value.isConstant()); } isConstant() {
return this.entries.every(e => e.value.isConstant());
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitLiteralMapExpr(this, context); return visitor.visitLiteralMapExpr(this, context);
@ -829,7 +886,9 @@ export class CommaExpr extends Expression {
return e instanceof CommaExpr && areAllEquivalent(this.parts, e.parts); return e instanceof CommaExpr && areAllEquivalent(this.parts, e.parts);
} }
isConstant() { return false; } isConstant() {
return false;
}
visitExpression(visitor: ExpressionVisitor, context: any): any { visitExpression(visitor: ExpressionVisitor, context: any): any {
return visitor.visitCommaExpr(this, context); return visitor.visitCommaExpr(this, context);
@ -892,7 +951,9 @@ export abstract class Statement {
abstract visitStatement(visitor: StatementVisitor, context: any): any; abstract visitStatement(visitor: StatementVisitor, context: any): any;
hasModifier(modifier: StmtModifier): boolean { return this.modifiers !.indexOf(modifier) !== -1; } hasModifier(modifier: StmtModifier): boolean {
return this.modifiers!.indexOf(modifier) !== -1;
}
} }
@ -965,7 +1026,9 @@ export class AbstractClassPart {
} }
this.type = type || null; this.type = type || null;
} }
hasModifier(modifier: StmtModifier): boolean { return this.modifiers !.indexOf(modifier) !== -1; } hasModifier(modifier: StmtModifier): boolean {
return this.modifiers!.indexOf(modifier) !== -1;
}
} }
export class ClassField extends AbstractClassPart { export class ClassField extends AbstractClassPart {
@ -974,7 +1037,9 @@ export class ClassField extends AbstractClassPart {
public initializer?: Expression) { public initializer?: Expression) {
super(type, modifiers); super(type, modifiers);
} }
isEquivalent(f: ClassField) { return this.name === f.name; } isEquivalent(f: ClassField) {
return this.name === f.name;
}
} }
@ -1044,7 +1109,9 @@ export class CommentStmt extends Statement {
constructor(public comment: string, public multiline = false, sourceSpan?: ParseSourceSpan|null) { constructor(public comment: string, public multiline = false, sourceSpan?: ParseSourceSpan|null) {
super(null, sourceSpan); super(null, sourceSpan);
} }
isEquivalent(stmt: Statement): boolean { return stmt instanceof CommentStmt; } isEquivalent(stmt: Statement): boolean {
return stmt instanceof CommentStmt;
}
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
return visitor.visitCommentStmt(this, context); return visitor.visitCommentStmt(this, context);
} }
@ -1060,7 +1127,9 @@ export class JSDocCommentStmt extends Statement {
visitStatement(visitor: StatementVisitor, context: any): any { visitStatement(visitor: StatementVisitor, context: any): any {
return visitor.visitJSDocCommentStmt(this, context); return visitor.visitJSDocCommentStmt(this, context);
} }
toString(): string { return serializeTags(this.tags); } toString(): string {
return serializeTags(this.tags);
}
} }
export class TryCatchStmt extends Statement { export class TryCatchStmt extends Statement {
@ -1105,11 +1174,17 @@ export interface StatementVisitor {
} }
export class AstTransformer implements StatementVisitor, ExpressionVisitor { export class AstTransformer implements StatementVisitor, ExpressionVisitor {
transformExpr(expr: Expression, context: any): Expression { return expr; } transformExpr(expr: Expression, context: any): Expression {
return expr;
}
transformStmt(stmt: Statement, context: any): Statement { return stmt; } transformStmt(stmt: Statement, context: any): Statement {
return stmt;
}
visitReadVarExpr(ast: ReadVarExpr, context: any): any { return this.transformExpr(ast, context); } visitReadVarExpr(ast: ReadVarExpr, context: any): any {
return this.transformExpr(ast, context);
}
visitWrappedNodeExpr(ast: WrappedNodeExpr<any>, context: any): any { visitWrappedNodeExpr(ast: WrappedNodeExpr<any>, context: any): any {
return this.transformExpr(ast, context); return this.transformExpr(ast, context);
@ -1169,7 +1244,9 @@ export class AstTransformer implements StatementVisitor, ExpressionVisitor {
context); context);
} }
visitLiteralExpr(ast: LiteralExpr, context: any): any { return this.transformExpr(ast, context); } visitLiteralExpr(ast: LiteralExpr, context: any): any {
return this.transformExpr(ast, context);
}
visitLocalizedString(ast: LocalizedString, context: any): any { visitLocalizedString(ast: LocalizedString, context: any): any {
return this.transformExpr( return this.transformExpr(
@ -1341,14 +1418,18 @@ export class AstTransformer implements StatementVisitor, ExpressionVisitor {
export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor { export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor {
visitType(ast: Type, context: any): any { return ast; } visitType(ast: Type, context: any): any {
return ast;
}
visitExpression(ast: Expression, context: any): any { visitExpression(ast: Expression, context: any): any {
if (ast.type) { if (ast.type) {
ast.type.visitType(this, context); ast.type.visitType(this, context);
} }
return ast; return ast;
} }
visitBuiltinType(type: BuiltinType, context: any): any { return this.visitType(type, context); } visitBuiltinType(type: BuiltinType, context: any): any {
return this.visitType(type, context);
}
visitExpressionType(type: ExpressionType, context: any): any { visitExpressionType(type: ExpressionType, context: any): any {
type.value.visitExpression(this, context); type.value.visitExpression(this, context);
if (type.typeParams !== null) { if (type.typeParams !== null) {
@ -1356,10 +1437,18 @@ export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor
} }
return this.visitType(type, context); return this.visitType(type, context);
} }
visitArrayType(type: ArrayType, context: any): any { return this.visitType(type, context); } visitArrayType(type: ArrayType, context: any): any {
visitMapType(type: MapType, context: any): any { return this.visitType(type, context); } return this.visitType(type, context);
visitWrappedNodeExpr(ast: WrappedNodeExpr<any>, context: any): any { return ast; } }
visitTypeofExpr(ast: TypeofExpr, context: any): any { return this.visitExpression(ast, context); } visitMapType(type: MapType, context: any): any {
return this.visitType(type, context);
}
visitWrappedNodeExpr(ast: WrappedNodeExpr<any>, context: any): any {
return ast;
}
visitTypeofExpr(ast: TypeofExpr, context: any): any {
return this.visitExpression(ast, context);
}
visitReadVarExpr(ast: ReadVarExpr, context: any): any { visitReadVarExpr(ast: ReadVarExpr, context: any): any {
return this.visitExpression(ast, context); return this.visitExpression(ast, context);
} }
@ -1505,8 +1594,12 @@ export class RecursiveAstVisitor implements StatementVisitor, ExpressionVisitor
stmt.error.visitExpression(this, context); stmt.error.visitExpression(this, context);
return stmt; return stmt;
} }
visitCommentStmt(stmt: CommentStmt, context: any): any { return stmt; } visitCommentStmt(stmt: CommentStmt, context: any): any {
visitJSDocCommentStmt(stmt: JSDocCommentStmt, context: any): any { return stmt; } return stmt;
}
visitJSDocCommentStmt(stmt: JSDocCommentStmt, context: any): any {
return stmt;
}
visitAllStatements(stmts: Statement[], context: any): void { visitAllStatements(stmts: Statement[], context: any): void {
stmts.forEach(stmt => stmt.visitStatement(this, context)); stmts.forEach(stmt => stmt.visitStatement(this, context));
} }
@ -1569,7 +1662,9 @@ export function applySourceSpanToExpressionIfNeeded(
} }
class _ApplySourceSpanTransformer extends AstTransformer { class _ApplySourceSpanTransformer extends AstTransformer {
constructor(private sourceSpan: ParseSourceSpan) { super(); } constructor(private sourceSpan: ParseSourceSpan) {
super();
}
private _clone(obj: any): any { private _clone(obj: any): any {
const clone = Object.create(obj.constructor.prototype); const clone = Object.create(obj.constructor.prototype);
for (let prop of Object.keys(obj)) { for (let prop of Object.keys(obj)) {
@ -1623,8 +1718,7 @@ export function typeofExpr(expr: Expression) {
} }
export function literalArr( export function literalArr(
values: Expression[], type?: Type | null, values: Expression[], type?: Type|null, sourceSpan?: ParseSourceSpan|null): LiteralArrayExpr {
sourceSpan?: ParseSourceSpan | null): LiteralArrayExpr {
return new LiteralArrayExpr(values, type, sourceSpan); return new LiteralArrayExpr(values, type, sourceSpan);
} }
@ -1639,8 +1733,7 @@ export function not(expr: Expression, sourceSpan?: ParseSourceSpan | null): NotE
return new NotExpr(expr, sourceSpan); return new NotExpr(expr, sourceSpan);
} }
export function assertNotNull( export function assertNotNull(expr: Expression, sourceSpan?: ParseSourceSpan|null): AssertNotNull {
expr: Expression, sourceSpan?: ParseSourceSpan | null): AssertNotNull {
return new AssertNotNull(expr, sourceSpan); return new AssertNotNull(expr, sourceSpan);
} }
@ -1689,8 +1782,7 @@ export type JSDocTag = {
text?: string, text?: string,
}|{ }|{
// no `tagName` for plain text documentation that occurs before any `@param` lines // no `tagName` for plain text documentation that occurs before any `@param` lines
tagName?: undefined, tagName?: undefined, text: string,
text: string,
}; };
/* /*

View File

@ -15,7 +15,9 @@ export function interpretStatements(
const visitor = new StatementInterpreter(reflector); const visitor = new StatementInterpreter(reflector);
visitor.visitAllStatements(statements, ctx); visitor.visitAllStatements(statements, ctx);
const result: {[key: string]: any} = {}; const result: {[key: string]: any} = {};
ctx.exports.forEach((exportName) => { result[exportName] = ctx.vars.get(exportName); }); ctx.exports.forEach((exportName) => {
result[exportName] = ctx.vars.get(exportName);
});
return result; return result;
} }
@ -77,7 +79,9 @@ function createDynamicClass(
// Note: use `function` instead of arrow function to capture `this` // Note: use `function` instead of arrow function to capture `this`
const ctor = function(this: Object, ...args: any[]) { const ctor = function(this: Object, ...args: any[]) {
const instanceCtx = new _ExecutionContext(_ctx, this, _classStmt.name, _ctx.vars); const instanceCtx = new _ExecutionContext(_ctx, this, _classStmt.name, _ctx.vars);
_classStmt.fields.forEach((field) => { (this as any)[field.name] = undefined; }); _classStmt.fields.forEach((field) => {
(this as any)[field.name] = undefined;
});
_executeFunctionStatements( _executeFunctionStatements(
ctorParamNames, args, _classStmt.constructorMethod.body, instanceCtx, _visitor); ctorParamNames, args, _classStmt.constructorMethod.body, instanceCtx, _visitor);
}; };
@ -88,7 +92,9 @@ function createDynamicClass(
class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor { class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
constructor(private reflector: CompileReflector) {} constructor(private reflector: CompileReflector) {}
debugAst(ast: o.Expression|o.Statement|o.Type): string { return debugOutputAstAsTypeScript(ast); } debugAst(ast: o.Expression|o.Statement|o.Type): string {
return debugOutputAstAsTypeScript(ast);
}
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: _ExecutionContext): any { visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: _ExecutionContext): any {
const initialValue = stmt.value ? stmt.value.visitExpression(this, ctx) : undefined; const initialValue = stmt.value ? stmt.value.visitExpression(this, ctx) : undefined;
@ -227,15 +233,23 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
visitThrowStmt(stmt: o.ThrowStmt, ctx: _ExecutionContext): any { visitThrowStmt(stmt: o.ThrowStmt, ctx: _ExecutionContext): any {
throw stmt.error.visitExpression(this, ctx); throw stmt.error.visitExpression(this, ctx);
} }
visitCommentStmt(stmt: o.CommentStmt, context?: any): any { return null; } visitCommentStmt(stmt: o.CommentStmt, context?: any): any {
visitJSDocCommentStmt(stmt: o.JSDocCommentStmt, context?: any): any { return null; } return null;
}
visitJSDocCommentStmt(stmt: o.JSDocCommentStmt, context?: any): any {
return null;
}
visitInstantiateExpr(ast: o.InstantiateExpr, ctx: _ExecutionContext): any { visitInstantiateExpr(ast: o.InstantiateExpr, ctx: _ExecutionContext): any {
const args = this.visitAllExpressions(ast.args, ctx); const args = this.visitAllExpressions(ast.args, ctx);
const clazz = ast.classExpr.visitExpression(this, ctx); const clazz = ast.classExpr.visitExpression(this, ctx);
return new clazz(...args); return new clazz(...args);
} }
visitLiteralExpr(ast: o.LiteralExpr, ctx: _ExecutionContext): any { return ast.value; } visitLiteralExpr(ast: o.LiteralExpr, ctx: _ExecutionContext): any {
visitLocalizedString(ast: o.LocalizedString, context: any): any { return null; } return ast.value;
}
visitLocalizedString(ast: o.LocalizedString, context: any): any {
return null;
}
visitExternalExpr(ast: o.ExternalExpr, ctx: _ExecutionContext): any { visitExternalExpr(ast: o.ExternalExpr, ctx: _ExecutionContext): any {
return this.reflector.resolveExternalReference(ast.value); return this.reflector.resolveExternalReference(ast.value);
} }

View File

@ -87,7 +87,9 @@ export class JitEvaluator {
* @param args The arguments to pass to the function being executed. * @param args The arguments to pass to the function being executed.
* @returns The return value of the executed function. * @returns The return value of the executed function.
*/ */
executeFunction(fn: Function, args: any[]) { return fn(...args); } executeFunction(fn: Function, args: any[]) {
return fn(...args);
}
} }
/** /**
@ -98,7 +100,9 @@ export class JitEmitterVisitor extends AbstractJsEmitterVisitor {
private _evalArgValues: any[] = []; private _evalArgValues: any[] = [];
private _evalExportedVars: string[] = []; private _evalExportedVars: string[] = [];
constructor(private reflector: CompileReflector) { super(); } constructor(private reflector: CompileReflector) {
super();
}
createReturnStmt(ctx: EmitterVisitorContext) { createReturnStmt(ctx: EmitterVisitorContext) {
const stmt = new o.ReturnStatement(new o.LiteralMapExpr(this._evalExportedVars.map( const stmt = new o.ReturnStatement(new o.LiteralMapExpr(this._evalExportedVars.map(

View File

@ -78,7 +78,9 @@ export class SourceMapGenerator {
* @internal strip this from published d.ts files due to * @internal strip this from published d.ts files due to
* https://github.com/microsoft/TypeScript/issues/36216 * https://github.com/microsoft/TypeScript/issues/36216
*/ */
private get currentLine(): Segment[]|null { return this.lines.slice(-1)[0]; } private get currentLine(): Segment[]|null {
return this.lines.slice(-1)[0];
}
toJSON(): SourceMap|null { toJSON(): SourceMap|null {
if (!this.hasMappings) { if (!this.hasMappings) {

View File

@ -15,8 +15,7 @@ import * as o from './output_ast';
const _debugFilePath = '/debug/lib'; const _debugFilePath = '/debug/lib';
export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.Type | any[]): export function debugOutputAstAsTypeScript(ast: o.Statement|o.Expression|o.Type|any[]): string {
string {
const converter = new _TsEmitterVisitor(); const converter = new _TsEmitterVisitor();
const ctx = EmitterVisitorContext.createRoot(); const ctx = EmitterVisitorContext.createRoot();
const asts: any[] = Array.isArray(ast) ? ast : [ast]; const asts: any[] = Array.isArray(ast) ? ast : [ast];

View File

@ -43,7 +43,9 @@ class _ValueOutputAstTransformer implements ValueTransformer {
return new o.LiteralMapExpr(entries, type); return new o.LiteralMapExpr(entries, type);
} }
visitPrimitive(value: any, type: o.Type): o.Expression { return o.literal(value, type); } visitPrimitive(value: any, type: o.Type): o.Expression {
return o.literal(value, type);
}
visitOther(value: any, type: o.Type): o.Expression { visitOther(value: any, type: o.Type): o.Expression {
if (value instanceof o.Expression) { if (value instanceof o.Expression) {

View File

@ -7,7 +7,7 @@
*/ */
import {CompileReflector} from './compile_reflector'; import {CompileReflector} from './compile_reflector';
import {Pipe, Type, createPipe} from './core'; import {createPipe, Pipe, Type} from './core';
import {findLast} from './directive_resolver'; import {findLast} from './directive_resolver';
import {resolveForwardRef, stringify} from './util'; import {resolveForwardRef, stringify} from './util';

View File

@ -9,12 +9,14 @@
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenName, tokenReference} from './compile_metadata'; import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenName, tokenReference} from './compile_metadata';
import {CompileReflector} from './compile_reflector'; import {CompileReflector} from './compile_reflector';
import {Identifiers, createTokenForExternalReference} from './identifiers'; import {createTokenForExternalReference, Identifiers} from './identifiers';
import {ParseError, ParseSourceSpan} from './parse_util'; import {ParseError, ParseSourceSpan} from './parse_util';
import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, QueryMatch, ReferenceAst} from './template_parser/template_ast'; import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, QueryMatch, ReferenceAst} from './template_parser/template_ast';
export class ProviderError extends ParseError { export class ProviderError extends ParseError {
constructor(message: string, span: ParseSourceSpan) { super(span, message); } constructor(message: string, span: ParseSourceSpan) {
super(span, message);
}
} }
export interface QueryWithId { export interface QueryWithId {
@ -125,7 +127,9 @@ export class ProviderElementContext {
get queryMatches(): QueryMatch[] { get queryMatches(): QueryMatch[] {
const allMatches: QueryMatch[] = []; const allMatches: QueryMatch[] = [];
this._queriedTokens.forEach((matches: QueryMatch[]) => { allMatches.push(...matches); }); this._queriedTokens.forEach((matches: QueryMatch[]) => {
allMatches.push(...matches);
});
return allMatches; return allMatches;
} }
@ -171,7 +175,8 @@ export class ProviderElementContext {
requestingProviderType: ProviderAstType, token: CompileTokenMetadata, requestingProviderType: ProviderAstType, token: CompileTokenMetadata,
eager: boolean): ProviderAst|null { eager: boolean): ProviderAst|null {
const resolvedProvider = this._allProviders.get(tokenReference(token)); const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider || ((requestingProviderType === ProviderAstType.Directive || if (!resolvedProvider ||
((requestingProviderType === ProviderAstType.Directive ||
requestingProviderType === ProviderAstType.PublicService) && requestingProviderType === ProviderAstType.PublicService) &&
resolvedProvider.providerType === ProviderAstType.PrivateService) || resolvedProvider.providerType === ProviderAstType.PrivateService) ||
((requestingProviderType === ProviderAstType.PrivateService || ((requestingProviderType === ProviderAstType.PrivateService ||
@ -478,7 +483,8 @@ function _resolveProviders(
let resolvedProvider = targetProvidersByToken.get(tokenReference(provider.token)); let resolvedProvider = targetProvidersByToken.get(tokenReference(provider.token));
if (resolvedProvider != null && !!resolvedProvider.multiProvider !== !!provider.multi) { if (resolvedProvider != null && !!resolvedProvider.multiProvider !== !!provider.multi) {
targetErrors.push(new ProviderError( targetErrors.push(new ProviderError(
`Mixing multi and non multi provider is not possible for token ${tokenName(resolvedProvider.token)}`, `Mixing multi and non multi provider is not possible for token ${
tokenName(resolvedProvider.token)}`,
sourceSpan)); sourceSpan));
} }
if (!resolvedProvider) { if (!resolvedProvider) {

View File

@ -18,19 +18,25 @@ export interface Node {
export class Text implements Node { export class Text implements Node {
constructor(public value: string, public sourceSpan: ParseSourceSpan) {} constructor(public value: string, public sourceSpan: ParseSourceSpan) {}
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitText(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitText(this);
}
} }
export class BoundText implements Node { export class BoundText implements Node {
constructor(public value: AST, public sourceSpan: ParseSourceSpan, public i18n?: I18nMeta) {} constructor(public value: AST, public sourceSpan: ParseSourceSpan, public i18n?: I18nMeta) {}
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitBoundText(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitBoundText(this);
}
} }
export class TextAttribute implements Node { export class TextAttribute implements Node {
constructor( constructor(
public name: string, public value: string, public sourceSpan: ParseSourceSpan, public name: string, public value: string, public sourceSpan: ParseSourceSpan,
public valueSpan?: ParseSourceSpan, public i18n?: I18nMeta) {} public valueSpan?: ParseSourceSpan, public i18n?: I18nMeta) {}
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitTextAttribute(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitTextAttribute(this);
}
} }
export class BoundAttribute implements Node { export class BoundAttribute implements Node {
@ -45,7 +51,9 @@ export class BoundAttribute implements Node {
prop.valueSpan, i18n); prop.valueSpan, i18n);
} }
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitBoundAttribute(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitBoundAttribute(this);
}
} }
export class BoundEvent implements Node { export class BoundEvent implements Node {
@ -62,7 +70,9 @@ export class BoundEvent implements Node {
event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan); event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan);
} }
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitBoundEvent(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitBoundEvent(this);
}
} }
export class Element implements Node { export class Element implements Node {
@ -76,7 +86,9 @@ export class Element implements Node {
this.sourceSpan = new ParseSourceSpan(sourceSpan.start, endSourceSpan.end); this.sourceSpan = new ParseSourceSpan(sourceSpan.start, endSourceSpan.end);
} }
} }
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitElement(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitElement(this);
}
} }
export class Template implements Node { export class Template implements Node {
@ -86,28 +98,36 @@ export class Template implements Node {
public children: Node[], public references: Reference[], public variables: Variable[], public children: Node[], public references: Reference[], public variables: Variable[],
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan|null, public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan|null,
public endSourceSpan: ParseSourceSpan|null, public i18n?: I18nMeta) {} public endSourceSpan: ParseSourceSpan|null, public i18n?: I18nMeta) {}
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitTemplate(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitTemplate(this);
}
} }
export class Content implements Node { export class Content implements Node {
constructor( constructor(
public selector: string, public attributes: TextAttribute[], public selector: string, public attributes: TextAttribute[],
public sourceSpan: ParseSourceSpan, public i18n?: I18nMeta) {} public sourceSpan: ParseSourceSpan, public i18n?: I18nMeta) {}
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitContent(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitContent(this);
}
} }
export class Variable implements Node { export class Variable implements Node {
constructor( constructor(
public name: string, public value: string, public sourceSpan: ParseSourceSpan, public name: string, public value: string, public sourceSpan: ParseSourceSpan,
public valueSpan?: ParseSourceSpan) {} public valueSpan?: ParseSourceSpan) {}
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitVariable(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitVariable(this);
}
} }
export class Reference implements Node { export class Reference implements Node {
constructor( constructor(
public name: string, public value: string, public sourceSpan: ParseSourceSpan, public name: string, public value: string, public sourceSpan: ParseSourceSpan,
public valueSpan?: ParseSourceSpan) {} public valueSpan?: ParseSourceSpan) {}
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitReference(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitReference(this);
}
} }
export class Icu implements Node { export class Icu implements Node {
@ -115,7 +135,9 @@ export class Icu implements Node {
public vars: {[name: string]: BoundText}, public vars: {[name: string]: BoundText},
public placeholders: {[name: string]: Text|BoundText}, public sourceSpan: ParseSourceSpan, public placeholders: {[name: string]: Text|BoundText}, public sourceSpan: ParseSourceSpan,
public i18n?: I18nMeta) {} public i18n?: I18nMeta) {}
visit<Result>(visitor: Visitor<Result>): Result { return visitor.visitIcu(this); } visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitIcu(this);
}
} }
export interface Visitor<Result = any> { export interface Visitor<Result = any> {
@ -210,16 +232,34 @@ export class TransformVisitor implements Visitor<Node> {
return template; return template;
} }
visitContent(content: Content): Node { return content; } visitContent(content: Content): Node {
return content;
}
visitVariable(variable: Variable): Node { return variable; } visitVariable(variable: Variable): Node {
visitReference(reference: Reference): Node { return reference; } return variable;
visitTextAttribute(attribute: TextAttribute): Node { return attribute; } }
visitBoundAttribute(attribute: BoundAttribute): Node { return attribute; } visitReference(reference: Reference): Node {
visitBoundEvent(attribute: BoundEvent): Node { return attribute; } return reference;
visitText(text: Text): Node { return text; } }
visitBoundText(text: BoundText): Node { return text; } visitTextAttribute(attribute: TextAttribute): Node {
visitIcu(icu: Icu): Node { return icu; } return attribute;
}
visitBoundAttribute(attribute: BoundAttribute): Node {
return attribute;
}
visitBoundEvent(attribute: BoundEvent): Node {
return attribute;
}
visitText(text: Text): Node {
return text;
}
visitBoundText(text: BoundText): Node {
return text;
}
visitIcu(icu: Icu): Node {
return icu;
}
} }
export function visitAll<Result>(visitor: Visitor<Result>, nodes: Node[]): Result[] { export function visitAll<Result>(visitor: Visitor<Result>, nodes: Node[]): Result[] {

View File

@ -280,8 +280,7 @@ export function compileFactoryFunction(meta: R3FactoryMetadata): R3FactoryFn {
`${meta.name}_Factory`), `${meta.name}_Factory`),
statements, statements,
type: o.expressionType(o.importExpr( type: o.expressionType(o.importExpr(
R3.FactoryDef, R3.FactoryDef, [typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType]))
[typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType]))
}; };
} }
@ -402,7 +401,8 @@ export function dependenciesFromGlobalMetadata(
// Construct the dependency. // Construct the dependency.
deps.push({ deps.push({
token, token,
attribute: null, resolved, attribute: null,
resolved,
host: !!dependency.isHost, host: !!dependency.isHost,
optional: !!dependency.isOptional, optional: !!dependency.isOptional,
self: !!dependency.isSelf, self: !!dependency.isSelf,

View File

@ -21,8 +21,8 @@ export class R3JitReflector implements CompileReflector {
resolveExternalReference(ref: o.ExternalReference): any { resolveExternalReference(ref: o.ExternalReference): any {
// This reflector only handles @angular/core imports. // This reflector only handles @angular/core imports.
if (ref.moduleName !== '@angular/core') { if (ref.moduleName !== '@angular/core') {
throw new Error( throw new Error(`Cannot resolve external reference to ${
`Cannot resolve external reference to ${ref.moduleName}, only references to @angular/core are supported.`); ref.moduleName}, only references to @angular/core are supported.`);
} }
if (!this.context.hasOwnProperty(ref.name!)) { if (!this.context.hasOwnProperty(ref.name!)) {
throw new Error(`No value provided for @angular/core symbol '${ref.name!}'.`); throw new Error(`No value provided for @angular/core symbol '${ref.name!}'.`);
@ -30,19 +30,35 @@ export class R3JitReflector implements CompileReflector {
return this.context[ref.name!]; return this.context[ref.name!];
} }
parameters(typeOrFunc: any): any[][] { throw new Error('Not implemented.'); } parameters(typeOrFunc: any): any[][] {
throw new Error('Not implemented.');
annotations(typeOrFunc: any): any[] { throw new Error('Not implemented.'); } }
shallowAnnotations(typeOrFunc: any): any[] { throw new Error('Not implemented.'); } annotations(typeOrFunc: any): any[] {
throw new Error('Not implemented.');
tryAnnotations(typeOrFunc: any): any[] { throw new Error('Not implemented.'); } }
propMetadata(typeOrFunc: any): {[key: string]: any[];} { throw new Error('Not implemented.'); } shallowAnnotations(typeOrFunc: any): any[] {
throw new Error('Not implemented.');
hasLifecycleHook(type: any, lcProperty: string): boolean { throw new Error('Not implemented.'); } }
guards(typeOrFunc: any): {[key: string]: any;} { throw new Error('Not implemented.'); } tryAnnotations(typeOrFunc: any): any[] {
throw new Error('Not implemented.');
componentModuleUrl(type: any, cmpMetadata: any): string { throw new Error('Not implemented.'); } }
propMetadata(typeOrFunc: any): {[key: string]: any[];} {
throw new Error('Not implemented.');
}
hasLifecycleHook(type: any, lcProperty: string): boolean {
throw new Error('Not implemented.');
}
guards(typeOrFunc: any): {[key: string]: any;} {
throw new Error('Not implemented.');
}
componentModuleUrl(type: any, cmpMetadata: any): string {
throw new Error('Not implemented.');
}
} }

View File

@ -12,9 +12,9 @@ import {mapLiteral} from '../output/map_util';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {OutputContext} from '../util'; import {OutputContext} from '../util';
import {R3DependencyMetadata, R3FactoryTarget, compileFactoryFunction} from './r3_factory'; import {compileFactoryFunction, R3DependencyMetadata, R3FactoryTarget} from './r3_factory';
import {Identifiers as R3} from './r3_identifiers'; import {Identifiers as R3} from './r3_identifiers';
import {R3Reference, convertMetaToOutput, jitOnlyGuardedExpression, mapToMapExpression} from './util'; import {convertMetaToOutput, jitOnlyGuardedExpression, mapToMapExpression, R3Reference} from './util';
export interface R3NgModuleDef { export interface R3NgModuleDef {
expression: o.Expression; expression: o.Expression;
@ -108,9 +108,7 @@ export function compileNgModule(meta: R3NgModuleMetadata): R3NgModuleDef {
} = meta; } = meta;
const additionalStatements: o.Statement[] = []; const additionalStatements: o.Statement[] = [];
const definitionMap = { const definitionMap = {type: internalType} as {
type: internalType
} as{
type: o.Expression, type: o.Expression,
bootstrap: o.Expression, bootstrap: o.Expression,
declarations: o.Expression, declarations: o.Expression,
@ -288,7 +286,8 @@ export function compileNgModuleFromRender2(
/* name */ 'ɵinj', /* name */ 'ɵinj',
/* type */ o.INFERRED_TYPE, /* type */ o.INFERRED_TYPE,
/* modifiers */[o.StmtModifier.Static], /* modifiers */[o.StmtModifier.Static],
/* initializer */ injectorDef, )], /* initializer */ injectorDef,
)],
/* getters */[], /* getters */[],
/* constructorMethod */ new o.ClassMethod(null, [], []), /* constructorMethod */ new o.ClassMethod(null, [], []),
/* methods */[])); /* methods */[]));

View File

@ -10,9 +10,9 @@ import {CompilePipeMetadata, identifierName} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector'; import {CompileReflector} from '../compile_reflector';
import {DefinitionKind} from '../constant_pool'; import {DefinitionKind} from '../constant_pool';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {OutputContext, error} from '../util'; import {error, OutputContext} from '../util';
import {R3DependencyMetadata, R3FactoryTarget, compileFactoryFunction, dependenciesFromGlobalMetadata} from './r3_factory'; import {compileFactoryFunction, dependenciesFromGlobalMetadata, R3DependencyMetadata, R3FactoryTarget} from './r3_factory';
import {Identifiers as R3} from './r3_identifiers'; import {Identifiers as R3} from './r3_identifiers';
import {R3Reference, typeWithParameters, wrapReference} from './util'; import {R3Reference, typeWithParameters, wrapReference} from './util';

View File

@ -260,8 +260,8 @@ class HtmlAstToIvyAst implements html.Visitor {
return null; return null;
} }
if (!isI18nRootNode(expansion.i18n)) { if (!isI18nRootNode(expansion.i18n)) {
throw new Error( throw new Error(`Invalid type "${expansion.i18n.constructor}" for "i18n" property of ${
`Invalid type "${expansion.i18n.constructor}" for "i18n" property of ${expansion.sourceSpan.toString()}. Expected a "Message"`); expansion.sourceSpan.toString()}. Expected a "Message"`);
} }
const message = expansion.i18n; const message = expansion.i18n;
const vars: {[name: string]: t.BoundText} = {}; const vars: {[name: string]: t.BoundText} = {};
@ -284,9 +284,13 @@ class HtmlAstToIvyAst implements html.Visitor {
return new t.Icu(vars, placeholders, expansion.sourceSpan, message); return new t.Icu(vars, placeholders, expansion.sourceSpan, message);
} }
visitExpansionCase(expansionCase: html.ExpansionCase): null { return null; } visitExpansionCase(expansionCase: html.ExpansionCase): null {
return null;
}
visitComment(comment: html.Comment): null { return null; } visitComment(comment: html.Comment): null {
return null;
}
// convert view engine `ParsedProperty` to a format suitable for IVY // convert view engine `ParsedProperty` to a format suitable for IVY
private extractAttributes( private extractAttributes(
@ -460,18 +464,26 @@ class NonBindableVisitor implements html.Visitor {
ast.startSourceSpan, ast.endSourceSpan); ast.startSourceSpan, ast.endSourceSpan);
} }
visitComment(comment: html.Comment): any { return null; } visitComment(comment: html.Comment): any {
return null;
}
visitAttribute(attribute: html.Attribute): t.TextAttribute { visitAttribute(attribute: html.Attribute): t.TextAttribute {
return new t.TextAttribute( return new t.TextAttribute(
attribute.name, attribute.value, attribute.sourceSpan, undefined, attribute.i18n); attribute.name, attribute.value, attribute.sourceSpan, undefined, attribute.i18n);
} }
visitText(text: html.Text): t.Text { return new t.Text(text.value, text.sourceSpan); } visitText(text: html.Text): t.Text {
return new t.Text(text.value, text.sourceSpan);
}
visitExpansion(expansion: html.Expansion): any { return null; } visitExpansion(expansion: html.Expansion): any {
return null;
}
visitExpansionCase(expansionCase: html.ExpansionCase): any { return null; } visitExpansionCase(expansionCase: html.ExpansionCase): any {
return null;
}
} }
const NON_BINDABLE_VISITOR = new NonBindableVisitor(); const NON_BINDABLE_VISITOR = new NonBindableVisitor();

View File

@ -13,8 +13,7 @@ import {OutputContext} from '../util';
/** /**
* Convert an object map with `Expression` values into a `LiteralMapExpr`. * Convert an object map with `Expression` values into a `LiteralMapExpr`.
*/ */
export function mapToMapExpression(map: {[key: string]: o.Expression | undefined}): export function mapToMapExpression(map: {[key: string]: o.Expression|undefined}): o.LiteralMapExpr {
o.LiteralMapExpr {
const result = Object.keys(map).map( const result = Object.keys(map).map(
key => ({ key => ({
key, key,

View File

@ -20,17 +20,17 @@ import {CssSelector, SelectorMatcher} from '../../selector';
import {ShadowCss} from '../../shadow_css'; import {ShadowCss} from '../../shadow_css';
import {CONTENT_ATTR, HOST_ATTR} from '../../style_compiler'; import {CONTENT_ATTR, HOST_ATTR} from '../../style_compiler';
import {BindingParser} from '../../template_parser/binding_parser'; import {BindingParser} from '../../template_parser/binding_parser';
import {OutputContext, error} from '../../util'; import {error, OutputContext} from '../../util';
import {BoundEvent} from '../r3_ast'; import {BoundEvent} from '../r3_ast';
import {R3DependencyMetadata, R3FactoryTarget, R3ResolvedDependencyType, compileFactoryFunction} from '../r3_factory'; import {compileFactoryFunction, R3DependencyMetadata, R3FactoryTarget, R3ResolvedDependencyType} from '../r3_factory';
import {Identifiers as R3} from '../r3_identifiers'; import {Identifiers as R3} from '../r3_identifiers';
import {Render3ParseResult} from '../r3_template_transform'; import {Render3ParseResult} from '../r3_template_transform';
import {prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, typeWithParameters} from '../util'; import {prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, typeWithParameters} from '../util';
import {R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from './api'; import {R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from './api';
import {MIN_STYLING_BINDING_SLOTS_REQUIRED, StylingBuilder, StylingInstructionCall} from './styling_builder'; import {MIN_STYLING_BINDING_SLOTS_REQUIRED, StylingBuilder, StylingInstructionCall} from './styling_builder';
import {BindingScope, TemplateDefinitionBuilder, ValueConverter, makeBindingParser, prepareEventListenerParameters, renderFlagCheckIfStmt, resolveSanitizationFn} from './template'; import {BindingScope, makeBindingParser, prepareEventListenerParameters, renderFlagCheckIfStmt, resolveSanitizationFn, TemplateDefinitionBuilder, ValueConverter} from './template';
import {CONTEXT_NAME, DefinitionMap, RENDER_FLAGS, TEMPORARY_NAME, asLiteral, chainedInstruction, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator} from './util'; import {asLiteral, chainedInstruction, conditionallyCreateMapObjectLiteral, CONTEXT_NAME, DefinitionMap, getQueryPredicate, RENDER_FLAGS, TEMPORARY_NAME, temporaryAllocator} from './util';
const EMPTY_ARRAY: any[] = []; const EMPTY_ARRAY: any[] = [];
@ -65,9 +65,10 @@ function baseDirectiveFields(
// e.g. `hostBindings: (rf, ctx) => { ... } // e.g. `hostBindings: (rf, ctx) => { ... }
definitionMap.set( definitionMap.set(
'hostBindings', createHostBindingsFunction( 'hostBindings',
meta.host, meta.typeSourceSpan, bindingParser, constantPool, createHostBindingsFunction(
meta.selector || '', meta.name, definitionMap)); meta.host, meta.typeSourceSpan, bindingParser, constantPool, meta.selector || '',
meta.name, definitionMap));
// e.g 'inputs: {a: 'a'}` // e.g 'inputs: {a: 'a'}`
definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true)); definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true));
@ -85,8 +86,7 @@ function baseDirectiveFields(
/** /**
* Add features to the definition map. * Add features to the definition map.
*/ */
function addFeatures( function addFeatures(definitionMap: DefinitionMap, meta: R3DirectiveMetadata|R3ComponentMetadata) {
definitionMap: DefinitionMap, meta: R3DirectiveMetadata | R3ComponentMetadata) {
// e.g. `features: [NgOnChangesFeature]` // e.g. `features: [NgOnChangesFeature]`
const features: o.Expression[] = []; const features: o.Expression[] = [];
@ -148,7 +148,8 @@ export function compileComponentFromMetadata(
const selectorAttributes = firstSelector.getAttrs(); const selectorAttributes = firstSelector.getAttrs();
if (selectorAttributes.length) { if (selectorAttributes.length) {
definitionMap.set( definitionMap.set(
'attrs', constantPool.getConstLiteral( 'attrs',
constantPool.getConstLiteral(
o.literalArr(selectorAttributes.map( o.literalArr(selectorAttributes.map(
value => value != null ? o.literal(value) : o.literal(undefined))), value => value != null ? o.literal(value) : o.literal(undefined))),
/* forceShared */ true)); /* forceShared */ true));
@ -372,7 +373,8 @@ function queriesFromGlobalMetadata(
propertyName: query.propertyName, propertyName: query.propertyName,
first: query.first, first: query.first,
predicate: selectorsFromGlobalMetadata(query.selectors, outputCtx), predicate: selectorsFromGlobalMetadata(query.selectors, outputCtx),
descendants: query.descendants, read, descendants: query.descendants,
read,
static: !!query.static static: !!query.static
}; };
}); });
@ -817,8 +819,7 @@ export interface ParsedHostBindings {
specialAttributes: {styleAttr?: string; classAttr?: string;}; specialAttributes: {styleAttr?: string; classAttr?: string;};
} }
export function parseHostBindings(host: {[key: string]: string | o.Expression}): export function parseHostBindings(host: {[key: string]: string|o.Expression}): ParsedHostBindings {
ParsedHostBindings {
const attributes: {[key: string]: o.Expression} = {}; const attributes: {[key: string]: o.Expression} = {};
const listeners: {[key: string]: string} = {}; const listeners: {[key: string]: string} = {};
const properties: {[key: string]: string} = {}; const properties: {[key: string]: string} = {};
@ -893,5 +894,7 @@ export function verifyHostBindings(
function compileStyles(styles: string[], selector: string, hostSelector: string): string[] { function compileStyles(styles: string[], selector: string, hostSelector: string): string[] {
const shadowCss = new ShadowCss(); const shadowCss = new ShadowCss();
return styles.map(style => { return shadowCss !.shimCssText(style, selector, hostSelector); }); return styles.map(style => {
return shadowCss!.shimCssText(style, selector, hostSelector);
});
} }

View File

@ -66,9 +66,15 @@ export class I18nContext {
updatePlaceholderMap(this.placeholders, ph, content); updatePlaceholderMap(this.placeholders, ph, content);
} }
get icus() { return this._registry.icus; } get icus() {
get isRoot() { return this.level === 0; } return this._registry.icus;
get isResolved() { return this._unresolvedCtxCount === 0; } }
get isRoot() {
return this.level === 0;
}
get isResolved() {
return this._unresolvedCtxCount === 0;
}
getSerializedPlaceholders() { getSerializedPlaceholders() {
const result = new Map<string, any[]>(); const result = new Map<string, any[]>();
@ -78,7 +84,9 @@ export class I18nContext {
} }
// public API to accumulate i18n-related content // public API to accumulate i18n-related content
appendBinding(binding: AST) { this.bindings.add(binding); } appendBinding(binding: AST) {
this.bindings.add(binding);
}
appendIcu(name: string, ref: o.Expression) { appendIcu(name: string, ref: o.Expression) {
updatePlaceholderMap(this._registry.icus, name, ref); updatePlaceholderMap(this._registry.icus, name, ref);
} }

View File

@ -47,23 +47,32 @@ export function createGoogleGetMsgStatements(
* placeholders in `{$placeholder}` (for plain messages) or `{PLACEHOLDER}` (inside ICUs) format. * placeholders in `{$placeholder}` (for plain messages) or `{PLACEHOLDER}` (inside ICUs) format.
*/ */
class GetMsgSerializerVisitor implements i18n.Visitor { class GetMsgSerializerVisitor implements i18n.Visitor {
private formatPh(value: string): string { return `{$${formatI18nPlaceholderName(value)}}`; } private formatPh(value: string): string {
return `{$${formatI18nPlaceholderName(value)}}`;
}
visitText(text: i18n.Text): any { return text.value; } visitText(text: i18n.Text): any {
return text.value;
}
visitContainer(container: i18n.Container): any { visitContainer(container: i18n.Container): any {
return container.children.map(child => child.visit(this)).join(''); return container.children.map(child => child.visit(this)).join('');
} }
visitIcu(icu: i18n.Icu): any { return serializeIcuNode(icu); } visitIcu(icu: i18n.Icu): any {
return serializeIcuNode(icu);
}
visitTagPlaceholder(ph: i18n.TagPlaceholder): any { visitTagPlaceholder(ph: i18n.TagPlaceholder): any {
return ph.isVoid ? return ph.isVoid ?
this.formatPh(ph.startName) : this.formatPh(ph.startName) :
`${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`; `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${
this.formatPh(ph.closeName)}`;
} }
visitPlaceholder(ph: i18n.Placeholder): any { return this.formatPh(ph.name); } visitPlaceholder(ph: i18n.Placeholder): any {
return this.formatPh(ph.name);
}
visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): any { visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): any {
return this.formatPh(ph.name); return this.formatPh(ph.name);

View File

@ -11,7 +11,9 @@ import * as i18n from '../../../i18n/i18n_ast';
import {formatI18nPlaceholderName} from './util'; import {formatI18nPlaceholderName} from './util';
class IcuSerializerVisitor implements i18n.Visitor { class IcuSerializerVisitor implements i18n.Visitor {
visitText(text: i18n.Text): any { return text.value; } visitText(text: i18n.Text): any {
return text.value;
}
visitContainer(container: i18n.Container): any { visitContainer(container: i18n.Container): any {
return container.children.map(child => child.visit(this)).join(''); return container.children.map(child => child.visit(this)).join('');
@ -27,10 +29,13 @@ class IcuSerializerVisitor implements i18n.Visitor {
visitTagPlaceholder(ph: i18n.TagPlaceholder): any { visitTagPlaceholder(ph: i18n.TagPlaceholder): any {
return ph.isVoid ? return ph.isVoid ?
this.formatPh(ph.startName) : this.formatPh(ph.startName) :
`${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`; `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${
this.formatPh(ph.closeName)}`;
} }
visitPlaceholder(ph: i18n.Placeholder): any { return this.formatPh(ph.name); } visitPlaceholder(ph: i18n.Placeholder): any {
return this.formatPh(ph.name);
}
visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): any { visitIcuPlaceholder(ph: i18n.IcuPlaceholder, context?: any): any {
return this.formatPh(ph.name); return this.formatPh(ph.name);

View File

@ -28,7 +28,9 @@ class MessagePiece {
} }
class LiteralPiece extends MessagePiece {} class LiteralPiece extends MessagePiece {}
class PlaceholderPiece extends MessagePiece { class PlaceholderPiece extends MessagePiece {
constructor(name: string) { super(formatI18nPlaceholderName(name, /* useCamelCase */ false)); } constructor(name: string) {
super(formatI18nPlaceholderName(name, /* useCamelCase */ false));
}
} }
/** /**

View File

@ -8,12 +8,12 @@
import {computeDecimalDigest, computeDigest, decimalDigest} from '../../../i18n/digest'; import {computeDecimalDigest, computeDigest, decimalDigest} from '../../../i18n/digest';
import * as i18n from '../../../i18n/i18n_ast'; import * as i18n from '../../../i18n/i18n_ast';
import {VisitNodeFn, createI18nMessageFactory} from '../../../i18n/i18n_parser'; import {createI18nMessageFactory, VisitNodeFn} from '../../../i18n/i18n_parser';
import * as html from '../../../ml_parser/ast'; import * as html from '../../../ml_parser/ast';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../../ml_parser/interpolation_config'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../../ml_parser/interpolation_config';
import * as o from '../../../output/output_ast'; import * as o from '../../../output/output_ast';
import {I18N_ATTR, I18N_ATTR_PREFIX, hasI18nAttrs, icuFromI18nMessage} from './util'; import {hasI18nAttrs, I18N_ATTR, I18N_ATTR_PREFIX, icuFromI18nMessage} from './util';
export type I18nMeta = { export type I18nMeta = {
id?: string, id?: string,
@ -134,10 +134,18 @@ export class I18nMetaVisitor implements html.Visitor {
return expansion; return expansion;
} }
visitText(text: html.Text): any { return text; } visitText(text: html.Text): any {
visitAttribute(attribute: html.Attribute): any { return attribute; } return text;
visitComment(comment: html.Comment): any { return comment; } }
visitExpansionCase(expansionCase: html.ExpansionCase): any { return expansionCase; } visitAttribute(attribute: html.Attribute): any {
return attribute;
}
visitComment(comment: html.Comment): any {
return comment;
}
visitExpansionCase(expansionCase: html.ExpansionCase): any {
return expansionCase;
}
/** /**
* Parse the general form `meta` passed into extract the explicit metadata needed to create a * Parse the general form `meta` passed into extract the explicit metadata needed to create a

View File

@ -110,7 +110,11 @@ export function stripUnnecessaryQuotes(value: string): string {
} }
export function hyphenate(value: string): string { export function hyphenate(value: string): string {
return value.replace(/[a-z][A-Z]/g, v => { return value
.replace(
/[a-z][A-Z]/g,
v => {
return v.charAt(0) + '-' + v.charAt(1); return v.charAt(0) + '-' + v.charAt(1);
}).toLowerCase(); })
.toLowerCase();
} }

View File

@ -226,7 +226,10 @@ export class StylingBuilder {
const entry: BoundStylingEntry = { const entry: BoundStylingEntry = {
name: property, name: property,
sanitize: property ? isStyleSanitizable(property) : true, sanitize: property ? isStyleSanitizable(property) : true,
unit: unit || bindingUnit, value, sourceSpan, hasOverrideFlag unit: unit || bindingUnit,
value,
sourceSpan,
hasOverrideFlag
}; };
if (isMapBased) { if (isMapBased) {
this._styleMapInput = entry; this._styleMapInput = entry;

View File

@ -22,7 +22,9 @@ import {BoundAttribute, BoundEvent, Element, Node, Reference, Template, TextAttr
/** /**
* A logical target for analysis, which could contain a template or other types of bindings. * A logical target for analysis, which could contain a template or other types of bindings.
*/ */
export interface Target { template?: Node[]; } export interface Target {
template?: Node[];
}
/** /**
* Metadata regarding a directive that's needed to match it against template elements. This is * Metadata regarding a directive that's needed to match it against template elements. This is
@ -67,7 +69,9 @@ export interface DirectiveMeta {
* *
* The returned `BoundTarget` has an API for extracting information about the processed target. * The returned `BoundTarget` has an API for extracting information about the processed target.
*/ */
export interface TargetBinder<D extends DirectiveMeta> { bind(target: Target): BoundTarget<D>; } export interface TargetBinder<D extends DirectiveMeta> {
bind(target: Target): BoundTarget<D>;
}
/** /**
* Result of performing the binding operation against a `Target`. * Result of performing the binding operation against a `Target`.

View File

@ -217,11 +217,17 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
return {directives, bindings, references}; return {directives, bindings, references};
} }
private ingest(template: Node[]): void { template.forEach(node => node.visit(this)); } private ingest(template: Node[]): void {
template.forEach(node => node.visit(this));
}
visitElement(element: Element): void { this.visitElementOrTemplate(element.name, element); } visitElement(element: Element): void {
this.visitElementOrTemplate(element.name, element);
}
visitTemplate(template: Template): void { this.visitElementOrTemplate('ng-template', template); } visitTemplate(template: Template): void {
this.visitElementOrTemplate('ng-template', template);
}
visitElementOrTemplate(elementName: string, node: Element|Template): void { visitElementOrTemplate(elementName: string, node: Element|Template): void {
// First, determine the HTML shape of the node for the purpose of directive matching. // First, determine the HTML shape of the node for the purpose of directive matching.
@ -432,11 +438,17 @@ class TemplateBinder extends RecursiveAstVisitor implements Visitor {
// The remaining visitors are concerned with processing AST expressions within template bindings // The remaining visitors are concerned with processing AST expressions within template bindings
visitBoundAttribute(attribute: BoundAttribute) { attribute.value.visit(this); } visitBoundAttribute(attribute: BoundAttribute) {
attribute.value.visit(this);
}
visitBoundEvent(event: BoundEvent) { event.handler.visit(this); } visitBoundEvent(event: BoundEvent) {
event.handler.visit(this);
}
visitBoundText(text: BoundText) { text.value.visit(this); } visitBoundText(text: BoundText) {
text.value.visit(this);
}
visitPipe(ast: BindingPipe, context: any): any { visitPipe(ast: BindingPipe, context: any): any {
this.usedPipes.add(ast.name); this.usedPipes.add(ast.name);
return super.visitPipe(ast, context); return super.visitPipe(ast, context);
@ -526,7 +538,9 @@ export class R3BoundTarget<DirectiveT extends DirectiveMeta> implements BoundTar
return this.symbols.get(symbol) || null; return this.symbols.get(symbol) || null;
} }
getNestingLevel(template: Template): number { return this.nestingLevel.get(template) || 0; } getNestingLevel(template: Template): number {
return this.nestingLevel.get(template) || 0;
}
getUsedDirectives(): DirectiveT[] { getUsedDirectives(): DirectiveT[] {
const set = new Set<DirectiveT>(); const set = new Set<DirectiveT>();
@ -534,5 +548,7 @@ export class R3BoundTarget<DirectiveT extends DirectiveMeta> implements BoundTar
return Array.from(set.values()); return Array.from(set.values());
} }
getUsedPipes(): string[] { return Array.from(this.usedPipes); } getUsedPipes(): string[] {
return Array.from(this.usedPipes);
}
} }

View File

@ -7,7 +7,7 @@
*/ */
import {flatten, sanitizeIdentifier} from '../../compile_metadata'; import {flatten, sanitizeIdentifier} from '../../compile_metadata';
import {BindingForm, BuiltinFunctionCall, LocalResolver, convertActionBinding, convertPropertyBinding, convertUpdateArguments} from '../../compiler_util/expression_converter'; import {BindingForm, BuiltinFunctionCall, convertActionBinding, convertPropertyBinding, convertUpdateArguments, LocalResolver} from '../../compiler_util/expression_converter';
import {ConstantPool} from '../../constant_pool'; import {ConstantPool} from '../../constant_pool';
import * as core from '../../core'; import * as core from '../../core';
import {AST, AstMemoryEfficientTransformer, BindingPipe, BindingType, FunctionCall, ImplicitReceiver, Interpolation, LiteralArray, LiteralMap, LiteralPrimitive, ParsedEventType, PropertyRead} from '../../expression_parser/ast'; import {AST, AstMemoryEfficientTransformer, BindingPipe, BindingType, FunctionCall, ImplicitReceiver, Interpolation, LiteralArray, LiteralMap, LiteralPrimitive, ParsedEventType, PropertyRead} from '../../expression_parser/ast';
@ -36,9 +36,9 @@ import {I18nContext} from './i18n/context';
import {createGoogleGetMsgStatements} from './i18n/get_msg_utils'; import {createGoogleGetMsgStatements} from './i18n/get_msg_utils';
import {createLocalizeStatements} from './i18n/localize_utils'; import {createLocalizeStatements} from './i18n/localize_utils';
import {I18nMetaVisitor} from './i18n/meta'; import {I18nMetaVisitor} from './i18n/meta';
import {I18N_ICU_MAPPING_PREFIX, TRANSLATION_PREFIX, assembleBoundTextPlaceholders, assembleI18nBoundString, declareI18nVariable, getTranslationConstPrefix, i18nFormatPlaceholderNames, icuFromI18nMessage, isI18nRootNode, isSingleI18nIcu, placeholdersToParams, wrapI18nPlaceholder} from './i18n/util'; import {assembleBoundTextPlaceholders, assembleI18nBoundString, declareI18nVariable, getTranslationConstPrefix, I18N_ICU_MAPPING_PREFIX, i18nFormatPlaceholderNames, icuFromI18nMessage, isI18nRootNode, isSingleI18nIcu, placeholdersToParams, TRANSLATION_PREFIX, wrapI18nPlaceholder} from './i18n/util';
import {StylingBuilder, StylingInstruction} from './styling_builder'; import {StylingBuilder, StylingInstruction} from './styling_builder';
import {CONTEXT_NAME, IMPLICIT_REFERENCE, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, asLiteral, chainedInstruction, getAttrsForDirectiveMatching, getInterpolationArgsLength, invalid, trimTrailingNulls, unsupported} from './util'; import {asLiteral, chainedInstruction, CONTEXT_NAME, getAttrsForDirectiveMatching, getInterpolationArgsLength, IMPLICIT_REFERENCE, invalid, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, trimTrailingNulls, unsupported} from './util';
@ -207,8 +207,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
// - this template has parent i18n context // - this template has parent i18n context
// - or the template has i18n meta associated with it, // - or the template has i18n meta associated with it,
// but it's not initiated by the Element (e.g. <ng-template i18n>) // but it's not initiated by the Element (e.g. <ng-template i18n>)
const initI18nContext = const initI18nContext = this.i18nContext ||
this.i18nContext || (isI18nRootNode(i18n) && !isSingleI18nIcu(i18n) && (isI18nRootNode(i18n) && !isSingleI18nIcu(i18n) &&
!(isSingleElementTemplate(nodes) && nodes[0].i18n === i18n)); !(isSingleElementTemplate(nodes) && nodes[0].i18n === i18n));
const selfClosingI18nInstruction = hasTextChildrenOnly(nodes); const selfClosingI18nInstruction = hasTextChildrenOnly(nodes);
if (initI18nContext) { if (initI18nContext) {
@ -295,10 +295,14 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
} }
// LocalResolver // LocalResolver
getLocal(name: string): o.Expression|null { return this._bindingScope.get(name); } getLocal(name: string): o.Expression|null {
return this._bindingScope.get(name);
}
// LocalResolver // LocalResolver
notifyImplicitReceiverUse(): void { this._bindingScope.notifyImplicitReceiverUse(); } notifyImplicitReceiverUse(): void {
this._bindingScope.notifyImplicitReceiverUse();
}
private i18nTranslate( private i18nTranslate(
message: i18n.Message, params: {[name: string]: o.Expression} = {}, ref?: o.ReadVarExpr, message: i18n.Message, params: {[name: string]: o.Expression} = {}, ref?: o.ReadVarExpr,
@ -339,8 +343,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
} }
} }
private i18nBindProps(props: {[key: string]: t.Text | t.BoundText}): private i18nBindProps(props: {[key: string]: t.Text|t.BoundText}): {[key: string]: o.Expression} {
{[key: string]: o.Expression} {
const bound: {[key: string]: o.Expression} = {}; const bound: {[key: string]: o.Expression} = {};
Object.keys(props).forEach(key => { Object.keys(props).forEach(key => {
const prop = props[key]; const prop = props[key];
@ -757,7 +760,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
propertyBindings.push({ propertyBindings.push({
name: attrName, name: attrName,
sourceSpan: input.sourceSpan, sourceSpan: input.sourceSpan,
value: () => this.convertPropertyBinding(value), params value: () => this.convertPropertyBinding(value),
params
}); });
} }
} else if (inputType === BindingType.Attribute) { } else if (inputType === BindingType.Attribute) {
@ -773,7 +777,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
attributeBindings.push({ attributeBindings.push({
name: attrName, name: attrName,
sourceSpan: input.sourceSpan, sourceSpan: input.sourceSpan,
value: () => this.convertPropertyBinding(boundValue), params value: () => this.convertPropertyBinding(boundValue),
params
}); });
} }
} else { } else {
@ -1016,13 +1021,21 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
return null; return null;
} }
private allocateDataSlot() { return this._dataIndex++; } private allocateDataSlot() {
return this._dataIndex++;
}
getConstCount() { return this._dataIndex; } getConstCount() {
return this._dataIndex;
}
getVarCount() { return this._pureFunctionSlots; } getVarCount() {
return this._pureFunctionSlots;
}
getConsts() { return this._constants; } getConsts() {
return this._constants;
}
getNgContentSelectors(): o.Expression|null { getNgContentSelectors(): o.Expression|null {
return this._ngContentReservedSlots.length ? return this._ngContentReservedSlots.length ?
@ -1030,7 +1043,9 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
null; null;
} }
private bindingContext() { return `${this._bindingContext++}`; } private bindingContext() {
return `${this._bindingContext++}`;
}
private templatePropertyBindings( private templatePropertyBindings(
templateIndex: number, attrs: (t.BoundAttribute|t.TextAttribute)[]) { templateIndex: number, attrs: (t.BoundAttribute|t.TextAttribute)[]) {
@ -1092,8 +1107,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
calls.push({ calls.push({
sourceSpan: call.sourceSpan, sourceSpan: call.sourceSpan,
value: () => { value: () => {
return call return call.params(
.params(
value => (call.supportsInterpolation && value instanceof Interpolation) ? value => (call.supportsInterpolation && value instanceof Interpolation) ?
this.getUpdateInstructionArguments(value) : this.getUpdateInstructionArguments(value) :
this.convertPropertyBinding(value)) as o.Expression[]; this.convertPropertyBinding(value)) as o.Expression[];
@ -1228,8 +1242,9 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
private matchDirectives(elementName: string, elOrTpl: t.Element|t.Template) { private matchDirectives(elementName: string, elOrTpl: t.Element|t.Template) {
if (this.directiveMatcher) { if (this.directiveMatcher) {
const selector = createCssSelector(elementName, getAttrsForDirectiveMatching(elOrTpl)); const selector = createCssSelector(elementName, getAttrsForDirectiveMatching(elOrTpl));
this.directiveMatcher.match( this.directiveMatcher.match(selector, (cssSelector, staticType) => {
selector, (cssSelector, staticType) => { this.directives.add(staticType); }); this.directives.add(staticType);
});
} }
} }
@ -1570,9 +1585,8 @@ const SHARED_CONTEXT_KEY = '$$shared_ctx$$';
* declaration should always come before the local ref declaration. * declaration should always come before the local ref declaration.
*/ */
type BindingData = { type BindingData = {
retrievalLevel: number; lhs: o.Expression; declareLocalCallback?: DeclareLocalVarCallback; retrievalLevel: number; lhs: o.Expression;
declare: boolean; declareLocalCallback?: DeclareLocalVarCallback; declare: boolean; priority: number;
priority: number;
localRef: boolean; localRef: boolean;
}; };
@ -1580,7 +1594,11 @@ type BindingData = {
* The sorting priority of a local variable declaration. Higher numbers * The sorting priority of a local variable declaration. Higher numbers
* mean the declaration will appear first in the generated code. * mean the declaration will appear first in the generated code.
*/ */
const enum DeclarationPriority { DEFAULT = 0, CONTEXT = 1, SHARED_CONTEXT = 2 } const enum DeclarationPriority {
DEFAULT = 0,
CONTEXT = 1,
SHARED_CONTEXT = 2
}
export class BindingScope implements LocalResolver { export class BindingScope implements LocalResolver {
/** Keeps a map from local variables to their BindingData. */ /** Keeps a map from local variables to their BindingData. */
@ -1669,7 +1687,9 @@ export class BindingScope implements LocalResolver {
} }
// Implemented as part of LocalResolver. // Implemented as part of LocalResolver.
getLocal(name: string): (o.Expression|null) { return this.get(name); } getLocal(name: string): (o.Expression|null) {
return this.get(name);
}
// Implemented as part of LocalResolver. // Implemented as part of LocalResolver.
notifyImplicitReceiverUse(): void { notifyImplicitReceiverUse(): void {
@ -1771,7 +1791,9 @@ export class BindingScope implements LocalResolver {
[]; [];
} }
isListenerScope() { return this.parent && this.parent.bindingLevel === this.bindingLevel; } isListenerScope() {
return this.parent && this.parent.bindingLevel === this.bindingLevel;
}
variableDeclarations(): o.Statement[] { variableDeclarations(): o.Statement[] {
let currentContextLevel = 0; let currentContextLevel = 0;
@ -1780,7 +1802,8 @@ export class BindingScope implements LocalResolver {
.sort((a, b) => b.retrievalLevel - a.retrievalLevel || b.priority - a.priority) .sort((a, b) => b.retrievalLevel - a.retrievalLevel || b.priority - a.priority)
.reduce((stmts: o.Statement[], value: BindingData) => { .reduce((stmts: o.Statement[], value: BindingData) => {
const levelDiff = this.bindingLevel - value.retrievalLevel; const levelDiff = this.bindingLevel - value.retrievalLevel;
const currStmts = value.declareLocalCallback !(this, levelDiff - currentContextLevel); const currStmts =
value.declareLocalCallback!(this, levelDiff - currentContextLevel);
currentContextLevel = levelDiff; currentContextLevel = levelDiff;
return stmts.concat(currStmts); return stmts.concat(currStmts);
}, []) as o.Statement[]; }, []) as o.Statement[];
@ -2126,7 +2149,8 @@ export function getTranslationDeclStmts(
const statements: o.Statement[] = [ const statements: o.Statement[] = [
declareI18nVariable(variable), declareI18nVariable(variable),
o.ifStmt( o.ifStmt(
createClosureModeGuard(), createGoogleGetMsgStatements( createClosureModeGuard(),
createGoogleGetMsgStatements(
variable, message, closureVar, variable, message, closureVar,
i18nFormatPlaceholderNames(params, /* useCamelCase */ true)), i18nFormatPlaceholderNames(params, /* useCamelCase */ true)),
createLocalizeStatements( createLocalizeStatements(

View File

@ -153,7 +153,9 @@ export class DefinitionMap {
} }
} }
toLiteralMap(): o.LiteralMapExpr { return o.literalMap(this.values); } toLiteralMap(): o.LiteralMapExpr {
return o.literalMap(this.values);
}
} }
/** /**
@ -165,8 +167,8 @@ export class DefinitionMap {
* object maps a property name to its (static) value. For any bindings, this map simply maps the * object maps a property name to its (static) value. For any bindings, this map simply maps the
* property name to an empty string. * property name to an empty string.
*/ */
export function getAttrsForDirectiveMatching(elOrTpl: t.Element | t.Template): export function getAttrsForDirectiveMatching(elOrTpl: t.Element|
{[name: string]: string} { t.Template): {[name: string]: string} {
const attributesMap: {[name: string]: string} = {}; const attributesMap: {[name: string]: string} = {};
@ -179,8 +181,12 @@ export function getAttrsForDirectiveMatching(elOrTpl: t.Element | t.Template):
} }
}); });
elOrTpl.inputs.forEach(i => { attributesMap[i.name] = ''; }); elOrTpl.inputs.forEach(i => {
elOrTpl.outputs.forEach(o => { attributesMap[o.name] = ''; }); attributesMap[i.name] = '';
});
elOrTpl.outputs.forEach(o => {
attributesMap[o.name] = '';
});
} }
return attributesMap; return attributesMap;

View File

@ -11,5 +11,7 @@
* to load templates. * to load templates.
*/ */
export class ResourceLoader { export class ResourceLoader {
get(url: string): Promise<string>|string { return ''; } get(url: string): Promise<string>|string {
return '';
}
} }

View File

@ -253,7 +253,9 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
typeNames.split(',').forEach(tag => this._schema[tag.toLowerCase()] = type); typeNames.split(',').forEach(tag => this._schema[tag.toLowerCase()] = type);
const superType = superName && this._schema[superName.toLowerCase()]; const superType = superName && this._schema[superName.toLowerCase()];
if (superType) { if (superType) {
Object.keys(superType).forEach((prop: string) => { type[prop] = superType[prop]; }); Object.keys(superType).forEach((prop: string) => {
type[prop] = superType[prop];
});
} }
properties.forEach((property: string) => { properties.forEach((property: string) => {
if (property.length > 0) { if (property.length > 0) {
@ -350,9 +352,13 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
return ctx ? ctx : SecurityContext.NONE; return ctx ? ctx : SecurityContext.NONE;
} }
getMappedPropName(propName: string): string { return _ATTR_TO_PROP[propName] || propName; } getMappedPropName(propName: string): string {
return _ATTR_TO_PROP[propName] || propName;
}
getDefaultComponentElementName(): string { return 'ng-component'; } getDefaultComponentElementName(): string {
return 'ng-component';
}
validateProperty(name: string): {error: boolean, msg?: string} { validateProperty(name: string): {error: boolean, msg?: string} {
if (name.toLowerCase().startsWith('on')) { if (name.toLowerCase().startsWith('on')) {
@ -376,7 +382,9 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
} }
} }
allKnownElementNames(): string[] { return Object.keys(this._schema); } allKnownElementNames(): string[] {
return Object.keys(this._schema);
}
normalizeAnimationStyleProperty(propName: string): string { normalizeAnimationStyleProperty(propName: string): string {
return dashCaseToCamelCase(propName); return dashCaseToCamelCase(propName);

View File

@ -118,9 +118,13 @@ export class CssSelector {
this.notSelectors.length === 0; this.notSelectors.length === 0;
} }
hasElementSelector(): boolean { return !!this.element; } hasElementSelector(): boolean {
return !!this.element;
}
setElement(element: string|null = null) { this.element = element; } setElement(element: string|null = null) {
this.element = element;
}
/** Gets a template string for an element that matches the selector. */ /** Gets a template string for an element that matches the selector. */
getMatchingElementTemplate(): string { getMatchingElementTemplate(): string {
@ -150,7 +154,9 @@ export class CssSelector {
this.attrs.push(name, value && value.toLowerCase() || ''); this.attrs.push(name, value && value.toLowerCase() || '');
} }
addClassName(name: string) { this.classNames.push(name.toLowerCase()); } addClassName(name: string) {
this.classNames.push(name.toLowerCase());
}
toString(): string { toString(): string {
let res: string = this.element || ''; let res: string = this.element || '';

View File

@ -175,8 +175,9 @@ export class ShadowCss {
**/ **/
private _insertPolyfillDirectivesInCssText(cssText: string): string { private _insertPolyfillDirectivesInCssText(cssText: string): string {
// Difference with webcomponents.js: does not handle comments // Difference with webcomponents.js: does not handle comments
return cssText.replace( return cssText.replace(_cssContentNextSelectorRe, function(...m: string[]) {
_cssContentNextSelectorRe, function(...m: string[]) { return m[2] + '{'; }); return m[2] + '{';
});
} }
/* /*
@ -505,7 +506,9 @@ class SafeSelector {
return content.replace(/__ph-(\d+)__/g, (ph, index) => this.placeholders[+index]); return content.replace(/__ph-(\d+)__/g, (ph, index) => this.placeholders[+index]);
} }
content(): string { return this._content; } content(): string {
return this._content;
}
} }
const _cssContentNextSelectorRe = const _cssContentNextSelectorRe =

View File

@ -28,14 +28,28 @@ export abstract class SummaryResolver<T> {
export class JitSummaryResolver implements SummaryResolver<Type> { export class JitSummaryResolver implements SummaryResolver<Type> {
private _summaries = new Map<Type, Summary<Type>>(); private _summaries = new Map<Type, Summary<Type>>();
isLibraryFile(): boolean { return false; } isLibraryFile(): boolean {
toSummaryFileName(fileName: string): string { return fileName; } return false;
fromSummaryFileName(fileName: string): string { return fileName; } }
toSummaryFileName(fileName: string): string {
return fileName;
}
fromSummaryFileName(fileName: string): string {
return fileName;
}
resolveSummary(reference: Type): Summary<Type>|null { resolveSummary(reference: Type): Summary<Type>|null {
return this._summaries.get(reference) || null; return this._summaries.get(reference) || null;
} }
getSymbolsOf(): Type[] { return []; } getSymbolsOf(): Type[] {
getImportAs(reference: Type): Type { return reference; } return [];
getKnownModuleName(fileName: string) { return null; } }
addSummary(summary: Summary<Type>) { this._summaries.set(summary.symbol, summary); } getImportAs(reference: Type): Type {
return reference;
}
getKnownModuleName(fileName: string) {
return null;
}
addSummary(summary: Summary<Type>) {
this._summaries.set(summary.symbol, summary);
}
} }

View File

@ -8,7 +8,7 @@
import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata'; import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata';
import {SecurityContext} from '../core'; import {SecurityContext} from '../core';
import {ASTWithSource, AbsoluteSourceSpan, BindingPipe, BindingType, BoundElementProperty, EmptyExpr, ParsedEvent, ParsedEventType, ParsedProperty, ParsedPropertyType, ParsedVariable, ParserError, RecursiveAstVisitor, TemplateBinding, VariableBinding} from '../expression_parser/ast'; import {AbsoluteSourceSpan, ASTWithSource, BindingPipe, BindingType, BoundElementProperty, EmptyExpr, ParsedEvent, ParsedEventType, ParsedProperty, ParsedPropertyType, ParsedVariable, ParserError, RecursiveAstVisitor, TemplateBinding, VariableBinding} from '../expression_parser/ast';
import {Parser} from '../expression_parser/parser'; import {Parser} from '../expression_parser/parser';
import {InterpolationConfig} from '../ml_parser/interpolation_config'; import {InterpolationConfig} from '../ml_parser/interpolation_config';
import {mergeNsAndName} from '../ml_parser/tags'; import {mergeNsAndName} from '../ml_parser/tags';
@ -45,9 +45,13 @@ export class BindingParser {
} }
} }
get interpolationConfig(): InterpolationConfig { return this._interpolationConfig; } get interpolationConfig(): InterpolationConfig {
return this._interpolationConfig;
}
getUsedPipes(): CompilePipeSummary[] { return Array.from(this._usedPipes.values()); } getUsedPipes(): CompilePipeSummary[] {
return Array.from(this._usedPipes.values());
}
createBoundHostProperties(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan): createBoundHostProperties(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan):
ParsedProperty[]|null { ParsedProperty[]|null {
@ -61,7 +65,9 @@ export class BindingParser {
boundProps); boundProps);
} else { } else {
this._reportError( this._reportError(
`Value of the host property binding "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, `Value of the host property binding "${
propName}" needs to be a string representing an expression but got "${
expression}" (${typeof expression})`,
sourceSpan); sourceSpan);
} }
}); });
@ -89,7 +95,9 @@ export class BindingParser {
this.parseEvent(propName, expression, sourceSpan, sourceSpan, [], targetEvents); this.parseEvent(propName, expression, sourceSpan, sourceSpan, [], targetEvents);
} else { } else {
this._reportError( this._reportError(
`Value of the host listener "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, `Value of the host listener "${
propName}" needs to be a string representing an expression but got "${
expression}" (${typeof expression})`,
sourceSpan); sourceSpan);
} }
}); });
@ -183,8 +191,9 @@ export class BindingParser {
this._checkPipes(binding.value, sourceSpan); this._checkPipes(binding.value, sourceSpan);
} }
}); });
bindingsResult.warnings.forEach( bindingsResult.warnings.forEach((warning) => {
(warning) => { this._reportError(warning, sourceSpan, ParseErrorLevel.WARNING); }); this._reportError(warning, sourceSpan, ParseErrorLevel.WARNING);
});
return bindingsResult.templateBindings; return bindingsResult.templateBindings;
} catch (e) { } catch (e) {
this._reportError(`${e}`, sourceSpan); this._reportError(`${e}`, sourceSpan);
@ -401,13 +410,15 @@ export class BindingParser {
default: default:
this._reportError( this._reportError(
`The provided animation output phase value "${phase}" for "@${eventName}" is not supported (use start or done)`, `The provided animation output phase value "${phase}" for "@${
eventName}" is not supported (use start or done)`,
sourceSpan); sourceSpan);
break; break;
} }
} else { } else {
this._reportError( this._reportError(
`The animation trigger output event (@${eventName}) is missing its phase value name (start or done are currently supported)`, `The animation trigger output event (@${
eventName}) is missing its phase value name (start or done are currently supported)`,
sourceSpan); sourceSpan);
} }
} }

View File

@ -36,7 +36,9 @@ export interface TemplateAst {
export class TextAst implements TemplateAst { export class TextAst implements TemplateAst {
constructor( constructor(
public value: string, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {} public value: string, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitText(this, context); } visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitText(this, context);
}
} }
/** /**
@ -56,7 +58,9 @@ export class BoundTextAst implements TemplateAst {
*/ */
export class AttrAst implements TemplateAst { export class AttrAst implements TemplateAst {
constructor(public name: string, public value: string, public sourceSpan: ParseSourceSpan) {} constructor(public name: string, public value: string, public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitAttr(this, context); } visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitAttr(this, context);
}
} }
export const enum PropertyBindingType { export const enum PropertyBindingType {
@ -319,7 +323,9 @@ export class NullTemplateVisitor implements TemplateAstVisitor {
* in an template ast recursively. * in an template ast recursively.
*/ */
export class RecursiveTemplateAstVisitor extends NullTemplateVisitor implements TemplateAstVisitor { export class RecursiveTemplateAstVisitor extends NullTemplateVisitor implements TemplateAstVisitor {
constructor() { super(); } constructor() {
super();
}
// Nodes with children // Nodes with children
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any { visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {

View File

@ -12,7 +12,7 @@ import {CompilerConfig} from '../config';
import {SchemaMetadata} from '../core'; import {SchemaMetadata} from '../core';
import {AST, ASTWithSource, EmptyExpr, ParsedEvent, ParsedProperty, ParsedVariable} from '../expression_parser/ast'; import {AST, ASTWithSource, EmptyExpr, ParsedEvent, ParsedProperty, ParsedVariable} from '../expression_parser/ast';
import {Parser} from '../expression_parser/parser'; import {Parser} from '../expression_parser/parser';
import {Identifiers, createTokenForExternalReference, createTokenForReference} from '../identifiers'; import {createTokenForExternalReference, createTokenForReference, Identifiers} from '../identifiers';
import * as html from '../ml_parser/ast'; import * as html from '../ml_parser/ast';
import {HtmlParser, ParseTreeResult} from '../ml_parser/html_parser'; import {HtmlParser, ParseTreeResult} from '../ml_parser/html_parser';
import {removeWhitespaces, replaceNgsp} from '../ml_parser/html_whitespaces'; import {removeWhitespaces, replaceNgsp} from '../ml_parser/html_whitespaces';
@ -84,7 +84,9 @@ export class TemplateParser {
private _htmlParser: HtmlParser, private _console: Console, private _htmlParser: HtmlParser, private _console: Console,
public transforms: t.TemplateAstVisitor[]) {} public transforms: t.TemplateAstVisitor[]) {}
public get expressionParser() { return this._exprParser; } public get expressionParser() {
return this._exprParser;
}
parse( parse(
component: CompileDirectiveMetadata, template: string|ParseTreeResult, component: CompileDirectiveMetadata, template: string|ParseTreeResult,
@ -164,8 +166,9 @@ export class TemplateParser {
} }
if (this.transforms) { if (this.transforms) {
this.transforms.forEach( this.transforms.forEach((transform: t.TemplateAstVisitor) => {
(transform: t.TemplateAstVisitor) => { result = t.templateVisitAll(transform, result); }); result = t.templateVisitAll(transform, result);
});
} }
return new TemplateParseResult(result, usedPipes, errors); return new TemplateParseResult(result, usedPipes, errors);
@ -230,9 +233,13 @@ class TemplateParseVisitor implements html.Visitor {
}); });
} }
visitExpansion(expansion: html.Expansion, context: any): any { return null; } visitExpansion(expansion: html.Expansion, context: any): any {
return null;
}
visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any { return null; } visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any {
return null;
}
visitText(text: html.Text, parent: ElementContext): any { visitText(text: html.Text, parent: ElementContext): any {
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR())!; const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR())!;
@ -246,7 +253,9 @@ class TemplateParseVisitor implements html.Visitor {
return new t.AttrAst(attribute.name, attribute.value, attribute.sourceSpan); return new t.AttrAst(attribute.name, attribute.value, attribute.sourceSpan);
} }
visitComment(comment: html.Comment, context: any): any { return null; } visitComment(comment: html.Comment, context: any): any {
return null;
}
visitElement(element: html.Element, parent: ElementContext): any { visitElement(element: html.Element, parent: ElementContext): any {
const queryStartIndex = this.contentQueryStartId; const queryStartIndex = this.contentQueryStartId;
@ -355,8 +364,7 @@ class TemplateParseVisitor implements html.Visitor {
} }
parsedElement = new t.NgContentAst( parsedElement = new t.NgContentAst(
this.ngContentCount++, hasInlineTemplates ? null ! : ngContentIndex, this.ngContentCount++, hasInlineTemplates ? null! : ngContentIndex, element.sourceSpan!);
element.sourceSpan !);
} else if (isTemplateElement) { } else if (isTemplateElement) {
// `<ng-template>` element // `<ng-template>` element
this._assertAllEventsPublishedByDirectives(directiveAsts, events); this._assertAllEventsPublishedByDirectives(directiveAsts, events);
@ -573,8 +581,7 @@ class TemplateParseVisitor implements html.Visitor {
// Note: We need to check the host properties here as well, // Note: We need to check the host properties here as well,
// as we don't know the element name in the DirectiveWrapperCompiler yet. // as we don't know the element name in the DirectiveWrapperCompiler yet.
hostProperties = this._checkPropertiesInSchema(elementName, hostProperties); hostProperties = this._checkPropertiesInSchema(elementName, hostProperties);
const parsedEvents = const parsedEvents = this._bindingParser.createDirectiveHostEventAsts(directive, sourceSpan)!;
this._bindingParser.createDirectiveHostEventAsts(directive, sourceSpan) !;
this._createDirectivePropertyAsts( this._createDirectivePropertyAsts(
directive.inputs, props, directiveProperties, targetBoundDirectivePropNames); directive.inputs, props, directiveProperties, targetBoundDirectivePropNames);
elementOrDirectiveRefs.forEach((elOrDirRef) => { elementOrDirectiveRefs.forEach((elOrDirRef) => {
@ -691,11 +698,11 @@ class TemplateParseVisitor implements html.Visitor {
if (!matchElement && !this._schemaRegistry.hasElement(elName, this._schemas)) { if (!matchElement && !this._schemaRegistry.hasElement(elName, this._schemas)) {
let errorMsg = `'${elName}' is not a known element:\n`; let errorMsg = `'${elName}' is not a known element:\n`;
errorMsg += errorMsg += `1. If '${
`1. If '${elName}' is an Angular component, then verify that it is part of this module.\n`; elName}' is an Angular component, then verify that it is part of this module.\n`;
if (elName.indexOf('-') > -1) { if (elName.indexOf('-') > -1) {
errorMsg += errorMsg += `2. If '${
`2. If '${elName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.`; elName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.`;
} else { } else {
errorMsg += errorMsg +=
`2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`; `2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`;
@ -714,7 +721,8 @@ class TemplateParseVisitor implements html.Visitor {
} }
elementProps.forEach(prop => { elementProps.forEach(prop => {
this._reportError( this._reportError(
`Property binding ${prop.name} 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".`, `Property binding ${
prop.name} 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".`,
sourceSpan); sourceSpan);
}); });
} }
@ -733,7 +741,9 @@ class TemplateParseVisitor implements html.Visitor {
events.forEach(event => { events.forEach(event => {
if (event.target != null || !allDirectiveEvents.has(event.name)) { if (event.target != null || !allDirectiveEvents.has(event.name)) {
this._reportError( this._reportError(
`Event binding ${event.fullName} 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".`, `Event binding ${
event
.fullName} 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".`,
event.sourceSpan); event.sourceSpan);
} }
}); });
@ -746,16 +756,20 @@ class TemplateParseVisitor implements html.Visitor {
return boundProps.filter((boundProp) => { return boundProps.filter((boundProp) => {
if (boundProp.type === t.PropertyBindingType.Property && if (boundProp.type === t.PropertyBindingType.Property &&
!this._schemaRegistry.hasProperty(elementName, boundProp.name, this._schemas)) { !this._schemaRegistry.hasProperty(elementName, boundProp.name, this._schemas)) {
let errorMsg = let errorMsg = `Can't bind to '${boundProp.name}' since it isn't a known property of '${
`Can't bind to '${boundProp.name}' since it isn't a known property of '${elementName}'.`; elementName}'.`;
if (elementName.startsWith('ng-')) { if (elementName.startsWith('ng-')) {
errorMsg += errorMsg +=
`\n1. If '${boundProp.name}' is an Angular directive, then add 'CommonModule' to the '@NgModule.imports' of this component.` + `\n1. If '${
boundProp
.name}' is an Angular directive, then add 'CommonModule' to the '@NgModule.imports' of this component.` +
`\n2. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`; `\n2. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`;
} else if (elementName.indexOf('-') > -1) { } else if (elementName.indexOf('-') > -1) {
errorMsg += errorMsg +=
`\n1. If '${elementName}' is an Angular component and it has '${boundProp.name}' input, then verify that it is part of this module.` + `\n1. If '${elementName}' is an Angular component and it has '${
`\n2. If '${elementName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.` + boundProp.name}' input, then verify that it is part of this module.` +
`\n2. If '${
elementName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.` +
`\n3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`; `\n3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`;
} }
this._reportError(errorMsg, boundProp.sourceSpan); this._reportError(errorMsg, boundProp.sourceSpan);
@ -791,7 +805,9 @@ class NonBindableVisitor implements html.Visitor {
ast.name, html.visitAll(this, ast.attrs), [], [], [], [], [], false, [], children, ast.name, html.visitAll(this, ast.attrs), [], [], [], [], [], false, [], children,
ngContentIndex, ast.sourceSpan, ast.endSourceSpan); ngContentIndex, ast.sourceSpan, ast.endSourceSpan);
} }
visitComment(comment: html.Comment, context: any): any { return null; } visitComment(comment: html.Comment, context: any): any {
return null;
}
visitAttribute(attribute: html.Attribute, context: any): t.AttrAst { visitAttribute(attribute: html.Attribute, context: any): t.AttrAst {
return new t.AttrAst(attribute.name, attribute.value, attribute.sourceSpan); return new t.AttrAst(attribute.name, attribute.value, attribute.sourceSpan);
@ -802,9 +818,13 @@ class NonBindableVisitor implements html.Visitor {
return new t.TextAst(text.value, ngContentIndex, text.sourceSpan!); return new t.TextAst(text.value, ngContentIndex, text.sourceSpan!);
} }
visitExpansion(expansion: html.Expansion, context: any): any { return expansion; } visitExpansion(expansion: html.Expansion, context: any): any {
return expansion;
}
visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any { return expansionCase; } visitExpansionCase(expansionCase: html.ExpansionCase, context: any): any {
return expansionCase;
}
} }
/** /**
@ -859,8 +879,9 @@ class ElementContext {
findNgContentIndex(selector: CssSelector): number|null { findNgContentIndex(selector: CssSelector): number|null {
const ngContentIndices: number[] = []; const ngContentIndices: number[] = [];
this._ngContentIndexMatcher.match( this._ngContentIndexMatcher.match(selector, (selector, ngContentIndex) => {
selector, (selector, ngContentIndex) => { ngContentIndices.push(ngContentIndex); }); ngContentIndices.push(ngContentIndex);
});
ngContentIndices.sort(); ngContentIndices.sort();
if (this._wildcardNgContentIndex != null) { if (this._wildcardNgContentIndex != null) {
ngContentIndices.push(this._wildcardNgContentIndex); ngContentIndices.push(this._wildcardNgContentIndex);

View File

@ -33,9 +33,13 @@ export function createOfflineCompileUrlResolver(): UrlResolver {
* Attacker-controlled data introduced by a template could expose your * Attacker-controlled data introduced by a template could expose your
* application to XSS risks. For more detail, see the [Security Guide](http://g.co/ng/security). * application to XSS risks. For more detail, see the [Security Guide](http://g.co/ng/security).
*/ */
export interface UrlResolver { resolve(baseUrl: string, url: string): string; } export interface UrlResolver {
resolve(baseUrl: string, url: string): string;
}
export interface UrlResolverCtor { new (packagePrefix?: string|null): UrlResolver; } export interface UrlResolverCtor {
new(packagePrefix?: string|null): UrlResolver;
}
export const UrlResolver: UrlResolverCtor = class UrlResolverImpl { export const UrlResolver: UrlResolverCtor = class UrlResolverImpl {
constructor(private _packagePrefix: string|null = null) {} constructor(private _packagePrefix: string|null = null) {}

View File

@ -69,11 +69,17 @@ export class ValueTransformer implements ValueVisitor {
} }
visitStringMap(map: {[key: string]: any}, context: any): any { visitStringMap(map: {[key: string]: any}, context: any): any {
const result: {[key: string]: any} = {}; const result: {[key: string]: any} = {};
Object.keys(map).forEach(key => { result[key] = visitValue(map[key], this, context); }); Object.keys(map).forEach(key => {
result[key] = visitValue(map[key], this, context);
});
return result; return result;
} }
visitPrimitive(value: any, context: any): any { return value; } visitPrimitive(value: any, context: any): any {
visitOther(value: any, context: any): any { return value; } return value;
}
visitOther(value: any, context: any): any {
return value;
}
} }
export type SyncAsync<T> = T|Promise<T>; export type SyncAsync<T> = T|Promise<T>;
@ -86,7 +92,9 @@ export const SyncAsync = {
return value; return value;
}, },
then: <T, R>(value: SyncAsync<T>, cb: (value: T) => R | Promise<R>| SyncAsync<R>): then: <T, R>(value: SyncAsync<T>, cb: (value: T) => R | Promise<R>| SyncAsync<R>):
SyncAsync<R> => { return isPromise(value) ? value.then(cb) : cb(value);}, SyncAsync<R> => {
return isPromise(value) ? value.then(cb) : cb(value);
},
all: <T>(syncAsyncValues: SyncAsync<T>[]): SyncAsync<T[]> => { all: <T>(syncAsyncValues: SyncAsync<T>[]): SyncAsync<T[]> => {
return syncAsyncValues.some(isPromise) ? Promise.all(syncAsyncValues) : syncAsyncValues as T[]; return syncAsyncValues.some(isPromise) ? Promise.all(syncAsyncValues) : syncAsyncValues as T[];
} }

View File

@ -9,7 +9,7 @@
import {CompileDiDependencyMetadata, CompileEntryComponentMetadata, CompileProviderMetadata, CompileTokenMetadata} from '../compile_metadata'; import {CompileDiDependencyMetadata, CompileEntryComponentMetadata, CompileProviderMetadata, CompileTokenMetadata} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector'; import {CompileReflector} from '../compile_reflector';
import {DepFlags, NodeFlags} from '../core'; import {DepFlags, NodeFlags} from '../core';
import {Identifiers, createTokenForExternalReference} from '../identifiers'; import {createTokenForExternalReference, Identifiers} from '../identifiers';
import {LifecycleHooks} from '../lifecycle_reflector'; import {LifecycleHooks} from '../lifecycle_reflector';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {convertValueToOutputAst} from '../output/value_util'; import {convertValueToOutputAst} from '../output/value_util';
@ -45,7 +45,8 @@ export function providerDef(ctx: OutputContext, providerAst: ProviderAst): {
singleProviderDef(ctx, flags, providerAst.providerType, providerAst.providers[0]); singleProviderDef(ctx, flags, providerAst.providerType, providerAst.providers[0]);
return { return {
providerExpr, providerExpr,
flags: providerFlags, depsExpr, flags: providerFlags,
depsExpr,
tokenExpr: tokenExpr(ctx, providerAst.token), tokenExpr: tokenExpr(ctx, providerAst.token),
}; };
} }

View File

@ -10,11 +10,11 @@ import {AotCompilerOptions} from '../aot/compiler_options';
import {StaticReflector} from '../aot/static_reflector'; import {StaticReflector} from '../aot/static_reflector';
import {StaticSymbol} from '../aot/static_symbol'; import {StaticSymbol} from '../aot/static_symbol';
import {CompileDirectiveMetadata, CompilePipeSummary} from '../compile_metadata'; import {CompileDirectiveMetadata, CompilePipeSummary} from '../compile_metadata';
import {BindingForm, EventHandlerVars, LocalResolver, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins} from '../compiler_util/expression_converter'; import {BindingForm, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins, EventHandlerVars, LocalResolver} from '../compiler_util/expression_converter';
import {AST, ASTWithSource, Interpolation} from '../expression_parser/ast'; import {AST, ASTWithSource, Interpolation} from '../expression_parser/ast';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {ParseSourceSpan} from '../parse_util'; import {ParseSourceSpan} from '../parse_util';
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast'; import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, templateVisitAll, TextAst, VariableAst} from '../template_parser/template_ast';
import {OutputContext} from '../util'; import {OutputContext} from '../util';
@ -247,7 +247,9 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
directives: DirectiveAst[], directives: DirectiveAst[],
references: ReferenceAst[], references: ReferenceAst[],
}) { }) {
ast.directives.forEach((dirAst) => { this.visitDirective(dirAst); }); ast.directives.forEach((dirAst) => {
this.visitDirective(dirAst);
});
ast.references.forEach((ref) => { ast.references.forEach((ref) => {
let outputVarType: OutputVarType = null!; let outputVarType: OutputVarType = null!;
@ -331,8 +333,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
// for arrays. // for arrays.
return this.options.fullTemplateTypeCheck ? arr : arr.cast(o.DYNAMIC_TYPE); return this.options.fullTemplateTypeCheck ? arr : arr.cast(o.DYNAMIC_TYPE);
}, },
createLiteralMapConverter: createLiteralMapConverter: (keys: {key: string, quoted: boolean}[]) =>
(keys: {key: string, quoted: boolean}[]) => (values: o.Expression[]) => { (values: o.Expression[]) => {
const entries = keys.map((k, i) => ({ const entries = keys.map((k, i) => ({
key: k.key, key: k.key,
value: values[i], value: values[i],

View File

@ -8,7 +8,7 @@
import {CompileDirectiveMetadata, CompilePipeSummary, CompileQueryMetadata, rendererTypeName, tokenReference, viewClassName} from '../compile_metadata'; import {CompileDirectiveMetadata, CompilePipeSummary, CompileQueryMetadata, rendererTypeName, tokenReference, viewClassName} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector'; import {CompileReflector} from '../compile_reflector';
import {BindingForm, BuiltinConverter, EventHandlerVars, LocalResolver, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins} from '../compiler_util/expression_converter'; import {BindingForm, BuiltinConverter, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins, EventHandlerVars, LocalResolver} from '../compiler_util/expression_converter';
import {ArgumentType, BindingFlags, ChangeDetectionStrategy, NodeFlags, QueryBindingType, QueryValueType, ViewFlags} from '../core'; import {ArgumentType, BindingFlags, ChangeDetectionStrategy, NodeFlags, QueryBindingType, QueryValueType, ViewFlags} from '../core';
import {AST, ASTWithSource, Interpolation} from '../expression_parser/ast'; import {AST, ASTWithSource, Interpolation} from '../expression_parser/ast';
import {Identifiers} from '../identifiers'; import {Identifiers} from '../identifiers';
@ -17,7 +17,7 @@ import {isNgContainer} from '../ml_parser/tags';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {convertValueToOutputAst} from '../output/value_util'; import {convertValueToOutputAst} from '../output/value_util';
import {ParseSourceSpan} from '../parse_util'; import {ParseSourceSpan} from '../parse_util';
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAst, QueryMatch, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast'; import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAst, QueryMatch, ReferenceAst, TemplateAst, TemplateAstVisitor, templateVisitAll, TextAst, VariableAst} from '../template_parser/template_ast';
import {OutputContext} from '../util'; import {OutputContext} from '../util';
import {componentFactoryResolverProviderDef, depDef, lifecycleHookToNodeFlag, providerDef} from './provider_compiler'; import {componentFactoryResolverProviderDef, depDef, lifecycleHookToNodeFlag, providerDef} from './provider_compiler';
@ -101,7 +101,9 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
private nodes: (() => { private nodes: (() => {
sourceSpan: ParseSourceSpan | null, sourceSpan: ParseSourceSpan | null,
nodeDef: o.Expression, nodeDef: o.Expression,
nodeFlags: NodeFlags, updateDirectives?: UpdateExpression[], updateRenderer?: UpdateExpression[] nodeFlags: NodeFlags,
updateDirectives?: UpdateExpression[],
updateRenderer?: UpdateExpression[]
})[] = []; })[] = [];
private purePipeNodeIndices: {[pipeName: string]: number} = Object.create(null); private purePipeNodeIndices: {[pipeName: string]: number} = Object.create(null);
// Need Object.create so that we don't have builtin values... // Need Object.create so that we don't have builtin values...
@ -219,9 +221,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
this.nodes.push(() => ({ this.nodes.push(() => ({
sourceSpan: ast.sourceSpan, sourceSpan: ast.sourceSpan,
nodeFlags: NodeFlags.TypeNgContent, nodeFlags: NodeFlags.TypeNgContent,
nodeDef: o.importExpr(Identifiers.ngContentDef).callFn([ nodeDef: o.importExpr(Identifiers.ngContentDef)
o.literal(ast.ngContentIndex), o.literal(ast.index) .callFn([o.literal(ast.ngContentIndex), o.literal(ast.index)])
])
})); }));
} }
@ -554,7 +555,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
})); }));
const hostEvents = dirAst.hostEvents.map((hostEventAst) => ({ const hostEvents = dirAst.hostEvents.map((hostEventAst) => ({
context: dirContextExpr, context: dirContextExpr,
eventAst: hostEventAst, dirAst, eventAst: hostEventAst,
dirAst,
})); }));
// Check index is the same as the node index during compilation // Check index is the same as the node index during compilation
@ -803,10 +805,9 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
context: expression.context, context: expression.context,
value: convertPropertyBindingBuiltins( value: convertPropertyBindingBuiltins(
{ {
createLiteralArrayConverter: (argCount: number) => this._createLiteralArrayConverter( createLiteralArrayConverter: (argCount: number) =>
expression.sourceSpan, argCount), this._createLiteralArrayConverter(expression.sourceSpan, argCount),
createLiteralMapConverter: createLiteralMapConverter: (keys: {key: string, quoted: boolean}[]) =>
(keys: {key: string, quoted: boolean}[]) =>
this._createLiteralMapConverter(expression.sourceSpan, keys), this._createLiteralMapConverter(expression.sourceSpan, keys),
createPipeConverter: (name: string, argCount: number) => createPipeConverter: (name: string, argCount: number) =>
this._createPipeConverter(expression, name, argCount) this._createPipeConverter(expression, name, argCount)
@ -975,7 +976,9 @@ function elementBindingDef(inputAst: BoundElementPropertyAst, dirAst: DirectiveA
function fixedAttrsDef(elementAst: ElementAst): o.Expression { function fixedAttrsDef(elementAst: ElementAst): o.Expression {
const mapResult: {[key: string]: string} = Object.create(null); const mapResult: {[key: string]: string} = Object.create(null);
elementAst.attrs.forEach(attrAst => { mapResult[attrAst.name] = attrAst.value; }); elementAst.attrs.forEach(attrAst => {
mapResult[attrAst.name] = attrAst.value;
});
elementAst.directives.forEach(dirAst => { elementAst.directives.forEach(dirAst => {
Object.keys(dirAst.directive.hostAttributes).forEach(name => { Object.keys(dirAst.directive.hostAttributes).forEach(name => {
const value = dirAst.directive.hostAttributes[name]; const value = dirAst.directive.hostAttributes[name];

View File

@ -13,7 +13,7 @@ import {extractSourceMap, originalPositionFor} from '@angular/compiler/testing/s
import {NodeFlags} from '@angular/core/src/view/index'; import {NodeFlags} from '@angular/core/src/view/index';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockDirectory, MockMetadataBundlerHost, arrayToMockDir, compile, expectNoDiagnostics, isInBazel, settings, setup, toMockFileArray} from './test_util'; import {arrayToMockDir, compile, EmittingCompilerHost, expectNoDiagnostics, isInBazel, MockAotCompilerHost, MockCompilerHost, MockDirectory, MockMetadataBundlerHost, settings, setup, toMockFileArray} from './test_util';
describe('compiler (unbundled Angular)', () => { describe('compiler (unbundled Angular)', () => {
let angularFiles = setup(); let angularFiles = setup();
@ -84,7 +84,9 @@ describe('compiler (unbundled Angular)', () => {
describe('inline templates', () => { describe('inline templates', () => {
const ngUrl = `${componentPath}.AppComponent.html`; const ngUrl = `${componentPath}.AppComponent.html`;
function templateDecorator(template: string) { return `template: \`${template}\`,`; } function templateDecorator(template: string) {
return `template: \`${template}\`,`;
}
declareTests({ngUrl, templateDecorator}); declareTests({ngUrl, templateDecorator});
}); });
@ -205,7 +207,6 @@ describe('compiler (unbundled Angular)', () => {
compile([FILES, angularFiles]); compile([FILES, angularFiles]);
expect(warnSpy).toHaveBeenCalledWith( expect(warnSpy).toHaveBeenCalledWith(
`Warning: Can't resolve all parameters for MyService in /app/app.ts: (?). This will become an error in Angular v6.x`); `Warning: Can't resolve all parameters for MyService in /app/app.ts: (?). This will become an error in Angular v6.x`);
}); });
it('should error if not all arguments of an @Injectable class can be resolved if strictInjectionParameters is true', it('should error if not all arguments of an @Injectable class can be resolved if strictInjectionParameters is true',
@ -479,7 +480,6 @@ describe('compiler (unbundled Angular)', () => {
genFiles.find(gf => gf.srcFileUrl === '/app/app.ts' && gf.genFileUrl.endsWith('.ts'))!; genFiles.find(gf => gf.srcFileUrl === '/app/app.ts' && gf.genFileUrl.endsWith('.ts'))!;
const genSource = toTypeScript(genFile); const genSource = toTypeScript(genFile);
expect(genSource).not.toContain('check('); expect(genSource).not.toContain('check(');
}); });
}); });
@ -492,7 +492,6 @@ describe('compiler (unbundled Angular)', () => {
inheritanceWithSummariesSpecs(() => angularSummaryFiles); inheritanceWithSummariesSpecs(() => angularSummaryFiles);
describe('external symbol re-exports enabled', () => { describe('external symbol re-exports enabled', () => {
it('should not reexport type symbols mentioned in constructors', () => { it('should not reexport type symbols mentioned in constructors', () => {
const libInput: MockDirectory = { const libInput: MockDirectory = {
'lib': { 'lib': {

View File

@ -8,7 +8,7 @@
import {AotCompiler, AotCompilerHost, AotCompilerOptions, CompileSummaryKind, GeneratedFile, toTypeScript} from '@angular/compiler'; import {AotCompiler, AotCompilerHost, AotCompilerOptions, CompileSummaryKind, GeneratedFile, toTypeScript} from '@angular/compiler';
import {MockDirectory, compile, setup} from './test_util'; import {compile, MockDirectory, setup} from './test_util';
describe('aot summaries for jit', () => { describe('aot summaries for jit', () => {
let angularFiles = setup(); let angularFiles = setup();
@ -301,8 +301,7 @@ describe('aot summaries for jit', () => {
createExternalSymbolFactoryReexports: true, createExternalSymbolFactoryReexports: true,
}); });
const lib2ModuleNgSummary = const lib2ModuleNgSummary = lib2Gen.find(f => f.genFileUrl === '/lib2/module.ngsummary.ts')!;
lib2Gen.find(f => f.genFileUrl === '/lib2/module.ngsummary.ts') !;
const lib2ReexportNgSummary = const lib2ReexportNgSummary =
lib2Gen.find(f => f.genFileUrl === '/lib2/reexport.ngsummary.ts')!; lib2Gen.find(f => f.genFileUrl === '/lib2/reexport.ngsummary.ts')!;
@ -336,8 +335,7 @@ describe('aot summaries for jit', () => {
useSummaries: true, useSummaries: true,
createExternalSymbolFactoryReexports: true createExternalSymbolFactoryReexports: true
}).genFiles; }).genFiles;
const lib3ModuleNgSummary = const lib3ModuleNgSummary = lib3Gen.find(f => f.genFileUrl === '/lib3/module.ngsummary.ts')!;
lib3Gen.find(f => f.genFileUrl === '/lib3/module.ngsummary.ts') !;
const lib3ReexportNgSummary = const lib3ReexportNgSummary =
lib3Gen.find(f => f.genFileUrl === '/lib3/reexport.ngsummary.ts')!; lib3Gen.find(f => f.genFileUrl === '/lib3/reexport.ngsummary.ts')!;

View File

@ -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 {MockDirectory, compile, expectNoDiagnostics, setup} from './test_util'; import {compile, expectNoDiagnostics, MockDirectory, setup} from './test_util';
describe('regressions', () => { describe('regressions', () => {
let angularFiles = setup(); let angularFiles = setup();

View File

@ -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, core as compilerCore} from '@angular/compiler'; import {core as compilerCore, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, StaticSymbolResolverHost} from '@angular/compiler';
import {CollectorOptions, METADATA_VERSION} from '@angular/compiler-cli'; import {CollectorOptions, METADATA_VERSION} from '@angular/compiler-cli';
import {MockStaticSymbolResolverHost, MockSummaryResolver} from './static_symbol_resolver_spec'; import {MockStaticSymbolResolverHost, MockSummaryResolver} from './static_symbol_resolver_spec';
@ -1334,10 +1334,9 @@ const DEFAULT_TEST_DATA: {[key: string]: any} = {
'decorators': [{ 'decorators': [{
'__symbolic': 'call', '__symbolic': 'call',
'expression': {'__symbolic': 'reference', 'name': 'Directive', 'module': '@angular/core'}, 'expression': {'__symbolic': 'reference', 'name': 'Directive', 'module': '@angular/core'},
'arguments': [{ 'arguments': [
'selector': '[ngFor][ngForOf]', {'selector': '[ngFor][ngForOf]', 'inputs': ['ngForTrackBy', 'ngForOf', 'ngForTemplate']}
'inputs': ['ngForTrackBy', 'ngForOf', 'ngForTemplate'] ]
}]
}], }],
'members': { 'members': {
'__ctor__': [{ '__ctor__': [{
@ -1345,11 +1344,8 @@ const DEFAULT_TEST_DATA: {[key: string]: any} = {
'parameters': [ 'parameters': [
{'__symbolic': 'reference', 'module': '@angular/core', 'name': 'ViewContainerRef'}, {'__symbolic': 'reference', 'module': '@angular/core', 'name': 'ViewContainerRef'},
{'__symbolic': 'reference', 'module': '@angular/core', 'name': 'TemplateRef'}, {'__symbolic': 'reference', 'module': '@angular/core', 'name': 'TemplateRef'},
{'__symbolic': 'reference', 'module': '@angular/core', 'name': 'IterableDiffers'}, { {'__symbolic': 'reference', 'module': '@angular/core', 'name': 'IterableDiffers'},
'__symbolic': 'reference', {'__symbolic': 'reference', 'module': '@angular/core', 'name': 'ChangeDetectorRef'}
'module': '@angular/core',
'name': 'ChangeDetectorRef'
}
] ]
}] }]
} }
@ -1387,8 +1383,7 @@ const DEFAULT_TEST_DATA: {[key: string]: any} = {
'__symbolic': 'property', '__symbolic': 'property',
'decorators': [{ 'decorators': [{
'__symbolic': 'call', '__symbolic': 'call',
'expression': 'expression': {'__symbolic': 'reference', 'name': 'Input', 'module': '@angular/core'}
{'__symbolic': 'reference', 'name': 'Input', 'module': '@angular/core'}
}] }]
}], }],
'onMouseOver': [{ 'onMouseOver': [{

View File

@ -19,7 +19,9 @@ describe('StaticSymbolResolver', () => {
let symbolResolver: StaticSymbolResolver; let symbolResolver: StaticSymbolResolver;
let symbolCache: StaticSymbolCache; let symbolCache: StaticSymbolCache;
beforeEach(() => { symbolCache = new StaticSymbolCache(); }); beforeEach(() => {
symbolCache = new StaticSymbolCache();
});
function init( function init(
testData: {[key: string]: any} = DEFAULT_TEST_DATA, summaries: Summary<StaticSymbol>[] = [], testData: {[key: string]: any} = DEFAULT_TEST_DATA, summaries: Summary<StaticSymbol>[] = [],
@ -36,7 +38,8 @@ describe('StaticSymbolResolver', () => {
() => symbolResolver.resolveSymbol( () => symbolResolver.resolveSymbol(
symbolResolver.getSymbolByModule('src/version-error', 'e'))) symbolResolver.getSymbolByModule('src/version-error', 'e')))
.toThrow(new Error( .toThrow(new Error(
`Metadata version mismatch for module /tmp/src/version-error.d.ts, found version 100, expected ${METADATA_VERSION}`)); `Metadata version mismatch for module /tmp/src/version-error.d.ts, found version 100, expected ${
METADATA_VERSION}`));
}); });
it('should throw an exception for version 2 metadata', () => { it('should throw an exception for version 2 metadata', () => {
@ -159,7 +162,6 @@ describe('StaticSymbolResolver', () => {
}); });
describe('importAs', () => { describe('importAs', () => {
it('should calculate importAs relationship for non source files without summaries', () => { it('should calculate importAs relationship for non source files without summaries', () => {
init( init(
{ {
@ -241,7 +243,6 @@ describe('StaticSymbolResolver', () => {
expect(symbolResolver.getImportAs(symbolCache.get('/test2.d.ts', 'a', ['someMember']))) expect(symbolResolver.getImportAs(symbolCache.get('/test2.d.ts', 'a', ['someMember'])))
.toBe(symbolCache.get('/test3.d.ts', 'b', ['someMember'])); .toBe(symbolCache.get('/test3.d.ts', 'b', ['someMember']));
}); });
}); });
it('should replace references by StaticSymbols', () => { it('should replace references by StaticSymbols', () => {
@ -345,10 +346,9 @@ describe('StaticSymbolResolver', () => {
__symbolic: 'class', __symbolic: 'class',
arity: 1, arity: 1,
members: { members: {
__ctor__: [{ __ctor__: [
__symbolic: 'constructor', {__symbolic: 'constructor', parameters: [symbolCache.get('/test.d.ts', 'AParam')]}
parameters: [symbolCache.get('/test.d.ts', 'AParam')] ]
}]
} }
} }
} }
@ -423,7 +423,6 @@ describe('StaticSymbolResolver', () => {
expect(symbol.name).toEqual('One'); expect(symbol.name).toEqual('One');
expect(symbol.filePath).toEqual('/tmp/src/reexport/src/origin1.d.ts'); expect(symbol.filePath).toEqual('/tmp/src/reexport/src/origin1.d.ts');
}); });
}); });
export class MockSummaryResolver implements SummaryResolver<StaticSymbol> { export class MockSummaryResolver implements SummaryResolver<StaticSymbol> {
@ -431,7 +430,9 @@ export class MockSummaryResolver implements SummaryResolver<StaticSymbol> {
symbol: StaticSymbol, symbol: StaticSymbol,
importAs: StaticSymbol importAs: StaticSymbol
}[] = []) {} }[] = []) {}
addSummary(summary: Summary<StaticSymbol>) { this.summaries.push(summary); } addSummary(summary: Summary<StaticSymbol>) {
this.summaries.push(summary);
}
resolveSummary(reference: StaticSymbol): Summary<StaticSymbol> { resolveSummary(reference: StaticSymbol): Summary<StaticSymbol> {
return this.summaries.find(summary => summary.symbol === reference)!; return this.summaries.find(summary => summary.symbol === reference)!;
} }
@ -444,10 +445,18 @@ export class MockSummaryResolver implements SummaryResolver<StaticSymbol> {
const entry = this.importAs.find(entry => entry.symbol === symbol); const entry = this.importAs.find(entry => entry.symbol === symbol);
return entry ? entry.importAs : undefined!; return entry ? entry.importAs : undefined!;
} }
getKnownModuleName(fileName: string): string|null { return null; } getKnownModuleName(fileName: string): string|null {
isLibraryFile(filePath: string): boolean { return filePath.endsWith('.d.ts'); } return null;
toSummaryFileName(filePath: string): string { return filePath.replace(/(\.d)?\.ts$/, '.d.ts'); } }
fromSummaryFileName(filePath: string): string { return filePath; } isLibraryFile(filePath: string): boolean {
return filePath.endsWith('.d.ts');
}
toSummaryFileName(filePath: string): string {
return filePath.replace(/(\.d)?\.ts$/, '.d.ts');
}
fromSummaryFileName(filePath: string): string {
return filePath;
}
} }
export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost { export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost {
@ -459,7 +468,9 @@ export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost {
// In tests, assume that symbols are not re-exported // In tests, assume that symbols are not re-exported
moduleNameToFileName(modulePath: string, containingFile?: string): string { moduleNameToFileName(modulePath: string, containingFile?: string): string {
function splitPath(path: string): string[] { return path.split(/\/|\\/g); } function splitPath(path: string): string[] {
return path.split(/\/|\\/g);
}
function resolvePath(pathParts: string[]): string { function resolvePath(pathParts: string[]): string {
const result: string[] = []; const result: string[] = [];
@ -503,9 +514,13 @@ export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost {
return '/tmp/' + modulePath + '.d.ts'; return '/tmp/' + modulePath + '.d.ts';
} }
getMetadataFor(moduleId: string): any { return this._getMetadataFor(moduleId); } getMetadataFor(moduleId: string): any {
return this._getMetadataFor(moduleId);
}
getOutputName(filePath: string): string { return filePath; } getOutputName(filePath: string): string {
return filePath;
}
private _getMetadataFor(filePath: string): any { private _getMetadataFor(filePath: string): any {
if (this.data[filePath] && filePath.match(TS_EXT)) { if (this.data[filePath] && filePath.match(TS_EXT)) {
@ -515,10 +530,10 @@ export class MockStaticSymbolResolverHost implements StaticSymbolResolverHost {
filePath, this.data[filePath], ts.ScriptTarget.ES5, /* setParentNodes */ true); filePath, this.data[filePath], ts.ScriptTarget.ES5, /* setParentNodes */ true);
const diagnostics: ts.Diagnostic[] = (<any>sf).parseDiagnostics; const diagnostics: ts.Diagnostic[] = (<any>sf).parseDiagnostics;
if (diagnostics && diagnostics.length) { if (diagnostics && diagnostics.length) {
const errors = const errors = diagnostics
diagnostics
.map(d => { .map(d => {
const {line, character} = ts.getLineAndCharacterOfPosition(d.file !, d.start !); const {line, character} =
ts.getLineAndCharacterOfPosition(d.file!, d.start!);
return `(${line}:${character}): ${d.messageText}`; return `(${line}:${character}): ${d.messageText}`;
}) })
.join('\n'); .join('\n');

View File

@ -23,7 +23,9 @@ const EXT = /(\.d)?\.ts$/;
let symbolCache: StaticSymbolCache; let symbolCache: StaticSymbolCache;
let host: MockAotSummaryResolverHost; let host: MockAotSummaryResolverHost;
beforeEach(() => { symbolCache = new StaticSymbolCache(); }); beforeEach(() => {
symbolCache = new StaticSymbolCache();
});
function init(summaries: {[filePath: string]: string} = {}) { function init(summaries: {[filePath: string]: string} = {}) {
host = new MockAotSummaryResolverHost(summaries); host = new MockAotSummaryResolverHost(summaries);
@ -121,11 +123,17 @@ export class MockAotSummaryResolverHost implements AotSummaryResolverHost {
return sourceFileName.replace(EXT, '') + '.d.ts'; return sourceFileName.replace(EXT, '') + '.d.ts';
} }
fromSummaryFileName(filePath: string): string { return filePath; } fromSummaryFileName(filePath: string): string {
return filePath;
}
isSourceFile(filePath: string) { return !filePath.endsWith('.d.ts'); } isSourceFile(filePath: string) {
return !filePath.endsWith('.d.ts');
}
loadSummary(filePath: string): string { return this.summaries[filePath]; } loadSummary(filePath: string): string {
return this.summaries[filePath];
}
} }
export function createMockOutputContext(): OutputContext { export function createMockOutputContext(): OutputContext {

View File

@ -12,7 +12,7 @@ import {deserializeSummaries, serializeSummaries} from '@angular/compiler/src/ao
import {summaryFileName} from '@angular/compiler/src/aot/util'; import {summaryFileName} from '@angular/compiler/src/aot/util';
import {MockStaticSymbolResolverHost} from './static_symbol_resolver_spec'; import {MockStaticSymbolResolverHost} from './static_symbol_resolver_spec';
import {MockAotSummaryResolverHost, createMockOutputContext} from './summary_resolver_spec'; import {createMockOutputContext, MockAotSummaryResolverHost} from './summary_resolver_spec';
{ {
@ -22,7 +22,9 @@ import {MockAotSummaryResolverHost, createMockOutputContext} from './summary_res
let symbolCache: StaticSymbolCache; let symbolCache: StaticSymbolCache;
let host: MockAotSummaryResolverHost; let host: MockAotSummaryResolverHost;
beforeEach(() => { symbolCache = new StaticSymbolCache(); }); beforeEach(() => {
symbolCache = new StaticSymbolCache();
});
function init( function init(
summaries: {[filePath: string]: string} = {}, metadata: {[key: string]: any} = {}) { summaries: {[filePath: string]: string} = {}, metadata: {[key: string]: any} = {}) {
@ -387,7 +389,6 @@ import {MockAotSummaryResolverHost, createMockOutputContext} from './summary_res
describe('symbol re-exports enabled', () => { describe('symbol re-exports enabled', () => {
it('should not create "importAs" names for ctor arguments which are types of reexported classes in libraries', it('should not create "importAs" names for ctor arguments which are types of reexported classes in libraries',
() => { () => {
init(); init();

View File

@ -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 {AotCompilerHost, AotCompilerOptions, GeneratedFile, createAotCompiler, toTypeScript} from '@angular/compiler'; import {AotCompilerHost, AotCompilerOptions, createAotCompiler, GeneratedFile, toTypeScript} from '@angular/compiler';
import {MetadataBundlerHost} from '@angular/compiler-cli/src/metadata/bundler'; import {MetadataBundlerHost} from '@angular/compiler-cli/src/metadata/bundler';
import {MetadataCollector} from '@angular/compiler-cli/src/metadata/collector'; import {MetadataCollector} from '@angular/compiler-cli/src/metadata/collector';
import {ModuleMetadata} from '@angular/compiler-cli/src/metadata/index'; import {ModuleMetadata} from '@angular/compiler-cli/src/metadata/index';
@ -15,7 +15,9 @@ import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
export interface MetadataProvider { getMetadata(source: ts.SourceFile): ModuleMetadata|undefined; } export interface MetadataProvider {
getMetadata(source: ts.SourceFile): ModuleMetadata|undefined;
}
let nodeModulesPath: string; let nodeModulesPath: string;
let angularSourcePath: string; let angularSourcePath: string;
@ -119,9 +121,13 @@ export class EmittingCompilerHost implements ts.CompilerHost {
return Array.from(this.writtenFiles).map(f => ({name: f[0], content: f[1]})); return Array.from(this.writtenFiles).map(f => ({name: f[0], content: f[1]}));
} }
public get scripts(): string[] { return this.scriptNames; } public get scripts(): string[] {
return this.scriptNames;
}
public get written(): Map<string, string> { return this.writtenFiles; } public get written(): Map<string, string> {
return this.writtenFiles;
}
public effectiveName(fileName: string): string { public effectiveName(fileName: string): string {
const prefix = '@angular/'; const prefix = '@angular/';
@ -154,7 +160,9 @@ export class EmittingCompilerHost implements ts.CompilerHost {
(fs.existsSync(directoryName) && fs.statSync(directoryName).isDirectory()); (fs.existsSync(directoryName) && fs.statSync(directoryName).isDirectory());
} }
getCurrentDirectory(): string { return this.root; } getCurrentDirectory(): string {
return this.root;
}
getDirectories(dir: string): string[] { getDirectories(dir: string): string[] {
const result = open(dir, this.options.mockData); const result = open(dir, this.options.mockData);
@ -179,7 +187,9 @@ export class EmittingCompilerHost implements ts.CompilerHost {
throw new Error(`File not found '${fileName}'.`); throw new Error(`File not found '${fileName}'.`);
} }
getDefaultLibFileName(options: ts.CompilerOptions): string { return 'lib.d.ts'; } getDefaultLibFileName(options: ts.CompilerOptions): string {
return 'lib.d.ts';
}
writeFile: ts.WriteFileCallback = writeFile: ts.WriteFileCallback =
(fileName: string, data: string, writeByteOrderMark: boolean, (fileName: string, data: string, writeByteOrderMark: boolean,
@ -197,8 +207,12 @@ export class EmittingCompilerHost implements ts.CompilerHost {
getCanonicalFileName(fileName: string): string { getCanonicalFileName(fileName: string): string {
return fileName; return fileName;
} }
useCaseSensitiveFileNames(): boolean { return false; } useCaseSensitiveFileNames(): boolean {
getNewLine(): string { return '\n'; } return false;
}
getNewLine(): string {
return '\n';
}
private getAddedDirectories(): Set<string> { private getAddedDirectories(): Set<string> {
let result = this.cachedAddedDirectories; let result = this.cachedAddedDirectories;
@ -247,7 +261,9 @@ export class MockCompilerHost implements ts.CompilerHost {
this.sourceFiles.delete(fileName); this.sourceFiles.delete(fileName);
} }
assumeFileExists(fileName: string) { this.assumeExists.add(fileName); } assumeFileExists(fileName: string) {
this.assumeExists.add(fileName);
}
remove(files: string[]) { remove(files: string[]) {
// Remove the files from the list of scripts. // Remove the files from the list of scripts.
@ -274,11 +290,17 @@ export class MockCompilerHost implements ts.CompilerHost {
return false; return false;
} }
readFile(fileName: string): string { return this.getFileContent(fileName) !; } readFile(fileName: string): string {
return this.getFileContent(fileName)!;
}
trace(s: string): void { this.traces.push(s); } trace(s: string): void {
this.traces.push(s);
}
getCurrentDirectory(): string { return '/'; } getCurrentDirectory(): string {
return '/';
}
getDirectories(dir: string): string[] { getDirectories(dir: string): string[] {
const effectiveName = this.getEffectiveName(dir); const effectiveName = this.getEffectiveName(dir);
@ -306,7 +328,9 @@ export class MockCompilerHost implements ts.CompilerHost {
return result!; return result!;
} }
getDefaultLibFileName(options: ts.CompilerOptions): string { return 'lib.d.ts'; } getDefaultLibFileName(options: ts.CompilerOptions): string {
return 'lib.d.ts';
}
writeFile: ts.WriteFileCallback = writeFile: ts.WriteFileCallback =
(fileName: string, data: string, writeByteOrderMark: boolean) => { (fileName: string, data: string, writeByteOrderMark: boolean) => {
@ -317,8 +341,12 @@ export class MockCompilerHost implements ts.CompilerHost {
getCanonicalFileName(fileName: string): string { getCanonicalFileName(fileName: string): string {
return fileName; return fileName;
} }
useCaseSensitiveFileNames(): boolean { return false; } useCaseSensitiveFileNames(): boolean {
getNewLine(): string { return '\n'; } return false;
}
getNewLine(): string {
return '\n';
}
// Private methods // Private methods
private getFileContent(fileName: string): string|undefined { private getFileContent(fileName: string): string|undefined {
@ -373,9 +401,13 @@ export class MockAotCompilerHost implements AotCompilerHost {
}; };
} }
hideMetadata() { this.metadataVisible = false; } hideMetadata() {
this.metadataVisible = false;
}
tsFilesOnly() { this.dtsAreSource = false; } tsFilesOnly() {
this.dtsAreSource = false;
}
// StaticSymbolResolverHost // StaticSymbolResolverHost
getMetadataFor(modulePath: string): {[key: string]: any}[]|undefined { getMetadataFor(modulePath: string): {[key: string]: any}[]|undefined {
@ -414,7 +446,9 @@ export class MockAotCompilerHost implements AotCompilerHost {
return resolved ? resolved.resolvedFileName : null; return resolved ? resolved.resolvedFileName : null;
} }
getOutputName(filePath: string) { return filePath; } getOutputName(filePath: string) {
return filePath;
}
resourceNameToFileName(resourceName: string, containingFile: string) { resourceNameToFileName(resourceName: string, containingFile: string) {
// Note: we convert package paths into relative paths to be compatible with the the // Note: we convert package paths into relative paths to be compatible with the the
@ -428,16 +462,22 @@ export class MockAotCompilerHost implements AotCompilerHost {
} }
// AotSummaryResolverHost // AotSummaryResolverHost
loadSummary(filePath: string): string|null { return this.tsHost.readFile(filePath); } loadSummary(filePath: string): string|null {
return this.tsHost.readFile(filePath);
}
isSourceFile(sourceFilePath: string): boolean { isSourceFile(sourceFilePath: string): boolean {
return !GENERATED_FILES.test(sourceFilePath) && return !GENERATED_FILES.test(sourceFilePath) &&
(this.dtsAreSource || !DTS.test(sourceFilePath)); (this.dtsAreSource || !DTS.test(sourceFilePath));
} }
toSummaryFileName(filePath: string): string { return filePath.replace(EXT, '') + '.d.ts'; } toSummaryFileName(filePath: string): string {
return filePath.replace(EXT, '') + '.d.ts';
}
fromSummaryFileName(filePath: string): string { return filePath; } fromSummaryFileName(filePath: string): string {
return filePath;
}
// AotCompilerHost // AotCompilerHost
fileNameToModuleName(importedFile: string, containingFile: string): string { fileNameToModuleName(importedFile: string, containingFile: string): string {
@ -523,12 +563,16 @@ function mockDirToFileArray(dir: MockDirectory, path: string, target: MockFileAr
} }
function mapToMockFileArray(files: Map<string, string>, target: MockFileArray) { function mapToMockFileArray(files: Map<string, string>, target: MockFileArray) {
files.forEach((content, fileName) => { target.push({fileName, content}); }); files.forEach((content, fileName) => {
target.push({fileName, content});
});
} }
export function arrayToMockMap(arr: MockFileArray): Map<string, string> { export function arrayToMockMap(arr: MockFileArray): Map<string, string> {
const map = new Map<string, string>(); const map = new Map<string, string>();
arr.forEach(({fileName, content}) => { map.set(fileName, content); }); arr.forEach(({fileName, content}) => {
map.set(fileName, content);
});
return map; return map;
} }
@ -594,8 +638,8 @@ function readBazelWrittenFilesFrom(
map.set(path.posix.join('/node_modules/@angular', packageName, 'index.d.ts'), content); map.set(path.posix.join('/node_modules/@angular', packageName, 'index.d.ts'), content);
} }
} catch (e) { } catch (e) {
console.error( console.error(`Consider adding //packages/${
`Consider adding //packages/${packageName} as a data dependency in the BUILD.bazel rule for the failing test`); packageName} as a data dependency in the BUILD.bazel rule for the failing test`);
throw e; throw e;
} }
} }
@ -606,8 +650,8 @@ export function isInBazel(): boolean {
export function setup(options: { export function setup(options: {
compileAngular: boolean, compileAngular: boolean,
compileFakeCore?: boolean, compileFakeCore?: boolean, compileAnimations: boolean,
compileAnimations: boolean, compileCommon?: boolean compileCommon?: boolean
} = { } = {
compileAngular: true, compileAngular: true,
compileAnimations: true, compileAnimations: true,
@ -687,7 +731,9 @@ export function expectNoDiagnostics(program: ts.Program) {
return ''; return '';
} }
function chars(len: number, ch: string): string { return newArray(len, ch).join(''); } function chars(len: number, ch: string): string {
return newArray(len, ch).join('');
}
function lineNoOf(offset: number, text: string): number { function lineNoOf(offset: number, text: string): number {
let result = 1; let result = 1;
@ -726,8 +772,8 @@ export function expectNoDiagnostics(program: ts.Program) {
'Errors from TypeScript:\n' + 'Errors from TypeScript:\n' +
diagnostics diagnostics
.map( .map(
d => d => `${fileInfo(d)}${ts.flattenDiagnosticMessageText(d.messageText, '\n')}${
`${fileInfo(d)}${ts.flattenDiagnosticMessageText(d.messageText, '\n')}${lineInfo(d)}`) lineInfo(d)}`)
.join(' \n')); .join(' \n'));
} }
} }
@ -777,7 +823,9 @@ export function compile(
const tsSettings = {...settings, ...tsOptions}; const tsSettings = {...settings, ...tsOptions};
const program = ts.createProgram([...host.scriptNames], tsSettings, host); const program = ts.createProgram([...host.scriptNames], tsSettings, host);
preCompile(program); preCompile(program);
const {compiler, reflector} = createAotCompiler(aotHost, options, (err) => { throw err; }); const {compiler, reflector} = createAotCompiler(aotHost, options, (err) => {
throw err;
});
const analyzedModules = const analyzedModules =
compiler.analyzeModulesSync(program.getSourceFiles().map(sf => sf.fileName)); compiler.analyzeModulesSync(program.getSourceFiles().map(sf => sf.fileName));
const genFiles = compiler.emitAllImpls(analyzedModules); const genFiles = compiler.emitAllImpls(analyzedModules);

Some files were not shown because too many files have changed in this diff Show More