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