diff --git a/modules/@angular/compiler/src/compile_metadata.ts b/modules/@angular/compiler/src/compile_metadata.ts index bec0a89c89..ca51676bdf 100644 --- a/modules/@angular/compiler/src/compile_metadata.ts +++ b/modules/@angular/compiler/src/compile_metadata.ts @@ -98,6 +98,15 @@ export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier get identifier(): CompileIdentifierMetadata { return this; } } +/** + * A CompileSummary is the data needed to use a directive / pipe / module + * in other modules / components. However, this data is not enough to compile + * the directive / module itself. + */ +export interface CompileSummary { + isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; +} + export class CompileDiDependencyMetadata { isAttribute: boolean; isSelf: boolean; @@ -264,6 +273,16 @@ export class CompileStylesheetMetadata { } } +/** + * Summary Metadata regarding compilation of a template. + */ +export interface CompileTemplateSummary extends CompileSummary { + isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; + animations: string[]; + ngContentSelectors: string[]; + encapsulation: ViewEncapsulation; +} + /** * Metadata regarding compilation of a template. */ @@ -303,6 +322,34 @@ export class CompileTemplateMetadata { } this.interpolation = interpolation; } + + toSummary(): CompileTemplateSummary { + return { + isSummary: true, + animations: this.animations.map(anim => anim.name), + ngContentSelectors: this.ngContentSelectors, + encapsulation: this.encapsulation + }; + } +} + +export interface CompileDirectiveSummary extends CompileSummary { + isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; + type: CompileTypeMetadata; + isComponent: boolean; + selector: string; + exportAs: string; + inputs: {[key: string]: string}; + outputs: {[key: string]: string}; + hostListeners: {[key: string]: string}; + hostProperties: {[key: string]: string}; + hostAttributes: {[key: string]: string}; + providers: CompileProviderMetadata[]; + viewProviders: CompileProviderMetadata[]; + queries: CompileQueryMetadata[]; + entryComponents: CompileIdentifierMetadata[]; + changeDetection: ChangeDetectionStrategy; + template: CompileTemplateSummary; } /** @@ -394,7 +441,6 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier { viewProviders: CompileProviderMetadata[]; queries: CompileQueryMetadata[]; viewQueries: CompileQueryMetadata[]; - // Note: Need to keep types here to prevent cycles! entryComponents: CompileIdentifierMetadata[]; template: CompileTemplateMetadata; @@ -442,6 +488,27 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier { } get identifier(): CompileIdentifierMetadata { return this.type; } + + toSummary(): CompileDirectiveSummary { + return { + isSummary: true, + type: this.type, + isComponent: this.isComponent, + selector: this.selector, + exportAs: this.exportAs, + inputs: this.inputs, + outputs: this.outputs, + hostListeners: this.hostListeners, + hostProperties: this.hostProperties, + hostAttributes: this.hostAttributes, + providers: this.providers, + viewProviders: this.viewProviders, + queries: this.queries, + entryComponents: this.entryComponents, + changeDetection: this.changeDetection, + template: this.template && this.template.toSummary() + }; + } } /** @@ -479,6 +546,12 @@ export function createHostComponentMeta(compMeta: CompileDirectiveMetadata): }); } +export interface CompilePipeSummary extends CompileSummary { + isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; + type: CompileTypeMetadata; + name: string; + pure: boolean; +} export class CompilePipeMetadata implements CompileMetadataWithIdentifier { type: CompileTypeMetadata; @@ -495,8 +568,33 @@ export class CompilePipeMetadata implements CompileMetadataWithIdentifier { this.pure = !!pure; } get identifier(): CompileIdentifierMetadata { return this.type; } + + toSummary(): CompilePipeSummary { + return {isSummary: true, type: this.type, name: this.name, pure: this.pure}; + } } +export interface CompileNgModuleInjectorSummary extends CompileSummary { + isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; + type: CompileTypeMetadata; + entryComponents: CompileIdentifierMetadata[]; + providers: CompileProviderMetadata[]; + importedModules: CompileNgModuleInjectorSummary[]; + exportedModules: CompileNgModuleInjectorSummary[]; +} + +export interface CompileNgModuleDirectiveSummary extends CompileSummary { + isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; + type: CompileTypeMetadata; + exportedDirectives: CompileIdentifierMetadata[]; + exportedPipes: CompileIdentifierMetadata[]; + exportedModules: CompileNgModuleDirectiveSummary[]; + loadingPromises: Promise[]; +} + +export type CompileNgModuleSummary = + CompileNgModuleInjectorSummary & CompileNgModuleDirectiveSummary; + /** * Metadata regarding compilation of a module. */ @@ -506,13 +604,12 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier { exportedDirectives: CompileIdentifierMetadata[]; declaredPipes: CompileIdentifierMetadata[]; exportedPipes: CompileIdentifierMetadata[]; - // Note: See CompileDirectiveMetadata.entryComponents why this has to be a type. entryComponents: CompileIdentifierMetadata[]; bootstrapComponents: CompileIdentifierMetadata[]; providers: CompileProviderMetadata[]; - importedModules: CompileNgModuleMetadata[]; - exportedModules: CompileNgModuleMetadata[]; + importedModules: CompileNgModuleSummary[]; + exportedModules: CompileNgModuleSummary[]; schemas: SchemaMetadata[]; id: string; @@ -531,8 +628,8 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier { exportedPipes?: CompileIdentifierMetadata[], entryComponents?: CompileIdentifierMetadata[], bootstrapComponents?: CompileIdentifierMetadata[], - importedModules?: CompileNgModuleMetadata[], - exportedModules?: CompileNgModuleMetadata[], + importedModules?: CompileNgModuleSummary[], + exportedModules?: CompileNgModuleSummary[], transitiveModule?: TransitiveCompileNgModuleMetadata, schemas?: SchemaMetadata[], id?: string @@ -553,6 +650,41 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier { } get identifier(): CompileIdentifierMetadata { return this.type; } + + toSummary(): CompileNgModuleSummary { + return { + isSummary: true, + type: this.type, + entryComponents: this.entryComponents, + providers: this.providers, + importedModules: this.importedModules, + exportedModules: this.exportedModules, + exportedDirectives: this.exportedDirectives, + exportedPipes: this.exportedPipes, + loadingPromises: this.transitiveModule.loadingPromises + }; + } + + toInjectorSummary(): CompileNgModuleInjectorSummary { + return { + isSummary: true, + type: this.type, + entryComponents: this.entryComponents, + providers: this.providers, + importedModules: this.importedModules, + exportedModules: this.exportedModules + }; + } + toDirectiveSummary(): CompileNgModuleDirectiveSummary { + return { + isSummary: true, + type: this.type, + exportedDirectives: this.exportedDirectives, + exportedPipes: this.exportedPipes, + exportedModules: this.exportedModules, + loadingPromises: this.transitiveModule.loadingPromises + }; + } } export class TransitiveCompileNgModuleMetadata { @@ -560,7 +692,7 @@ export class TransitiveCompileNgModuleMetadata { pipesSet = new Set(); constructor( - public modules: CompileNgModuleMetadata[], public providers: CompileProviderMetadata[], + public modules: CompileNgModuleInjectorSummary[], public providers: CompileProviderMetadata[], public entryComponents: CompileIdentifierMetadata[], public directives: CompileIdentifierMetadata[], public pipes: CompileIdentifierMetadata[], public loadingPromises: Promise[]) { diff --git a/modules/@angular/compiler/src/directive_wrapper_compiler.ts b/modules/@angular/compiler/src/directive_wrapper_compiler.ts index 4a27901680..24ec49439e 100644 --- a/modules/@angular/compiler/src/directive_wrapper_compiler.ts +++ b/modules/@angular/compiler/src/directive_wrapper_compiler.ts @@ -8,7 +8,7 @@ import {Injectable} from '@angular/core'; -import {CompileDirectiveMetadata, CompileIdentifierMetadata} from './compile_metadata'; +import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata} from './compile_metadata'; import {createCheckBindingField, createCheckBindingStmt} from './compiler_util/binding_util'; import {EventHandlerVars, convertActionBinding, convertPropertyBinding} from './compiler_util/expression_converter'; import {triggerAnimation, writeToRenderer} from './compiler_util/render_util'; @@ -355,8 +355,8 @@ function parseHostBindings( const sourceSpan = new ParseSourceSpan( new ParseLocation(sourceFile, null, null, null), new ParseLocation(sourceFile, null, null, null)); - const parsedHostProps = parser.createDirectiveHostPropertyAsts(dirMeta, sourceSpan); - const parsedHostListeners = parser.createDirectiveHostEventAsts(dirMeta, sourceSpan); + const parsedHostProps = parser.createDirectiveHostPropertyAsts(dirMeta.toSummary(), sourceSpan); + const parsedHostListeners = parser.createDirectiveHostEventAsts(dirMeta.toSummary(), sourceSpan); return new ParseResult(parsedHostProps, parsedHostListeners, errors); } @@ -418,7 +418,7 @@ export class DirectiveWrapperExpressions { return []; } } - static ngOnDestroy(dir: CompileDirectiveMetadata, dirWrapper: o.Expression): o.Statement[] { + static ngOnDestroy(dir: CompileDirectiveSummary, dirWrapper: o.Expression): o.Statement[] { if (dir.type.lifecycleHooks.indexOf(LifecycleHooks.OnDestroy) !== -1 || Object.keys(dir.outputs).length > 0) { return [dirWrapper.callMethod('ngOnDestroy', []).toStmt()]; @@ -427,7 +427,7 @@ export class DirectiveWrapperExpressions { } } static subscribe( - dirMeta: CompileDirectiveMetadata, hostProps: BoundElementPropertyAst[], usedEvents: string[], + dirMeta: CompileDirectiveSummary, hostProps: BoundElementPropertyAst[], usedEvents: string[], dirWrapper: o.Expression, view: o.Expression, eventListener: o.Expression): o.Statement[] { let needsSubscribe = false; let eventFlags: o.Expression[] = []; diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index 61009f787c..20793d2dd8 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -12,7 +12,7 @@ import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions'; import * as cpl from './compile_metadata'; import {DirectiveNormalizer} from './directive_normalizer'; import {DirectiveResolver} from './directive_resolver'; -import {ListWrapper} from './facade/collection'; +import {ListWrapper, StringMapWrapper} from './facade/collection'; import {isBlank, isPresent, stringify} from './facade/lang'; import {Identifiers, resolveIdentifierToken} from './identifiers'; import {hasLifecycleHook} from './lifecycle_reflector'; @@ -24,6 +24,7 @@ import {getUrlScheme} from './url_resolver'; import {MODULE_SUFFIX, SyncAsyncResult, ValueTransformer, sanitizeIdentifier, visitValue} from './util'; + // Design notes: // - don't lazily create metadata: // For some metadata, we need to do async work sometimes, @@ -34,7 +35,9 @@ import {MODULE_SUFFIX, SyncAsyncResult, ValueTransformer, sanitizeIdentifier, vi @Injectable() export class CompileMetadataResolver { private _directiveCache = new Map, cpl.CompileDirectiveMetadata>(); + private _directiveSummaryCache = new Map, cpl.CompileDirectiveSummary>(); private _pipeCache = new Map, cpl.CompilePipeMetadata>(); + private _pipeSummaryCache = new Map, cpl.CompilePipeSummary>(); private _ngModuleCache = new Map, cpl.CompileNgModuleMetadata>(); private _ngModuleOfTypes = new Map, Type>(); private _anonymousTypes = new Map(); @@ -63,7 +66,9 @@ export class CompileMetadataResolver { clearCacheFor(type: Type) { const dirMeta = this._directiveCache.get(type); this._directiveCache.delete(type); + this._directiveSummaryCache.delete(type); this._pipeCache.delete(type); + this._pipeSummaryCache.delete(type); this._ngModuleOfTypes.delete(type); // Clear all of the NgModule as they contain transitive information! this._ngModuleCache.clear(); @@ -74,7 +79,9 @@ export class CompileMetadataResolver { clearCache() { this._directiveCache.clear(); + this._directiveSummaryCache.clear(); this._pipeCache.clear(); + this._pipeSummaryCache.clear(); this._ngModuleCache.clear(); this._ngModuleOfTypes.clear(); this._directiveNormalizer.clearCache(); @@ -205,6 +212,7 @@ export class CompileMetadataResolver { entryComponents: entryComponentMetadata }); this._directiveCache.set(directiveType, meta); + this._directiveSummaryCache.set(directiveType, meta.toSummary()); return meta; }; @@ -259,6 +267,15 @@ export class CompileMetadataResolver { return dirMeta; } + getDirectiveSummary(dirType: any): cpl.CompileDirectiveSummary { + const dirSummary = this._directiveSummaryCache.get(dirType); + if (!dirSummary) { + throw new Error( + `Illegal state: getDirectiveSummary can only be called after loadNgModuleMetadata for a module that imports it. Directive ${stringify(dirType)}.`); + } + return dirSummary; + } + isDirective(type: any) { return this._directiveResolver.isDirective(type); } isPipe(type: any) { return this._pipeResolver.isPipe(type); } @@ -276,6 +293,14 @@ export class CompileMetadataResolver { return modMeta; } + private _loadNgModuleSummary(moduleType: any, isSync: boolean): cpl.CompileNgModuleSummary { + // TODO(tbosch): add logic to read summary files! + // - needs to add directive / pipe summaries to this._directiveSummaryCache / + // this._pipeSummaryCache as well! + const moduleMeta = this._loadNgModuleMetadata(moduleType, isSync, false); + return moduleMeta ? moduleMeta.toSummary() : null; + } + /** * Loads an NgModule and all of its directives. This includes loading the exported directives of * imported modules, @@ -301,11 +326,10 @@ export class CompileMetadataResolver { return null; } const declaredDirectives: cpl.CompileIdentifierMetadata[] = []; - const exportedDirectives: cpl.CompileIdentifierMetadata[] = []; + const exportedNonModuleIdentifiers: cpl.CompileIdentifierMetadata[] = []; const declaredPipes: cpl.CompileIdentifierMetadata[] = []; - const exportedPipes: cpl.CompileIdentifierMetadata[] = []; - const importedModules: cpl.CompileNgModuleMetadata[] = []; - const exportedModules: cpl.CompileNgModuleMetadata[] = []; + const importedModules: cpl.CompileNgModuleSummary[] = []; + const exportedModules: cpl.CompileNgModuleSummary[] = []; const providers: any[] = []; const entryComponents: cpl.CompileIdentifierMetadata[] = []; const bootstrapComponents: cpl.CompileIdentifierMetadata[] = []; @@ -327,12 +351,12 @@ export class CompileMetadataResolver { } if (importedModuleType) { - const importedMeta = this._loadNgModuleMetadata(importedModuleType, isSync, false); - if (importedMeta === null) { + const importedModuleSummary = this._loadNgModuleSummary(importedModuleType, isSync); + if (!importedModuleSummary) { throw new Error( `Unexpected ${this._getTypeDescriptor(importedType)} '${stringify(importedType)}' imported by the module '${stringify(moduleType)}'`); } - importedModules.push(importedMeta); + importedModules.push(importedModuleSummary); } else { throw new Error( `Unexpected value '${stringify(importedType)}' imported by the module '${stringify(moduleType)}'`); @@ -346,18 +370,12 @@ export class CompileMetadataResolver { throw new Error( `Unexpected value '${stringify(exportedType)}' exported by the module '${stringify(moduleType)}'`); } - let identifier = - this._getIdentifierMetadata(exportedType, staticTypeModuleUrl(exportedType)); - let exportedModuleMeta: cpl.CompileNgModuleMetadata; - if (this._directiveResolver.isDirective(exportedType)) { - exportedDirectives.push(identifier); - } else if (this._pipeResolver.isPipe(exportedType)) { - exportedPipes.push(identifier); - } else if (exportedModuleMeta = this._loadNgModuleMetadata(exportedType, isSync, false)) { - exportedModules.push(exportedModuleMeta); + const exportedModuleSummary = this._loadNgModuleSummary(exportedType, isSync); + if (exportedModuleSummary) { + exportedModules.push(exportedModuleSummary); } else { - throw new Error( - `Unexpected ${this._getTypeDescriptor(exportedType)} '${stringify(exportedType)}' exported by the module '${stringify(moduleType)}'`); + exportedNonModuleIdentifiers.push( + this._getIdentifierMetadata(exportedType, staticTypeModuleUrl(exportedType))); } }); } @@ -395,6 +413,19 @@ export class CompileMetadataResolver { }); } + const exportedDirectives: cpl.CompileIdentifierMetadata[] = []; + const exportedPipes: cpl.CompileIdentifierMetadata[] = []; + exportedNonModuleIdentifiers.forEach((exportedId) => { + if (transitiveModule.directivesSet.has(exportedId.reference)) { + exportedDirectives.push(exportedId); + } else if (transitiveModule.pipesSet.has(exportedId.reference)) { + exportedPipes.push(exportedId); + } else { + throw new Error( + `Can't export ${this._getTypeDescriptor(exportedId.reference)} ${stringify(exportedId.reference)} from ${stringify(moduleType)} as it was neither declared nor imported!`); + } + }); + // The providers of the module have to go last // so that they overwrite any other provider we already added. if (meta.providers) { @@ -444,29 +475,11 @@ export class CompileMetadataResolver { id: meta.id, }); - transitiveModule.modules.push(compileMeta); - this._verifyModule(compileMeta); + transitiveModule.modules.push(compileMeta.toInjectorSummary()); this._ngModuleCache.set(moduleType, compileMeta); return compileMeta; } - - private _verifyModule(moduleMeta: cpl.CompileNgModuleMetadata) { - moduleMeta.exportedDirectives.forEach((dirIdentifier) => { - if (!moduleMeta.transitiveModule.directivesSet.has(dirIdentifier.reference)) { - throw new Error( - `Can't export directive ${stringify(dirIdentifier.reference)} from ${stringify(moduleMeta.type.reference)} as it was neither declared nor imported!`); - } - }); - - moduleMeta.exportedPipes.forEach((pipeIdentifier) => { - if (!moduleMeta.transitiveModule.pipesSet.has(pipeIdentifier.reference)) { - throw new Error( - `Can't export pipe ${stringify(pipeIdentifier.reference)} from ${stringify(moduleMeta.type.reference)} as it was neither declared nor imported!`); - } - }); - } - private _getTypeDescriptor(type: Type): string { if (this._directiveResolver.isDirective(type)) { return 'directive'; @@ -500,20 +513,20 @@ export class CompileMetadataResolver { } private _getTransitiveNgModuleMetadata( - importedModules: cpl.CompileNgModuleMetadata[], - exportedModules: cpl.CompileNgModuleMetadata[]): cpl.TransitiveCompileNgModuleMetadata { + importedModules: cpl.CompileNgModuleSummary[], + exportedModules: cpl.CompileNgModuleSummary[]): cpl.TransitiveCompileNgModuleMetadata { // collect `providers` / `entryComponents` from all imported and all exported modules - const transitiveModules = getTransitiveModules(importedModules.concat(exportedModules), true); + const transitiveModules = getTransitiveImportedModules(importedModules.concat(exportedModules)); const providers = flattenArray(transitiveModules.map((ngModule) => ngModule.providers)); const entryComponents = flattenArray(transitiveModules.map((ngModule) => ngModule.entryComponents)); - const transitiveExportedModules = getTransitiveModules(importedModules, false); + const transitiveExportedModules = getTransitiveExportedModules(importedModules); const directives = flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedDirectives)); const pipes = flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedPipes)); - const loadingPromises = ListWrapper.flatten( - transitiveExportedModules.map(ngModule => ngModule.transitiveModule.loadingPromises)); + const loadingPromises = + ListWrapper.flatten(transitiveExportedModules.map(ngModule => ngModule.loadingPromises)); return new cpl.TransitiveCompileNgModuleMetadata( transitiveModules, providers, entryComponents, directives, pipes, loadingPromises); } @@ -562,6 +575,15 @@ export class CompileMetadataResolver { return pipeMeta; } + getPipeSummary(pipeType: any): cpl.CompilePipeSummary { + const pipeSummary = this._pipeSummaryCache.get(pipeType); + if (!pipeSummary) { + throw new Error( + `Illegal state: getPipeSummary can only be called after loadNgModuleMetadata for a module that imports it. Pipe ${stringify(pipeType)}.`); + } + return pipeSummary; + } + private _loadPipeMetadata(pipeType: Type): void { pipeType = resolveForwardRef(pipeType); const pipeMeta = this._pipeResolver.resolve(pipeType); @@ -575,6 +597,7 @@ export class CompileMetadataResolver { pure: pipeMeta.pure }); this._pipeCache.set(pipeType, meta); + this._pipeSummaryCache.set(pipeType, meta.toSummary()); } private _getDependenciesMetadata(typeOrFunc: Type|Function, dependencies: any[]): @@ -790,17 +813,31 @@ export class CompileMetadataResolver { } } -function getTransitiveModules( - modules: cpl.CompileNgModuleMetadata[], includeImports: boolean, - targetModules: cpl.CompileNgModuleMetadata[] = [], - visitedModules = new Set>()): cpl.CompileNgModuleMetadata[] { +function getTransitiveExportedModules( + modules: cpl.CompileNgModuleDirectiveSummary[], + targetModules: cpl.CompileNgModuleDirectiveSummary[] = [], + visitedModules = new Set>()): cpl.CompileNgModuleDirectiveSummary[] { modules.forEach((ngModule) => { if (!visitedModules.has(ngModule.type.reference)) { visitedModules.add(ngModule.type.reference); - const nestedModules = includeImports ? - ngModule.importedModules.concat(ngModule.exportedModules) : - ngModule.exportedModules; - getTransitiveModules(nestedModules, includeImports, targetModules, visitedModules); + getTransitiveExportedModules(ngModule.exportedModules, targetModules, visitedModules); + // Add after recursing so imported/exported modules are before the module itself. + // This is important for overwriting providers of imported modules! + targetModules.push(ngModule); + } + }); + return targetModules; +} + +function getTransitiveImportedModules( + modules: cpl.CompileNgModuleInjectorSummary[], + targetModules: cpl.CompileNgModuleInjectorSummary[] = [], + visitedModules = new Set>()): cpl.CompileNgModuleInjectorSummary[] { + modules.forEach((ngModule) => { + if (!visitedModules.has(ngModule.type.reference)) { + visitedModules.add(ngModule.type.reference); + const nestedModules = ngModule.importedModules.concat(ngModule.exportedModules); + getTransitiveImportedModules(nestedModules, targetModules, visitedModules); // Add after recursing so imported/exported modules are before the module itself. // This is important for overwriting providers of imported modules! targetModules.push(ngModule); diff --git a/modules/@angular/compiler/src/offline_compiler.ts b/modules/@angular/compiler/src/offline_compiler.ts index 8a2d633d88..6a2737aa40 100644 --- a/modules/@angular/compiler/src/offline_compiler.ts +++ b/modules/@angular/compiler/src/offline_compiler.ts @@ -228,9 +228,9 @@ export class OfflineCompiler { fileSuffix: string, targetStatements: o.Statement[]): string { const parsedAnimations = this._animationParser.parseComponent(compMeta); const directives = - directiveIdentifiers.map(dir => this._metadataResolver.getDirectiveMetadata(dir.reference)); + directiveIdentifiers.map(dir => this._metadataResolver.getDirectiveSummary(dir.reference)); const pipes = ngModule.transitiveModule.pipes.map( - pipe => this._metadataResolver.getPipeMetadata(pipe.reference)); + pipe => this._metadataResolver.getPipeSummary(pipe.reference)); const parsedTemplate = this._templateParser.parse( compMeta, compMeta.template.template, directives, pipes, ngModule.schemas, diff --git a/modules/@angular/compiler/src/provider_analyzer.ts b/modules/@angular/compiler/src/provider_analyzer.ts index 1116e42528..f95019581d 100644 --- a/modules/@angular/compiler/src/provider_analyzer.ts +++ b/modules/@angular/compiler/src/provider_analyzer.ts @@ -7,7 +7,7 @@ */ -import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata'; +import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata'; import {isBlank, isPresent} from './facade/lang'; import {Identifiers, resolveIdentifierToken} from './identifiers'; import {ParseError, ParseSourceSpan} from './parse_util'; @@ -440,7 +440,7 @@ function _normalizeProviders( function _resolveProvidersFromDirectives( - directives: CompileDirectiveMetadata[], sourceSpan: ParseSourceSpan, + directives: CompileDirectiveSummary[], sourceSpan: ParseSourceSpan, targetErrors: ParseError[]): Map { var providersByToken = new Map(); directives.forEach((directive) => { @@ -504,7 +504,7 @@ function _getViewQueries(component: CompileDirectiveMetadata): Map { var contentQueries = new Map(); directives.forEach(directive => { diff --git a/modules/@angular/compiler/src/runtime_compiler.ts b/modules/@angular/compiler/src/runtime_compiler.ts index 33f8cbd822..e619b53f79 100644 --- a/modules/@angular/compiler/src/runtime_compiler.ts +++ b/modules/@angular/compiler/src/runtime_compiler.ts @@ -149,7 +149,9 @@ export class RuntimeCompiler implements Compiler { const moduleByDirective = new Map(); const templates = new Set(); - ngModule.transitiveModule.modules.forEach((localModuleMeta) => { + ngModule.transitiveModule.modules.forEach((localModuleSummary) => { + const localModuleMeta = + this._metadataResolver.getNgModuleMetadata(localModuleSummary.type.reference); localModuleMeta.declaredDirectives.forEach((dirIdentifier) => { moduleByDirective.set(dirIdentifier.reference, localModuleMeta); const dirMeta = this._metadataResolver.getDirectiveMetadata(dirIdentifier.reference); @@ -165,7 +167,9 @@ export class RuntimeCompiler implements Compiler { } }); }); - ngModule.transitiveModule.modules.forEach((localModuleMeta) => { + ngModule.transitiveModule.modules.forEach((localModuleSummary) => { + const localModuleMeta = + this._metadataResolver.getNgModuleMetadata(localModuleSummary.type.reference); localModuleMeta.declaredDirectives.forEach((dirIdentifier) => { const dirMeta = this._metadataResolver.getDirectiveMetadata(dirIdentifier.reference); if (dirMeta.isComponent) { @@ -279,9 +283,9 @@ export class RuntimeCompiler implements Compiler { stylesCompileResult.componentStylesheet, externalStylesheetsByModuleUrl); const parsedAnimations = this._animationParser.parseComponent(compMeta); const directives = - template.directives.map(dir => this._metadataResolver.getDirectiveMetadata(dir.reference)); + template.directives.map(dir => this._metadataResolver.getDirectiveSummary(dir.reference)); const pipes = template.ngModule.transitiveModule.pipes.map( - pipe => this._metadataResolver.getPipeMetadata(pipe.reference)); + pipe => this._metadataResolver.getPipeSummary(pipe.reference)); const parsedTemplate = this._templateParser.parse( compMeta, compMeta.template.template, directives, pipes, template.ngModule.schemas, compMeta.type.name); diff --git a/modules/@angular/compiler/src/template_parser/binding_parser.ts b/modules/@angular/compiler/src/template_parser/binding_parser.ts index fc815d145e..d5c34b60c5 100644 --- a/modules/@angular/compiler/src/template_parser/binding_parser.ts +++ b/modules/@angular/compiler/src/template_parser/binding_parser.ts @@ -8,7 +8,7 @@ import {SecurityContext} from '@angular/core'; -import {CompileDirectiveMetadata, CompilePipeMetadata} from '../compile_metadata'; +import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata'; import {AST, ASTWithSource, BindingPipe, EmptyExpr, Interpolation, LiteralPrimitive, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast'; import {Parser} from '../expression_parser/parser'; import {isPresent} from '../facade/lang'; @@ -52,16 +52,16 @@ export class BoundProperty { * Parses bindings in templates and in the directive host area. */ export class BindingParser { - pipesByName: Map = new Map(); + pipesByName: Map = new Map(); constructor( private _exprParser: Parser, private _interpolationConfig: InterpolationConfig, - private _schemaRegistry: ElementSchemaRegistry, pipes: CompilePipeMetadata[], + private _schemaRegistry: ElementSchemaRegistry, pipes: CompilePipeSummary[], private _targetErrors: ParseError[]) { pipes.forEach(pipe => this.pipesByName.set(pipe.name, pipe)); } - createDirectiveHostPropertyAsts(dirMeta: CompileDirectiveMetadata, sourceSpan: ParseSourceSpan): + createDirectiveHostPropertyAsts(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan): BoundElementPropertyAst[] { if (dirMeta.hostProperties) { const boundProps: BoundProperty[] = []; @@ -79,7 +79,7 @@ export class BindingParser { } } - createDirectiveHostEventAsts(dirMeta: CompileDirectiveMetadata, sourceSpan: ParseSourceSpan): + createDirectiveHostEventAsts(dirMeta: CompileDirectiveSummary, sourceSpan: ParseSourceSpan): BoundEventAst[] { if (dirMeta.hostListeners) { const targetEventAsts: BoundEventAst[] = []; diff --git a/modules/@angular/compiler/src/template_parser/template_ast.ts b/modules/@angular/compiler/src/template_parser/template_ast.ts index 926b78fd3f..a0d964345f 100644 --- a/modules/@angular/compiler/src/template_parser/template_ast.ts +++ b/modules/@angular/compiler/src/template_parser/template_ast.ts @@ -8,7 +8,7 @@ import {SecurityContext} from '@angular/core'; -import {CompileDirectiveMetadata, CompileProviderMetadata, CompileTokenMetadata} from '../compile_metadata'; +import {CompileDirectiveSummary, CompileProviderMetadata, CompileTokenMetadata} from '../compile_metadata'; import {AST} from '../expression_parser/ast'; import {ParseSourceSpan} from '../parse_util'; import {LifecycleHooks} from '../private_import_core'; @@ -168,7 +168,7 @@ export class BoundDirectivePropertyAst implements TemplateAst { */ export class DirectiveAst implements TemplateAst { constructor( - public directive: CompileDirectiveMetadata, public inputs: BoundDirectivePropertyAst[], + public directive: CompileDirectiveSummary, public inputs: BoundDirectivePropertyAst[], public hostProperties: BoundElementPropertyAst[], public hostEvents: BoundEventAst[], public sourceSpan: ParseSourceSpan) {} visit(visitor: TemplateAstVisitor, context: any): any { diff --git a/modules/@angular/compiler/src/template_parser/template_parser.ts b/modules/@angular/compiler/src/template_parser/template_parser.ts index 2fcfecce52..4a7cbc1bf0 100644 --- a/modules/@angular/compiler/src/template_parser/template_parser.ts +++ b/modules/@angular/compiler/src/template_parser/template_parser.ts @@ -8,7 +8,7 @@ import {Inject, Injectable, OpaqueToken, Optional, SchemaMetadata, SecurityContext} from '@angular/core'; -import {CompileDirectiveMetadata, CompilePipeMetadata, CompileTemplateMetadata, CompileTokenMetadata, removeIdentifierDuplicates} from '../compile_metadata'; +import {CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileTemplateMetadata, CompileTemplateSummary, CompileTokenMetadata, CompileTypeMetadata, removeIdentifierDuplicates} from '../compile_metadata'; import {AST, ASTWithSource, BindingPipe, EmptyExpr, Interpolation, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast'; import {Parser} from '../expression_parser/parser'; import {isPresent} from '../facade/lang'; @@ -90,8 +90,8 @@ export class TemplateParser { @Optional() @Inject(TEMPLATE_TRANSFORMS) public transforms: TemplateAstVisitor[]) {} parse( - component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveMetadata[], - pipes: CompilePipeMetadata[], schemas: SchemaMetadata[], templateUrl: string): TemplateAst[] { + component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveSummary[], + pipes: CompilePipeSummary[], schemas: SchemaMetadata[], templateUrl: string): TemplateAst[] { const result = this.tryParse(component, template, directives, pipes, schemas, templateUrl); const warnings = result.errors.filter(error => error.level === ParseErrorLevel.WARNING); const errors = result.errors.filter(error => error.level === ParseErrorLevel.FATAL); @@ -109,8 +109,8 @@ export class TemplateParser { } tryParse( - component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveMetadata[], - pipes: CompilePipeMetadata[], schemas: SchemaMetadata[], + component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveSummary[], + pipes: CompilePipeSummary[], schemas: SchemaMetadata[], templateUrl: string): TemplateParseResult { return this.tryParseHtml( this.expandHtml(this._htmlParser.parse( @@ -120,13 +120,13 @@ export class TemplateParser { tryParseHtml( htmlAstWithErrors: ParseTreeResult, component: CompileDirectiveMetadata, template: string, - directives: CompileDirectiveMetadata[], pipes: CompilePipeMetadata[], - schemas: SchemaMetadata[], templateUrl: string): TemplateParseResult { + directives: CompileDirectiveSummary[], pipes: CompilePipeSummary[], schemas: SchemaMetadata[], + templateUrl: string): TemplateParseResult { var result: TemplateAst[]; var errors = htmlAstWithErrors.errors; if (htmlAstWithErrors.rootNodes.length > 0) { - const uniqDirectives = removeIdentifierDuplicates(directives); - const uniqPipes = removeIdentifierDuplicates(pipes); + const uniqDirectives = removeSummaryDuplicates(directives); + const uniqPipes = removeSummaryDuplicates(pipes); const providerViewContext = new ProviderViewContext(component, htmlAstWithErrors.rootNodes[0].sourceSpan); let interpolationConfig: InterpolationConfig; @@ -200,14 +200,14 @@ export class TemplateParser { class TemplateParseVisitor implements html.Visitor { selectorMatcher = new SelectorMatcher(); - directivesIndex = new Map(); + directivesIndex = new Map(); ngContentCount: number = 0; constructor( - public providerViewContext: ProviderViewContext, directives: CompileDirectiveMetadata[], + public providerViewContext: ProviderViewContext, directives: CompileDirectiveSummary[], private _bindingParser: BindingParser, private _schemaRegistry: ElementSchemaRegistry, private _schemas: SchemaMetadata[], private _targetErrors: TemplateParseError[]) { - directives.forEach((directive: CompileDirectiveMetadata, index: number) => { + directives.forEach((directive, index) => { const selector = CssSelector.parse(directive.selector); this.selectorMatcher.addSelectables(selector, directive); this.directivesIndex.set(directive, index); @@ -360,7 +360,8 @@ class TemplateParseVisitor implements html.Visitor { componentDirectiveAst.directive.template)); const componentTemplate = providerContext.viewContext.component.template; - this._validateElementAnimationInputOutputs(elementProps, events, componentTemplate); + this._validateElementAnimationInputOutputs( + elementProps, events, componentTemplate.toSummary()); } if (hasInlineTemplates) { @@ -392,9 +393,9 @@ class TemplateParseVisitor implements html.Visitor { private _validateElementAnimationInputOutputs( inputs: BoundElementPropertyAst[], outputs: BoundEventAst[], - template: CompileTemplateMetadata) { + template: CompileTemplateSummary) { const triggerLookup = new Set(); - template.animations.forEach(entry => { triggerLookup.add(entry.name); }); + template.animations.forEach(entry => { triggerLookup.add(entry); }); const animationInputs = inputs.filter(input => input.isAnimation); animationInputs.forEach(input => { @@ -518,7 +519,7 @@ class TemplateParseVisitor implements html.Visitor { } private _parseDirectives(selectorMatcher: SelectorMatcher, elementCssSelector: CssSelector): - {directives: CompileDirectiveMetadata[], matchElement: boolean} { + {directives: CompileDirectiveSummary[], matchElement: boolean} { // Need to sort the directives so that we get consistent results throughout, // as selectorMatcher uses Maps inside. // Also deduplicate directives as they might match more than one time! @@ -538,12 +539,12 @@ class TemplateParseVisitor implements html.Visitor { } private _createDirectiveAsts( - isTemplateElement: boolean, elementName: string, directives: CompileDirectiveMetadata[], + isTemplateElement: boolean, elementName: string, directives: CompileDirectiveSummary[], props: BoundProperty[], elementOrDirectiveRefs: ElementOrDirectiveRef[], elementSourceSpan: ParseSourceSpan, targetReferences: ReferenceAst[]): DirectiveAst[] { const matchedReferences = new Set(); - let component: CompileDirectiveMetadata = null; - const directiveAsts = directives.map((directive: CompileDirectiveMetadata) => { + let component: CompileDirectiveSummary = null; + const directiveAsts = directives.map((directive) => { const sourceSpan = new ParseSourceSpan( elementSourceSpan.start, elementSourceSpan.end, `Directive ${directive.type.name}`); if (directive.isComponent) { @@ -837,3 +838,15 @@ const NON_BINDABLE_VISITOR = new NonBindableVisitor(); function _isEmptyTextNode(node: html.Node): boolean { return node instanceof html.Text && node.value.trim().length == 0; } + +export function removeSummaryDuplicates(items: T[]): T[] { + const map = new Map(); + + items.forEach((item) => { + if (!map.get(item.type.reference)) { + map.set(item.type.reference, item); + } + }); + + return Array.from(map.values()); +} diff --git a/modules/@angular/compiler/src/view_compiler/compile_element.ts b/modules/@angular/compiler/src/view_compiler/compile_element.ts index 722fb8ad9d..d0ba770711 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_element.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_element.ts @@ -7,7 +7,7 @@ */ -import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileIdentifierMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata} from '../compile_metadata'; +import {CompileDiDependencyMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata} from '../compile_metadata'; import {createDiTokenExpression} from '../compiler_util/identifier_util'; import {DirectiveWrapperCompiler, DirectiveWrapperExpressions} from '../directive_wrapper_compiler'; import {isPresent} from '../facade/lang'; @@ -54,8 +54,8 @@ export class CompileElement extends CompileNode { constructor( parent: CompileElement, view: CompileView, nodeIndex: number, renderNode: o.Expression, - sourceAst: TemplateAst, public component: CompileDirectiveMetadata, - private _directives: CompileDirectiveMetadata[], + sourceAst: TemplateAst, public component: CompileDirectiveSummary, + private _directives: CompileDirectiveSummary[], private _resolvedProvidersArray: ProviderAst[], public hasViewContainer: boolean, public hasEmbeddedView: boolean, references: ReferenceAst[], private _targetDependencies: diff --git a/modules/@angular/compiler/src/view_compiler/compile_pipe.ts b/modules/@angular/compiler/src/view_compiler/compile_pipe.ts index 6c27149ffe..f4697c3965 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_pipe.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_pipe.ts @@ -7,7 +7,7 @@ */ -import {CompilePipeMetadata} from '../compile_metadata'; +import {CompilePipeSummary} from '../compile_metadata'; import {createPureProxy} from '../compiler_util/identifier_util'; import {Identifiers, resolveIdentifier, resolveIdentifierToken} from '../identifiers'; import * as o from '../output/output_ast'; @@ -39,7 +39,7 @@ export class CompilePipe { instance: o.ReadPropExpr; private _purePipeProxyCount = 0; - constructor(public view: CompileView, public meta: CompilePipeMetadata) { + constructor(public view: CompileView, public meta: CompilePipeSummary) { this.instance = o.THIS_EXPR.prop(`_pipe_${meta.name}_${view.pipeCount++}`); var deps = this.meta.type.diDeps.map((diDep) => { if (diDep.token.reference === @@ -77,8 +77,8 @@ export class CompilePipe { } } -function _findPipeMeta(view: CompileView, name: string): CompilePipeMetadata { - var pipeMeta: CompilePipeMetadata = null; +function _findPipeMeta(view: CompileView, name: string): CompilePipeSummary { + var pipeMeta: CompilePipeSummary = null; for (var i = view.pipeMetas.length - 1; i >= 0; i--) { var localPipeMeta = view.pipeMetas[i]; if (localPipeMeta.name == name) { diff --git a/modules/@angular/compiler/src/view_compiler/compile_view.ts b/modules/@angular/compiler/src/view_compiler/compile_view.ts index 7bf7e5306f..dc5bfe4a1e 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_view.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_view.ts @@ -7,7 +7,7 @@ */ import {AnimationEntryCompileResult} from '../animation/animation_compiler'; -import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeMetadata} from '../compile_metadata'; +import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeSummary} from '../compile_metadata'; import {EventHandlerVars, NameResolver} from '../compiler_util/expression_converter'; import {createPureProxy} from '../compiler_util/identifier_util'; import {CompilerConfig} from '../config'; @@ -82,7 +82,7 @@ export class CompileView implements NameResolver { constructor( public component: CompileDirectiveMetadata, public genConfig: CompilerConfig, - public pipeMetas: CompilePipeMetadata[], public styles: o.Expression, + public pipeMetas: CompilePipeSummary[], public styles: o.Expression, public animations: AnimationEntryCompileResult[], public viewIndex: number, public declarationElement: CompileElement, public templateVariableBindings: string[][]) { this.createMethod = new CompileMethod(this); diff --git a/modules/@angular/compiler/src/view_compiler/lifecycle_binder.ts b/modules/@angular/compiler/src/view_compiler/lifecycle_binder.ts index 1e722529d1..cd5947b334 100644 --- a/modules/@angular/compiler/src/view_compiler/lifecycle_binder.ts +++ b/modules/@angular/compiler/src/view_compiler/lifecycle_binder.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {CompileDirectiveMetadata, CompilePipeMetadata} from '../compile_metadata'; +import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata'; import {DirectiveWrapperExpressions} from '../directive_wrapper_compiler'; import * as o from '../output/output_ast'; import {LifecycleHooks} from '../private_import_core'; @@ -20,7 +20,7 @@ var STATE_IS_NEVER_CHECKED = o.THIS_EXPR.prop('numberOfChecks').identical(new o. var NOT_THROW_ON_CHANGES = o.not(DetectChangesVars.throwOnChange); export function bindDirectiveAfterContentLifecycleCallbacks( - directiveMeta: CompileDirectiveMetadata, directiveInstance: o.Expression, + directiveMeta: CompileDirectiveSummary, directiveInstance: o.Expression, compileElement: CompileElement) { var view = compileElement.view; var lifecycleHooks = directiveMeta.type.lifecycleHooks; @@ -38,7 +38,7 @@ export function bindDirectiveAfterContentLifecycleCallbacks( } export function bindDirectiveAfterViewLifecycleCallbacks( - directiveMeta: CompileDirectiveMetadata, directiveInstance: o.Expression, + directiveMeta: CompileDirectiveSummary, directiveInstance: o.Expression, compileElement: CompileElement) { var view = compileElement.view; var lifecycleHooks = directiveMeta.type.lifecycleHooks; @@ -77,7 +77,7 @@ export function bindInjectableDestroyLifecycleCallbacks( } export function bindPipeDestroyLifecycleCallbacks( - pipeMeta: CompilePipeMetadata, pipeInstance: o.Expression, view: CompileView) { + pipeMeta: CompilePipeSummary, pipeInstance: o.Expression, view: CompileView) { var onDestroyMethod = view.destroyMethod; if (pipeMeta.type.lifecycleHooks.indexOf(LifecycleHooks.OnDestroy) !== -1) { onDestroyMethod.addStmt(pipeInstance.callMethod('ngOnDestroy', []).toStmt()); diff --git a/modules/@angular/compiler/src/view_compiler/util.ts b/modules/@angular/compiler/src/view_compiler/util.ts index 25a66e0ba1..7636d823b8 100644 --- a/modules/@angular/compiler/src/view_compiler/util.ts +++ b/modules/@angular/compiler/src/view_compiler/util.ts @@ -7,7 +7,7 @@ */ -import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata'; +import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata'; import {createDiTokenExpression} from '../compiler_util/identifier_util'; import {isPresent} from '../facade/lang'; import {Identifiers, resolveIdentifier} from '../identifiers'; @@ -72,7 +72,8 @@ export function injectFromViewParentInjector( } export function getViewClassName( - component: CompileDirectiveMetadata, embeddedTemplateIndex: number): string { + component: CompileDirectiveSummary | CompileDirectiveMetadata, + embeddedTemplateIndex: number): string { return `View_${component.type.name}${embeddedTemplateIndex}`; } diff --git a/modules/@angular/compiler/src/view_compiler/view_builder.ts b/modules/@angular/compiler/src/view_compiler/view_builder.ts index bf5d8409fe..caf53a8358 100644 --- a/modules/@angular/compiler/src/view_compiler/view_builder.ts +++ b/modules/@angular/compiler/src/view_compiler/view_builder.ts @@ -8,7 +8,7 @@ import {ViewEncapsulation} from '@angular/core'; -import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata'; +import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata'; import {createSharedBindingVariablesIfNeeded} from '../compiler_util/expression_converter'; import {createDiTokenExpression, createInlineArray} from '../compiler_util/identifier_util'; import {isPresent} from '../facade/lang'; @@ -336,7 +336,7 @@ function _isNgContainer(node: CompileNode, view: CompileView): boolean { function _mergeHtmlAndDirectiveAttrs( - declaredHtmlAttrs: {[key: string]: string}, directives: CompileDirectiveMetadata[]): string[] { + declaredHtmlAttrs: {[key: string]: string}, directives: CompileDirectiveSummary[]): string[] { const mapResult: {[key: string]: string} = {}; Object.keys(declaredHtmlAttrs).forEach(key => { mapResult[key] = declaredHtmlAttrs[key]; }); directives.forEach(directiveMeta => { diff --git a/modules/@angular/compiler/src/view_compiler/view_compiler.ts b/modules/@angular/compiler/src/view_compiler/view_compiler.ts index 1e10f1534b..99f62d3714 100644 --- a/modules/@angular/compiler/src/view_compiler/view_compiler.ts +++ b/modules/@angular/compiler/src/view_compiler/view_compiler.ts @@ -9,7 +9,7 @@ import {Injectable} from '@angular/core'; import {AnimationEntryCompileResult} from '../animation/animation_compiler'; -import {CompileDirectiveMetadata, CompilePipeMetadata} from '../compile_metadata'; +import {CompileDirectiveMetadata, CompilePipeSummary} from '../compile_metadata'; import {CompilerConfig} from '../config'; import * as o from '../output/output_ast'; import {ElementSchemaRegistry} from '../schema/element_schema_registry'; @@ -36,7 +36,7 @@ export class ViewCompiler { compileComponent( component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression, - pipes: CompilePipeMetadata[], + pipes: CompilePipeSummary[], compiledAnimations: AnimationEntryCompileResult[]): ViewCompileResult { const dependencies: Array = []; diff --git a/modules/@angular/compiler/test/template_parser/template_parser_spec.ts b/modules/@angular/compiler/test/template_parser/template_parser_spec.ts index a5785b5338..b9a01327a7 100644 --- a/modules/@angular/compiler/test/template_parser/template_parser_spec.ts +++ b/modules/@angular/compiler/test/template_parser/template_parser_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {CompileAnimationEntryMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata'; +import {CompileAnimationEntryMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata'; import {DomElementSchemaRegistry} from '@angular/compiler/src/schema/dom_element_schema_registry'; import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema_registry'; import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAstType, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '@angular/compiler/src/template_parser/template_ast'; @@ -16,6 +16,7 @@ import {SchemaMetadata, SecurityContext, Type} from '@angular/core'; import {Console} from '@angular/core/src/console'; import {TestBed} from '@angular/core/testing'; import {beforeEach, describe, expect, inject, it} from '@angular/core/testing/testing_internal'; + import {Identifiers, identifierToken, resolveIdentifierToken} from '../../src/identifiers'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../src/ml_parser/interpolation_config'; import {MockSchemaRegistry} from '../../testing/index'; @@ -31,9 +32,9 @@ const MOCK_SCHEMA_REGISTRY = [{ }]; export function main() { - var ngIf: CompileDirectiveMetadata; + var ngIf: CompileDirectiveSummary; var parse: ( - template: string, directives: CompileDirectiveMetadata[], pipes?: CompilePipeMetadata[], + template: string, directives: CompileDirectiveSummary[], pipes?: CompilePipeSummary[], schemas?: SchemaMetadata[]) => TemplateAst[]; var console: ArrayConsole; @@ -52,17 +53,19 @@ export function main() { {moduleUrl: someModuleUrl, name: 'Root', reference: {} as Type}), isComponent: true }); - ngIf = CompileDirectiveMetadata.create({ - selector: '[ngIf]', - template: someTemplate, - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'NgIf', reference: {} as Type}), - inputs: ['ngIf'] - }); + ngIf = CompileDirectiveMetadata + .create({ + selector: '[ngIf]', + template: someTemplate, + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'NgIf', reference: {} as Type}), + inputs: ['ngIf'] + }) + .toSummary(); parse = - (template: string, directives: CompileDirectiveMetadata[], - pipes: CompilePipeMetadata[] = null, schemas: SchemaMetadata[] = []): TemplateAst[] => { + (template: string, directives: CompileDirectiveSummary[], + pipes: CompilePipeSummary[] = null, schemas: SchemaMetadata[] = []): TemplateAst[] => { if (pipes === null) { pipes = []; } @@ -462,25 +465,34 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { const animationEntries = [new CompileAnimationEntryMetadata('prop', [])]; - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - template: new CompileTemplateMetadata({animations: animationEntries}), - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - host: {'[@prop]': 'expr'} - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + template: new CompileTemplateMetadata({animations: animationEntries}), + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: 'DirA', + reference: {} as Type + }), + host: {'[@prop]': 'expr'} + }) + .toSummary(); humanizeTplAst(parse('
', [dirA])); expect(console.warnings.length).toEqual(0); }); it('should throw descriptive error when a host binding is not a string expression', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: 'broken', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - host: {'[class.foo]': null} - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'broken', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + host: {'[class.foo]': null} + }) + .toSummary(); expect(() => { parse('', [dirA]); }) .toThrowError( @@ -488,12 +500,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: 'broken', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - host: {'(click)': null} - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'broken', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + host: {'(click)': null} + }) + .toSummary(); expect(() => { parse('', [dirA]); }) .toThrowError( @@ -553,12 +568,17 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: 'template', - outputs: ['e'], - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); + var dirA = CompileDirectiveMetadata + .create({ + selector: 'template', + outputs: ['e'], + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: 'DirA', + reference: {} as Type + }) + }) + .toSummary(); expect(humanizeTplAst(parse('', [dirA]))).toEqual([ [EmbeddedTemplateAst], [BoundEventAst, 'e', null, 'f'], @@ -591,21 +611,36 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { it('should order directives by the directives array in the View and match them only once', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); - var dirB = CompileDirectiveMetadata.create({ - selector: '[b]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type}) - }); - var dirC = CompileDirectiveMetadata.create({ - selector: '[c]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirC', reference: {} as Type}) - }); + var dirA = CompileDirectiveMetadata + .create({ + selector: '[a]', + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: 'DirA', + reference: {} as Type + }) + }) + .toSummary(); + var dirB = CompileDirectiveMetadata + .create({ + selector: '[b]', + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: 'DirB', + reference: {} as Type + }) + }) + .toSummary(); + var dirC = CompileDirectiveMetadata + .create({ + selector: '[c]', + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: 'DirC', + reference: {} as Type + }) + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA, dirB, dirC]))).toEqual([ [ElementAst, 'div'], [AttrAst, 'a', ''], [AttrAst, 'c', ''], [AttrAst, 'b', ''], [AttrAst, 'a', ''], [AttrAst, 'b', ''], [DirectiveAst, dirA], @@ -614,16 +649,22 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a=b]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); - var dirB = CompileDirectiveMetadata.create({ - selector: '[b]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a=b]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) + }) + .toSummary(); + var dirB = + CompileDirectiveMetadata + .create({ + selector: '[b]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type}) + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA, dirB]))).toEqual([ [ElementAst, 'div'], [BoundElementPropertyAst, PropertyBindingType.Property, 'a', 'b', null], @@ -632,11 +673,14 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type}) + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [BoundEventAst, 'a', null, 'b'], [DirectiveAst, dirA] @@ -644,12 +688,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - host: {'[a]': 'expr'} - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + host: {'[a]': 'expr'} + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [DirectiveAst, dirA], [BoundElementPropertyAst, PropertyBindingType.Property, 'a', 'expr', null] @@ -657,24 +704,30 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - host: {'(a)': 'expr'} - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + host: {'(a)': 'expr'} + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [DirectiveAst, dirA], [BoundEventAst, 'a', null, 'expr'] ]); }); it('should parse directive properties', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - inputs: ['aProp'] - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + inputs: ['aProp'] + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [DirectiveAst, dirA], [BoundDirectivePropertyAst, 'aProp', 'expr'] @@ -682,12 +735,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - inputs: ['b:a'] - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + inputs: ['b:a'] + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [DirectiveAst, dirA], [BoundDirectivePropertyAst, 'b', 'expr'] @@ -695,12 +751,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - inputs: ['a'] - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + inputs: ['a'] + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [AttrAst, 'a', 'literal'], [DirectiveAst, dirA], [BoundDirectivePropertyAst, 'a', '"literal"'] @@ -708,12 +767,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - inputs: ['a'] - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + inputs: ['a'] + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))) .toEqual([ [ElementAst, 'div'], [AttrAst, 'a', 'literal'], [DirectiveAst, dirA], @@ -722,12 +784,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - inputs: ['a'] - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + inputs: ['a'] + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [DirectiveAst, dirA] ]); @@ -795,23 +860,25 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" - }), - isComponent: isComponent, - template: new CompileTemplateMetadata({ngContentSelectors: []}), - providers: providers, - viewProviders: viewProviders, - queries: queries.map( - (value) => new CompileQueryMetadata({selectors: [createToken(value)]})) - }); + return CompileDirectiveMetadata + .create({ + selector: selector, + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: selector, + diDeps: deps.map(createDep), + reference: selector as any as Type + }), + isComponent: isComponent, + template: new CompileTemplateMetadata({ngContentSelectors: []}), + providers: providers, + viewProviders: viewProviders, + queries: queries.map( + (value) => new CompileQueryMetadata({selectors: [createToken(value)]})) + }) + .toSummary(); } beforeEach(() => { nextProviderId = 0; }); @@ -1051,12 +1118,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons (" { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - exportAs: 'dirA' - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + exportAs: 'dirA' + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [AttrAst, 'a', ''], @@ -1095,14 +1165,17 @@ Reference "#a" is defined several times ("
]#a>
}); it('should assign references with empty value to components', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - isComponent: true, - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - exportAs: 'dirA', - template: new CompileTemplateMetadata({ngContentSelectors: []}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a]', + isComponent: true, + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + exportAs: 'dirA', + template: new CompileTemplateMetadata({ngContentSelectors: []}) + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [AttrAst, 'a', ''], @@ -1112,11 +1185,14 @@ Reference "#a" is defined several times ("
]#a>
}); it('should not locate directives in references', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [ReferenceAst, 'a', null] ]); @@ -1159,11 +1235,14 @@ Reference "#a" is defined several times ("
]#a>
}); it('should not locate directives in variables', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) + }) + .toSummary(); expect(humanizeTplAst(parse('', [dirA]))).toEqual([ [EmbeddedTemplateAst], [VariableAst, 'a', 'b'] ]); @@ -1202,17 +1281,25 @@ Reference "#a" is defined several times ("
]#a>
describe('directives', () => { it('should locate directives in property bindings', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a=b]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - inputs: ['a'] - }); - var dirB = CompileDirectiveMetadata.create({ - selector: '[b]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a=b]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + inputs: ['a'] + }) + .toSummary(); + var dirB = CompileDirectiveMetadata + .create({ + selector: '[b]', + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: 'DirB', + reference: {} as Type + }) + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA, dirB]))).toEqual([ [EmbeddedTemplateAst], [DirectiveAst, dirA], [BoundDirectivePropertyAst, 'a', 'b'], [ElementAst, 'div'], [AttrAst, 'b', ''], @@ -1221,22 +1308,32 @@ Reference "#a" is defined several times ("
]#a>
}); it('should not locate directives in variables', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); + var dirA = CompileDirectiveMetadata + .create({ + selector: '[a]', + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: 'DirA', + reference: {} as Type + }) + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [EmbeddedTemplateAst], [VariableAst, 'a', 'b'], [ElementAst, 'div'] ]); }); it('should not locate directives in references', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); + var dirA = CompileDirectiveMetadata + .create({ + selector: '[a]', + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: 'DirA', + reference: {} as Type + }) + }) + .toSummary(); expect(humanizeTplAst(parse('
', [dirA]))).toEqual([ [ElementAst, 'div'], [ReferenceAst, 'a', null] ]); @@ -1265,28 +1362,32 @@ Reference "#a" is defined several times ("
]#a>
beforeEach(() => { compCounter = 0; }); function createComp( - selector: string, ngContentSelectors: string[]): CompileDirectiveMetadata { - return CompileDirectiveMetadata.create({ - selector: selector, - isComponent: true, - type: new CompileTypeMetadata({ - moduleUrl: someModuleUrl, - name: `SomeComp${compCounter++}`, - reference: {} as Type - }), - template: new CompileTemplateMetadata({ngContentSelectors: ngContentSelectors}) - }); + selector: string, ngContentSelectors: string[]): CompileDirectiveSummary { + return CompileDirectiveMetadata + .create({ + selector: selector, + isComponent: true, + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: `SomeComp${compCounter++}`, + reference: {} as Type + }), + template: new CompileTemplateMetadata({ngContentSelectors: ngContentSelectors}) + }) + .toSummary(); } - function createDir(selector: string): CompileDirectiveMetadata { - return CompileDirectiveMetadata.create({ - selector: selector, - type: new CompileTypeMetadata({ - moduleUrl: someModuleUrl, - name: `SomeDir${compCounter++}`, - reference: {} as Type - }) - }); + function createDir(selector: string): CompileDirectiveSummary { + return CompileDirectiveMetadata + .create({ + selector: selector, + type: new CompileTypeMetadata({ + moduleUrl: someModuleUrl, + name: `SomeDir${compCounter++}`, + reference: {} as Type + }) + }) + .toSummary(); } describe('project text nodes', () => { @@ -1454,12 +1555,15 @@ Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("
{ - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - host: {'[invalidProp]': 'someProp'} - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + host: {'[invalidProp]': 'someProp'} + }) + .toSummary(); expect(() => parse('
', [dirA])).toThrowError(`Template parse errors: Can't bind to 'invalidProp' since it isn't a known property of 'div'. ("[ERROR ->]
"): TestComp@0:0, Directive DirA`); }); @@ -1471,30 +1575,39 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("
{ - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - inputs: ['invalidProp'] - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + inputs: ['invalidProp'] + }) + .toSummary(); expect(() => parse('
', [dirA])).not.toThrow(); }); it('should not allow more than 1 component per element', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - isComponent: true, - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - template: new CompileTemplateMetadata({ngContentSelectors: []}) - }); - var dirB = CompileDirectiveMetadata.create({ - selector: 'div', - isComponent: true, - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type}), - template: new CompileTemplateMetadata({ngContentSelectors: []}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + isComponent: true, + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + template: new CompileTemplateMetadata({ngContentSelectors: []}) + }) + .toSummary(); + var dirB = + CompileDirectiveMetadata + .create({ + selector: 'div', + isComponent: true, + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirB', reference: {} as Type}), + template: new CompileTemplateMetadata({ngContentSelectors: []}) + }) + .toSummary(); expect(() => parse('
', [dirB, dirA])) .toThrowError( `Template parse errors:\n` + @@ -1505,13 +1618,16 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("
{ - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - isComponent: true, - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - template: new CompileTemplateMetadata({ngContentSelectors: []}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a]', + isComponent: true, + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + template: new CompileTemplateMetadata({ngContentSelectors: []}) + }) + .toSummary(); expect(() => parse('', [dirA])) .toThrowError(`Template parse errors: Event binding e not emitted by any directive on an embedded template. Make sure that the event name is spelled correctly and all directives are listed in the "directives" section. (""): TestComp@0:18 @@ -1520,13 +1636,16 @@ Property binding a not used by any directive on an embedded template. Make sure }); it('should not allow components or element bindings on inline embedded templates', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - isComponent: true, - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - template: new CompileTemplateMetadata({ngContentSelectors: []}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a]', + isComponent: true, + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + template: new CompileTemplateMetadata({ngContentSelectors: []}) + }) + .toSummary(); expect(() => parse('
', [dirA])).toThrowError(`Template parse errors: Components on an embedded template: DirA ("[ERROR ->]
"): TestComp@0:0 Property binding a not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "directives" section. ("[ERROR ->]
"): TestComp@0:0`); @@ -1678,18 +1797,24 @@ Property binding a not used by any directive on an embedded template. Make sure }); it('should support directive', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: '[a]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); - var comp = CompileDirectiveMetadata.create({ - selector: 'div', - isComponent: true, - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'ZComp', reference: {} as Type}), - template: new CompileTemplateMetadata({ngContentSelectors: []}) - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: '[a]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) + }) + .toSummary(); + var comp = + CompileDirectiveMetadata + .create({ + selector: 'div', + isComponent: true, + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'ZComp', reference: {} as Type}), + template: new CompileTemplateMetadata({ngContentSelectors: []}) + }) + .toSummary(); expect(humanizeTplAstSourceSpans(parse('
', [dirA, comp]))).toEqual([ [ElementAst, 'div', '
'], [AttrAst, 'a', '', 'a'], [DirectiveAst, dirA, '
'], [DirectiveAst, comp, '
'] @@ -1697,16 +1822,22 @@ Property binding a not used by any directive on an embedded template. Make sure }); it('should support directive in namespace', () => { - var tagSel = CompileDirectiveMetadata.create({ - selector: 'circle', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'elDir', reference: {} as Type}) - }); - var attrSel = CompileDirectiveMetadata.create({ - selector: '[href]', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'attrDir', reference: {} as Type}) - }); + var tagSel = + CompileDirectiveMetadata + .create({ + selector: 'circle', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'elDir', reference: {} as Type}) + }) + .toSummary(); + var attrSel = + CompileDirectiveMetadata + .create({ + selector: '[href]', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'attrDir', reference: {} as Type}) + }) + .toSummary(); expect(humanizeTplAstSourceSpans( parse('', [tagSel, attrSel]))) @@ -1721,12 +1852,15 @@ Property binding a not used by any directive on an embedded template. Make sure }); it('should support directive property', () => { - var dirA = CompileDirectiveMetadata.create({ - selector: 'div', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), - inputs: ['aProp'] - }); + var dirA = + CompileDirectiveMetadata + .create({ + selector: 'div', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}), + inputs: ['aProp'] + }) + .toSummary(); expect(humanizeTplAstSourceSpans(parse('
', [dirA]))).toEqual([ [ElementAst, 'div', '
'], [DirectiveAst, dirA, '
'], @@ -1735,11 +1869,14 @@ Property binding a not used by any directive on an embedded template. Make sure }); it('should support endSourceSpan for elements', () => { - const tagSel = CompileDirectiveMetadata.create({ - selector: 'circle', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'elDir', reference: {} as Type}) - }); + const tagSel = + CompileDirectiveMetadata + .create({ + selector: 'circle', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'elDir', reference: {} as Type}) + }) + .toSummary(); const result = parse('', [tagSel]); const circle = result[0] as ElementAst; expect(circle.endSourceSpan).toBeDefined(); @@ -1748,16 +1885,22 @@ Property binding a not used by any directive on an embedded template. Make sure }); it('should report undefined for endSourceSpan for elements without an end-tag', () => { - const ulSel = CompileDirectiveMetadata.create({ - selector: 'ul', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'ulDir', reference: {} as Type}) - }); - const liSel = CompileDirectiveMetadata.create({ - selector: 'li', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'liDir', reference: {} as Type}) - }); + const ulSel = + CompileDirectiveMetadata + .create({ + selector: 'ul', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'ulDir', reference: {} as Type}) + }) + .toSummary(); + const liSel = + CompileDirectiveMetadata + .create({ + selector: 'li', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'liDir', reference: {} as Type}) + }) + .toSummary(); const result = parse('
', [ulSel, liSel]); const ul = result[0] as ElementAst; const li = ul.children[0] as ElementAst; @@ -1767,11 +1910,12 @@ Property binding a not used by any directive on an embedded template. Make sure describe('pipes', () => { it('should allow pipes that have been defined as dependencies', () => { - var testPipe = new CompilePipeMetadata({ - name: 'test', - type: new CompileTypeMetadata( - {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) - }); + var testPipe = + new CompilePipeMetadata({ + name: 'test', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'DirA', reference: {} as Type}) + }).toSummary(); expect(() => parse('{{a | test}}', [], [testPipe])).not.toThrow(); });