refactor(compiler): convert metadata classes used in summaries into interfaces (#13123)

Part of #12787
This commit is contained in:
Tobias Bosch 2016-11-30 10:52:51 -08:00 committed by Alex Rickabaugh
parent 42cf06fa12
commit 3e73bea3e7
15 changed files with 441 additions and 547 deletions

View File

@ -113,17 +113,17 @@ export class AotCompiler {
const providers: CompileProviderMetadata[] = []; const providers: CompileProviderMetadata[] = [];
if (this._localeId) { if (this._localeId) {
providers.push(new CompileProviderMetadata({ providers.push({
token: createIdentifierToken(Identifiers.LOCALE_ID), token: createIdentifierToken(Identifiers.LOCALE_ID),
useValue: this._localeId, useValue: this._localeId,
})); });
} }
if (this._translationFormat) { if (this._translationFormat) {
providers.push(new CompileProviderMetadata({ providers.push({
token: createIdentifierToken(Identifiers.TRANSLATIONS_FORMAT), token: createIdentifierToken(Identifiers.TRANSLATIONS_FORMAT),
useValue: this._translationFormat useValue: this._translationFormat
})); });
} }
const appCompileResult = this._ngModuleCompiler.compile(ngModule, providers); const appCompileResult = this._ngModuleCompiler.compile(ngModule, providers);

View File

@ -112,11 +112,7 @@ export function identifierModuleUrl(compileIdentifier: CompileIdentifierMetadata
return reflector.importUri(ref); return reflector.importUri(ref);
} }
export class CompileIdentifierMetadata { export interface CompileIdentifierMetadata { reference: any; }
reference: any;
constructor({reference}: {reference?: any} = {}) { this.reference = reference; }
}
/** /**
* A CompileSummary is the data needed to use a directive / pipe / module * A CompileSummary is the data needed to use a directive / pipe / module
@ -127,74 +123,30 @@ export interface CompileSummary {
isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */;
} }
export class CompileDiDependencyMetadata { export interface CompileDiDependencyMetadata {
isAttribute: boolean; isAttribute?: boolean;
isSelf: boolean; isSelf?: boolean;
isHost: boolean; isHost?: boolean;
isSkipSelf: boolean; isSkipSelf?: boolean;
isOptional: boolean; isOptional?: boolean;
isValue: boolean; isValue?: boolean;
token: CompileTokenMetadata; token?: CompileTokenMetadata;
value: any; value?: any;
constructor({isAttribute, isSelf, isHost, isSkipSelf, isOptional, isValue, token, value}: {
isAttribute?: boolean,
isSelf?: boolean,
isHost?: boolean,
isSkipSelf?: boolean,
isOptional?: boolean,
isValue?: boolean,
query?: CompileQueryMetadata,
viewQuery?: CompileQueryMetadata,
token?: CompileTokenMetadata,
value?: any
} = {}) {
this.isAttribute = !!isAttribute;
this.isSelf = !!isSelf;
this.isHost = !!isHost;
this.isSkipSelf = !!isSkipSelf;
this.isOptional = !!isOptional;
this.isValue = !!isValue;
this.token = token;
this.value = value;
}
} }
export class CompileProviderMetadata { export interface CompileProviderMetadata {
token: CompileTokenMetadata; token: CompileTokenMetadata;
useClass: CompileTypeMetadata; useClass?: CompileTypeMetadata;
useValue: any; useValue?: any;
useExisting: CompileTokenMetadata; useExisting?: CompileTokenMetadata;
useFactory: CompileFactoryMetadata; useFactory?: CompileFactoryMetadata;
deps: CompileDiDependencyMetadata[]; deps?: CompileDiDependencyMetadata[];
multi: boolean; multi?: boolean;
constructor({token, useClass, useValue, useExisting, useFactory, deps, multi}: {
token?: CompileTokenMetadata,
useClass?: CompileTypeMetadata,
useValue?: any,
useExisting?: CompileTokenMetadata,
useFactory?: CompileFactoryMetadata,
deps?: CompileDiDependencyMetadata[],
multi?: boolean
}) {
this.token = token;
this.useClass = useClass;
this.useValue = useValue;
this.useExisting = useExisting;
this.useFactory = useFactory;
this.deps = deps || null;
this.multi = !!multi;
}
} }
export class CompileFactoryMetadata extends CompileIdentifierMetadata { export interface CompileFactoryMetadata extends CompileIdentifierMetadata {
diDeps: CompileDiDependencyMetadata[]; diDeps: CompileDiDependencyMetadata[];
reference: any;
constructor({reference, diDeps}: {reference?: Function, diDeps?: CompileDiDependencyMetadata[]}) {
super({reference: reference});
this.diDeps = _normalizeArray(diDeps);
}
} }
export function tokenName(token: CompileTokenMetadata) { export function tokenName(token: CompileTokenMetadata) {
@ -210,54 +162,26 @@ export function tokenReference(token: CompileTokenMetadata) {
} }
} }
export class CompileTokenMetadata { export interface CompileTokenMetadata {
value: any; value?: any;
identifier: CompileIdentifierMetadata; identifier?: CompileIdentifierMetadata|CompileTypeMetadata;
constructor({value, identifier}: {value?: any, identifier?: CompileIdentifierMetadata}) {
this.value = value;
this.identifier = identifier;
}
} }
/** /**
* Metadata regarding compilation of a type. * Metadata regarding compilation of a type.
*/ */
export class CompileTypeMetadata extends CompileIdentifierMetadata { export interface CompileTypeMetadata extends CompileIdentifierMetadata {
diDeps: CompileDiDependencyMetadata[]; diDeps: CompileDiDependencyMetadata[];
lifecycleHooks: LifecycleHooks[]; lifecycleHooks: LifecycleHooks[];
reference: any;
constructor({reference, diDeps, lifecycleHooks}: {
reference?: Type<any>| StaticSymbol,
diDeps?: CompileDiDependencyMetadata[],
lifecycleHooks?: LifecycleHooks[];
} = {}) {
super({reference: reference});
this.diDeps = _normalizeArray(diDeps);
this.lifecycleHooks = _normalizeArray(lifecycleHooks);
}
} }
export class CompileQueryMetadata { export interface CompileQueryMetadata {
selectors: Array<CompileTokenMetadata>; selectors: Array<CompileTokenMetadata>;
descendants: boolean; descendants: boolean;
first: boolean; first: boolean;
propertyName: string; propertyName: string;
read: CompileTokenMetadata; read: CompileTokenMetadata;
constructor({selectors, descendants, first, propertyName, read}: {
selectors?: Array<CompileTokenMetadata>,
descendants?: boolean,
first?: boolean,
propertyName?: string,
read?: CompileTokenMetadata
} = {}) {
this.selectors = selectors;
this.descendants = !!descendants;
this.first = !!first;
this.propertyName = propertyName;
this.read = read;
}
} }
/** /**
@ -336,6 +260,8 @@ export class CompileTemplateMetadata {
} }
} }
// Note: This should only use interfaces as nested data types
// as we need to be able to serialize this from/to JSON!
export interface CompileDirectiveSummary extends CompileSummary { export interface CompileDirectiveSummary extends CompileSummary {
isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */;
type: CompileTypeMetadata; type: CompileTypeMetadata;
@ -371,10 +297,8 @@ export class CompileDirectiveMetadata {
inputs?: string[], inputs?: string[],
outputs?: string[], outputs?: string[],
host?: {[key: string]: string}, host?: {[key: string]: string},
providers?: providers?: CompileProviderMetadata[],
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, viewProviders?: CompileProviderMetadata[],
viewProviders?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
queries?: CompileQueryMetadata[], queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[], viewQueries?: CompileQueryMetadata[],
entryComponents?: CompileIdentifierMetadata[], entryComponents?: CompileIdentifierMetadata[],
@ -466,10 +390,8 @@ export class CompileDirectiveMetadata {
hostListeners?: {[key: string]: string}, hostListeners?: {[key: string]: string},
hostProperties?: {[key: string]: string}, hostProperties?: {[key: string]: string},
hostAttributes?: {[key: string]: string}, hostAttributes?: {[key: string]: string},
providers?: providers?: CompileProviderMetadata[],
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>, viewProviders?: CompileProviderMetadata[],
viewProviders?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
queries?: CompileQueryMetadata[], queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[], viewQueries?: CompileQueryMetadata[],
entryComponents?: CompileIdentifierMetadata[], entryComponents?: CompileIdentifierMetadata[],
@ -525,7 +447,7 @@ export function createHostComponentMeta(
const template = CssSelector.parse(compMeta.selector)[0].getMatchingElementTemplate(); const template = CssSelector.parse(compMeta.selector)[0].getMatchingElementTemplate();
return CompileDirectiveMetadata.create({ return CompileDirectiveMetadata.create({
isHost: true, isHost: true,
type: new CompileTypeMetadata({reference: typeReference}), type: {reference: typeReference, diDeps: [], lifecycleHooks: []},
template: new CompileTemplateMetadata({ template: new CompileTemplateMetadata({
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
template: template, template: template,
@ -575,6 +497,8 @@ export class CompilePipeMetadata {
} }
} }
// Note: This should only use interfaces as nested data types
// as we need to be able to serialize this from/to JSON!
export interface CompileNgModuleInjectorSummary extends CompileSummary { export interface CompileNgModuleInjectorSummary extends CompileSummary {
isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */;
type: CompileTypeMetadata; type: CompileTypeMetadata;
@ -584,6 +508,8 @@ export interface CompileNgModuleInjectorSummary extends CompileSummary {
exportedModules: CompileNgModuleInjectorSummary[]; exportedModules: CompileNgModuleInjectorSummary[];
} }
// Note: This should only use interfaces as nested data types
// as we need to be able to serialize this from/to JSON!
export interface CompileNgModuleDirectiveSummary extends CompileSummary { export interface CompileNgModuleDirectiveSummary extends CompileSummary {
isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */; isSummary: boolean /* TODO: `true` when we drop TS 1.8 support */;
type: CompileTypeMetadata; type: CompileTypeMetadata;
@ -593,6 +519,8 @@ export interface CompileNgModuleDirectiveSummary extends CompileSummary {
directiveLoaders: (() => Promise<void>)[]; directiveLoaders: (() => Promise<void>)[];
} }
// Note: This should only use interfaces as nested data types
// as we need to be able to serialize this from/to JSON!
export type CompileNgModuleSummary = export type CompileNgModuleSummary =
CompileNgModuleInjectorSummary & CompileNgModuleDirectiveSummary; CompileNgModuleInjectorSummary & CompileNgModuleDirectiveSummary;
@ -621,8 +549,7 @@ export class CompileNgModuleMetadata {
entryComponents, bootstrapComponents, importedModules, exportedModules, schemas, entryComponents, bootstrapComponents, importedModules, exportedModules, schemas,
transitiveModule, id}: { transitiveModule, id}: {
type?: CompileTypeMetadata, type?: CompileTypeMetadata,
providers?: providers?: CompileProviderMetadata[],
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
declaredDirectives?: CompileIdentifierMetadata[], declaredDirectives?: CompileIdentifierMetadata[],
exportedDirectives?: CompileIdentifierMetadata[], exportedDirectives?: CompileIdentifierMetadata[],
declaredPipes?: CompileIdentifierMetadata[], declaredPipes?: CompileIdentifierMetadata[],

View File

@ -350,14 +350,14 @@ export function resolveIdentifier(identifier: IdentifierSpec) {
return reflector.resolveIdentifier(identifier.name, identifier.moduleUrl, identifier.runtime); return reflector.resolveIdentifier(identifier.name, identifier.moduleUrl, identifier.runtime);
} }
export function createIdentifier(identifier: IdentifierSpec) { export function createIdentifier(identifier: IdentifierSpec): CompileIdentifierMetadata {
const reference = const reference =
reflector.resolveIdentifier(identifier.name, identifier.moduleUrl, identifier.runtime); reflector.resolveIdentifier(identifier.name, identifier.moduleUrl, identifier.runtime);
return new CompileIdentifierMetadata({reference: reference}); return {reference: reference};
} }
export function identifierToken(identifier: CompileIdentifierMetadata): CompileTokenMetadata { export function identifierToken(identifier: CompileIdentifierMetadata): CompileTokenMetadata {
return new CompileTokenMetadata({identifier: identifier}); return {identifier: identifier};
} }
export function createIdentifierToken(identifier: IdentifierSpec): CompileTokenMetadata { export function createIdentifierToken(identifier: IdentifierSpec): CompileTokenMetadata {
@ -367,5 +367,5 @@ export function createIdentifierToken(identifier: IdentifierSpec): CompileTokenM
export function createEnumIdentifier( export function createEnumIdentifier(
enumType: IdentifierSpec, name: string): CompileIdentifierMetadata { enumType: IdentifierSpec, name: string): CompileIdentifierMetadata {
const resolvedEnum = reflector.resolveEnum(resolveIdentifier(enumType), name); const resolvedEnum = reflector.resolveEnum(resolveIdentifier(enumType), name);
return new CompileIdentifierMetadata({reference: resolvedEnum}); return {reference: resolvedEnum};
} }

View File

@ -216,7 +216,7 @@ export class CompileMetadataResolver {
} }
let changeDetectionStrategy: ChangeDetectionStrategy = null; let changeDetectionStrategy: ChangeDetectionStrategy = null;
let viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; let viewProviders: cpl.CompileProviderMetadata[] = [];
let entryComponentMetadata: cpl.CompileIdentifierMetadata[] = []; let entryComponentMetadata: cpl.CompileIdentifierMetadata[] = [];
let selector = dirMeta.selector; let selector = dirMeta.selector;
@ -243,7 +243,7 @@ export class CompileMetadataResolver {
} }
} }
let providers: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; let providers: cpl.CompileProviderMetadata[] = [];
if (isPresent(dirMeta.providers)) { if (isPresent(dirMeta.providers)) {
providers = this._getProvidersMetadata( providers = this._getProvidersMetadata(
dirMeta.providers, entryComponentMetadata, `providers for "${stringify(directiveType)}"`); dirMeta.providers, entryComponentMetadata, `providers for "${stringify(directiveType)}"`);
@ -557,24 +557,23 @@ export class CompileMetadataResolver {
private _getIdentifierMetadata(type: Type<any>): cpl.CompileIdentifierMetadata { private _getIdentifierMetadata(type: Type<any>): cpl.CompileIdentifierMetadata {
type = resolveForwardRef(type); type = resolveForwardRef(type);
return new cpl.CompileIdentifierMetadata({reference: type}); return {reference: type};
} }
private _getTypeMetadata(type: Type<any>, dependencies: any[] = null): cpl.CompileTypeMetadata { private _getTypeMetadata(type: Type<any>, dependencies: any[] = null): cpl.CompileTypeMetadata {
const identifier = this._getIdentifierMetadata(type); const identifier = this._getIdentifierMetadata(type);
return new cpl.CompileTypeMetadata({ return {
reference: identifier.reference, reference: identifier.reference,
diDeps: this._getDependenciesMetadata(identifier.reference, dependencies), diDeps: this._getDependenciesMetadata(identifier.reference, dependencies),
lifecycleHooks: lifecycleHooks:
LIFECYCLE_HOOKS_VALUES.filter(hook => hasLifecycleHook(hook, identifier.reference)), LIFECYCLE_HOOKS_VALUES.filter(hook => hasLifecycleHook(hook, identifier.reference)),
}); };
} }
private _getFactoryMetadata(factory: Function, dependencies: any[] = null): private _getFactoryMetadata(factory: Function, dependencies: any[] = null):
cpl.CompileFactoryMetadata { cpl.CompileFactoryMetadata {
factory = resolveForwardRef(factory); factory = resolveForwardRef(factory);
return new cpl.CompileFactoryMetadata( return {reference: factory, diDeps: this._getDependenciesMetadata(factory, dependencies)};
{reference: factory, diDeps: this._getDependenciesMetadata(factory, dependencies)});
} }
/** /**
@ -660,14 +659,14 @@ export class CompileMetadataResolver {
return null; return null;
} }
return new cpl.CompileDiDependencyMetadata({ return {
isAttribute, isAttribute,
isHost, isHost,
isSelf, isSelf,
isSkipSelf, isSkipSelf,
isOptional, isOptional,
token: this._getTokenMetadata(token) token: this._getTokenMetadata(token)
}); };
}); });
@ -685,57 +684,50 @@ export class CompileMetadataResolver {
token = resolveForwardRef(token); token = resolveForwardRef(token);
let compileToken: cpl.CompileTokenMetadata; let compileToken: cpl.CompileTokenMetadata;
if (typeof token === 'string') { if (typeof token === 'string') {
compileToken = new cpl.CompileTokenMetadata({value: token}); compileToken = {value: token};
} else { } else {
compileToken = new cpl.CompileTokenMetadata( compileToken = {identifier: {reference: token}};
{identifier: new cpl.CompileIdentifierMetadata({reference: token})});
} }
return compileToken; return compileToken;
} }
private _getProvidersMetadata( private _getProvidersMetadata(
providers: Provider[], targetEntryComponents: cpl.CompileIdentifierMetadata[], providers: Provider[], targetEntryComponents: cpl.CompileIdentifierMetadata[],
debugInfo?: string): Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> { debugInfo?: string,
const compileProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; compileProviders: cpl.CompileProviderMetadata[] = []): cpl.CompileProviderMetadata[] {
providers.forEach((provider: any, providerIdx: number) => { providers.forEach((provider: any, providerIdx: number) => {
provider = resolveForwardRef(provider);
if (provider && typeof provider == 'object' && provider.hasOwnProperty('provide')) {
provider = new cpl.ProviderMeta(provider.provide, provider);
}
let compileProvider: cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[];
if (Array.isArray(provider)) { if (Array.isArray(provider)) {
compileProvider = this._getProvidersMetadata(provider, targetEntryComponents, debugInfo); this._getProvidersMetadata(provider, targetEntryComponents, debugInfo, compileProviders);
} else if (provider instanceof cpl.ProviderMeta) {
const tokenMeta = this._getTokenMetadata(provider.token);
if (cpl.tokenReference(tokenMeta) ===
resolveIdentifier(Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS)) {
targetEntryComponents.push(...this._getEntryComponentsFromProvider(provider));
} else {
compileProvider = this.getProviderMetadata(provider);
}
} else if (isValidType(provider)) {
compileProvider = this._getTypeMetadata(provider);
} else { } else {
const providersInfo = provider = resolveForwardRef(provider);
(<string[]>providers.reduce( let providerMeta: cpl.ProviderMeta;
(soFar: string[], seenProvider: any, seenProviderIdx: number) => { if (provider && typeof provider == 'object' && provider.hasOwnProperty('provide')) {
if (seenProviderIdx < providerIdx) { providerMeta = new cpl.ProviderMeta(provider.provide, provider);
soFar.push(`${stringify(seenProvider)}`); } else if (isValidType(provider)) {
} else if (seenProviderIdx == providerIdx) { providerMeta = new cpl.ProviderMeta(provider, {useClass: provider});
soFar.push(`?${stringify(seenProvider)}?`); } else {
} else if (seenProviderIdx == providerIdx + 1) { const providersInfo =
soFar.push('...'); (<string[]>providers.reduce(
} (soFar: string[], seenProvider: any, seenProviderIdx: number) => {
return soFar; if (seenProviderIdx < providerIdx) {
}, soFar.push(`${stringify(seenProvider)}`);
[])) } else if (seenProviderIdx == providerIdx) {
.join(', '); soFar.push(`?${stringify(seenProvider)}?`);
} else if (seenProviderIdx == providerIdx + 1) {
throw new Error( soFar.push('...');
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`); }
} return soFar;
if (compileProvider) { },
compileProviders.push(compileProvider); []))
.join(', ');
throw new Error(
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`);
}
if (providerMeta.token === resolveIdentifier(Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS)) {
targetEntryComponents.push(...this._getEntryComponentsFromProvider(providerMeta));
} else {
compileProviders.push(this.getProviderMetadata(providerMeta));
}
} }
}); });
return compileProviders; return compileProviders;
@ -754,7 +746,7 @@ export class CompileMetadataResolver {
throw new Error(`The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'!`); throw new Error(`The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'!`);
} }
convertToCompileValue(provider.useValue, collectedIdentifiers); extractIdentifiers(provider.useValue, collectedIdentifiers);
collectedIdentifiers.forEach((identifier) => { collectedIdentifiers.forEach((identifier) => {
if (this._directiveResolver.isDirective(identifier.reference)) { if (this._directiveResolver.isDirective(identifier.reference)) {
components.push(identifier); components.push(identifier);
@ -767,24 +759,29 @@ export class CompileMetadataResolver {
let compileDeps: cpl.CompileDiDependencyMetadata[]; let compileDeps: cpl.CompileDiDependencyMetadata[];
let compileTypeMetadata: cpl.CompileTypeMetadata = null; let compileTypeMetadata: cpl.CompileTypeMetadata = null;
let compileFactoryMetadata: cpl.CompileFactoryMetadata = null; let compileFactoryMetadata: cpl.CompileFactoryMetadata = null;
let token: cpl.CompileTokenMetadata = this._getTokenMetadata(provider.token);
if (provider.useClass) { if (provider.useClass) {
compileTypeMetadata = this._getTypeMetadata(provider.useClass, provider.dependencies); compileTypeMetadata = this._getTypeMetadata(provider.useClass, provider.dependencies);
compileDeps = compileTypeMetadata.diDeps; compileDeps = compileTypeMetadata.diDeps;
if (provider.token === provider.useClass) {
// use the compileTypeMetadata as it contains information about lifecycleHooks...
token = {identifier: compileTypeMetadata};
}
} else if (provider.useFactory) { } else if (provider.useFactory) {
compileFactoryMetadata = this._getFactoryMetadata(provider.useFactory, provider.dependencies); compileFactoryMetadata = this._getFactoryMetadata(provider.useFactory, provider.dependencies);
compileDeps = compileFactoryMetadata.diDeps; compileDeps = compileFactoryMetadata.diDeps;
} }
return new cpl.CompileProviderMetadata({ return {
token: this._getTokenMetadata(provider.token), token: token,
useClass: compileTypeMetadata, useClass: compileTypeMetadata,
useValue: convertToCompileValue(provider.useValue, []), useValue: provider.useValue,
useFactory: compileFactoryMetadata, useFactory: compileFactoryMetadata,
useExisting: provider.useExisting ? this._getTokenMetadata(provider.useExisting) : null, useExisting: provider.useExisting ? this._getTokenMetadata(provider.useExisting) : null,
deps: compileDeps, deps: compileDeps,
multi: provider.multi multi: provider.multi
}); };
} }
private _getQueriesMetadata( private _getQueriesMetadata(
@ -818,12 +815,12 @@ export class CompileMetadataResolver {
selectors = [this._getTokenMetadata(q.selector)]; selectors = [this._getTokenMetadata(q.selector)];
} }
return new cpl.CompileQueryMetadata({ return {
selectors, selectors,
first: q.first, first: q.first,
descendants: q.descendants, propertyName, descendants: q.descendants, propertyName,
read: q.read ? this._getTokenMetadata(q.read) : null read: q.read ? this._getTokenMetadata(q.read) : null
}); };
} }
} }
@ -909,15 +906,12 @@ export function componentModuleUrl(
return reflector.importUri(type); return reflector.importUri(type);
} }
function convertToCompileValue( function extractIdentifiers(value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]) {
value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]): any { visitValue(value, new _CompileValueConverter(), targetIdentifiers);
return visitValue(value, new _CompileValueConverter(), targetIdentifiers);
} }
class _CompileValueConverter extends ValueTransformer { class _CompileValueConverter extends ValueTransformer {
visitOther(value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]): any { visitOther(value: any, targetIdentifiers: cpl.CompileIdentifierMetadata[]): any {
const identifier = new cpl.CompileIdentifierMetadata({reference: value}); targetIdentifiers.push({reference: value});
targetIdentifiers.push(identifier);
return identifier;
} }
} }

View File

@ -47,7 +47,7 @@ export class NgModuleCompiler {
const bootstrapComponentFactories: CompileIdentifierMetadata[] = []; const bootstrapComponentFactories: CompileIdentifierMetadata[] = [];
const entryComponentFactories = const entryComponentFactories =
ngModuleMeta.transitiveModule.entryComponents.map((entryComponent) => { ngModuleMeta.transitiveModule.entryComponents.map((entryComponent) => {
const id = new CompileIdentifierMetadata(); const id: CompileIdentifierMetadata = {reference: null};
if (ngModuleMeta.bootstrapComponents.indexOf(entryComponent) > -1) { if (ngModuleMeta.bootstrapComponents.indexOf(entryComponent) > -1) {
bootstrapComponentFactories.push(id); bootstrapComponentFactories.push(id);
} }
@ -159,7 +159,7 @@ class _InjectorBuilder implements ClassBuilder {
private _getProviderValue(provider: CompileProviderMetadata): o.Expression { private _getProviderValue(provider: CompileProviderMetadata): o.Expression {
let result: o.Expression; let result: o.Expression;
if (isPresent(provider.useExisting)) { if (isPresent(provider.useExisting)) {
result = this._getDependency(new CompileDiDependencyMetadata({token: provider.useExisting})); result = this._getDependency({token: provider.useExisting});
} else if (isPresent(provider.useFactory)) { } else if (isPresent(provider.useFactory)) {
const deps = provider.deps || provider.useFactory.diDeps; const deps = provider.deps || provider.useFactory.diDeps;
const depsExpr = deps.map((dep) => this._getDependency(dep)); const depsExpr = deps.map((dep) => this._getDependency(dep));

View File

@ -30,12 +30,10 @@ class _ValueOutputAstTransformer implements ValueTransformer {
visitPrimitive(value: any, type: o.Type): o.Expression { return o.literal(value, type); } visitPrimitive(value: any, type: o.Type): o.Expression { return o.literal(value, type); }
visitOther(value: any, type: o.Type): o.Expression { visitOther(value: any, type: o.Type): o.Expression {
if (value instanceof CompileIdentifierMetadata) { if (value instanceof o.Expression) {
return o.importExpr(value);
} else if (value instanceof o.Expression) {
return value; return value;
} else { } else {
throw new Error(`Illegal state: Don't now how to compile value ${value}`); return o.importExpr({reference: value});
} }
} }
} }

View File

@ -31,7 +31,7 @@ export class ProviderViewContext {
constructor(public component: CompileDirectiveMetadata, public sourceSpan: ParseSourceSpan) { constructor(public component: CompileDirectiveMetadata, public sourceSpan: ParseSourceSpan) {
this.viewQueries = _getViewQueries(component); this.viewQueries = _getViewQueries(component);
this.viewProviders = new Map<any, boolean>(); this.viewProviders = new Map<any, boolean>();
_normalizeProviders(component.viewProviders, sourceSpan, this.errors).forEach((provider) => { component.viewProviders.forEach((provider) => {
if (isBlank(this.viewProviders.get(tokenReference(provider.token)))) { if (isBlank(this.viewProviders.get(tokenReference(provider.token)))) {
this.viewProviders.set(tokenReference(provider.token), true); this.viewProviders.set(tokenReference(provider.token), true);
} }
@ -62,9 +62,7 @@ export class ProviderElementContext {
Array.from(this._allProviders.values()).forEach((provider) => { Array.from(this._allProviders.values()).forEach((provider) => {
this._addQueryReadsTo(provider.token, queriedTokens); this._addQueryReadsTo(provider.token, queriedTokens);
}); });
refs.forEach((refAst) => { refs.forEach((refAst) => { this._addQueryReadsTo({value: refAst.name}, queriedTokens); });
this._addQueryReadsTo(new CompileTokenMetadata({value: refAst.name}), queriedTokens);
});
if (isPresent(queriedTokens.get(resolveIdentifier(Identifiers.ViewContainerRef)))) { if (isPresent(queriedTokens.get(resolveIdentifier(Identifiers.ViewContainerRef)))) {
this._hasViewContainer = true; this._hasViewContainer = true;
} }
@ -160,8 +158,7 @@ export class ProviderElementContext {
let transformedDeps: CompileDiDependencyMetadata[]; let transformedDeps: CompileDiDependencyMetadata[];
if (isPresent(provider.useExisting)) { if (isPresent(provider.useExisting)) {
const existingDiDep = this._getDependency( const existingDiDep = this._getDependency(
resolvedProvider.providerType, resolvedProvider.providerType, {token: provider.useExisting}, eager);
new CompileDiDependencyMetadata({token: provider.useExisting}), eager);
if (isPresent(existingDiDep.token)) { if (isPresent(existingDiDep.token)) {
transformedUseExisting = existingDiDep.token; transformedUseExisting = existingDiDep.token;
} else { } else {
@ -194,8 +191,7 @@ export class ProviderElementContext {
eager: boolean = null): CompileDiDependencyMetadata { eager: boolean = null): CompileDiDependencyMetadata {
if (dep.isAttribute) { if (dep.isAttribute) {
const attrValue = this._attrs[dep.token.value]; const attrValue = this._attrs[dep.token.value];
return new CompileDiDependencyMetadata( return {isValue: true, value: attrValue == null ? null : attrValue};
{isValue: true, value: attrValue == null ? null : attrValue});
} }
if (isPresent(dep.token)) { if (isPresent(dep.token)) {
@ -235,7 +231,7 @@ export class ProviderElementContext {
} }
if (dep.isSelf) { if (dep.isSelf) {
if (!result && dep.isOptional) { if (!result && dep.isOptional) {
result = new CompileDiDependencyMetadata({isValue: true, value: null}); result = {isValue: true, value: null};
} }
} else { } else {
// check parent elements // check parent elements
@ -254,9 +250,7 @@ export class ProviderElementContext {
isPresent(this.viewContext.viewProviders.get(tokenReference(dep.token)))) { isPresent(this.viewContext.viewProviders.get(tokenReference(dep.token)))) {
result = dep; result = dep;
} else { } else {
result = dep.isOptional ? result = dep.isOptional ? result = {isValue: true, value: null} : null;
result = new CompileDiDependencyMetadata({isValue: true, value: null}) :
null;
} }
} }
} }
@ -281,16 +275,14 @@ export class NgModuleProviderAnalyzer {
this._allProviders = new Map<any, ProviderAst>(); this._allProviders = new Map<any, ProviderAst>();
const ngModuleTypes = ngModule.transitiveModule.modules.map((moduleMeta) => moduleMeta.type); const ngModuleTypes = ngModule.transitiveModule.modules.map((moduleMeta) => moduleMeta.type);
ngModuleTypes.forEach((ngModuleType: CompileTypeMetadata) => { ngModuleTypes.forEach((ngModuleType: CompileTypeMetadata) => {
const ngModuleProvider = new CompileProviderMetadata( const ngModuleProvider = {token: {identifier: ngModuleType}, useClass: ngModuleType};
{token: new CompileTokenMetadata({identifier: ngModuleType}), useClass: ngModuleType});
_resolveProviders( _resolveProviders(
[ngModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors, [ngModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors,
this._allProviders); this._allProviders);
}); });
_resolveProviders( _resolveProviders(
_normalizeProviders( ngModule.transitiveModule.providers.concat(extraProviders), ProviderAstType.PublicService,
ngModule.transitiveModule.providers.concat(extraProviders), sourceSpan, this._errors), false, sourceSpan, this._errors, this._allProviders);
ProviderAstType.PublicService, false, sourceSpan, this._errors, this._allProviders);
} }
parse(): ProviderAst[] { parse(): ProviderAst[] {
@ -325,9 +317,8 @@ export class NgModuleProviderAnalyzer {
let transformedUseExisting = provider.useExisting; let transformedUseExisting = provider.useExisting;
let transformedDeps: CompileDiDependencyMetadata[]; let transformedDeps: CompileDiDependencyMetadata[];
if (isPresent(provider.useExisting)) { if (isPresent(provider.useExisting)) {
const existingDiDep = this._getDependency( const existingDiDep =
new CompileDiDependencyMetadata({token: provider.useExisting}), eager, this._getDependency({token: provider.useExisting}, eager, resolvedProvider.sourceSpan);
resolvedProvider.sourceSpan);
if (isPresent(existingDiDep.token)) { if (isPresent(existingDiDep.token)) {
transformedUseExisting = existingDiDep.token; transformedUseExisting = existingDiDep.token;
} else { } else {
@ -372,7 +363,7 @@ export class NgModuleProviderAnalyzer {
let result: CompileDiDependencyMetadata = dep; let result: CompileDiDependencyMetadata = dep;
if (dep.isSelf && !foundLocal) { if (dep.isSelf && !foundLocal) {
if (dep.isOptional) { if (dep.isOptional) {
result = new CompileDiDependencyMetadata({isValue: true, value: null}); result = {isValue: true, value: null};
} else { } else {
this._errors.push( this._errors.push(
new ProviderError(`No provider for ${tokenName(dep.token)}`, requestorSourceSpan)); new ProviderError(`No provider for ${tokenName(dep.token)}`, requestorSourceSpan));
@ -386,7 +377,7 @@ function _transformProvider(
provider: CompileProviderMetadata, provider: CompileProviderMetadata,
{useExisting, useValue, deps}: {useExisting, useValue, deps}:
{useExisting: CompileTokenMetadata, useValue: any, deps: CompileDiDependencyMetadata[]}) { {useExisting: CompileTokenMetadata, useValue: any, deps: CompileDiDependencyMetadata[]}) {
return new CompileProviderMetadata({ return {
token: provider.token, token: provider.token,
useClass: provider.useClass, useClass: provider.useClass,
useExisting: useExisting, useExisting: useExisting,
@ -394,7 +385,7 @@ function _transformProvider(
useValue: useValue, useValue: useValue,
deps: deps, deps: deps,
multi: provider.multi multi: provider.multi
}); };
} }
function _transformProviderAst( function _transformProviderAst(
@ -405,44 +396,13 @@ function _transformProviderAst(
provider.providerType, provider.lifecycleHooks, provider.sourceSpan); provider.providerType, provider.lifecycleHooks, provider.sourceSpan);
} }
function _normalizeProviders(
providers: Array<CompileProviderMetadata|CompileTypeMetadata|any[]>,
sourceSpan: ParseSourceSpan, targetErrors: ParseError[],
targetProviders: CompileProviderMetadata[] = null): CompileProviderMetadata[] {
if (!targetProviders) {
targetProviders = [];
}
if (isPresent(providers)) {
providers.forEach((provider) => {
if (Array.isArray(provider)) {
_normalizeProviders(<any[]>provider, sourceSpan, targetErrors, targetProviders);
} else {
let normalizeProvider: CompileProviderMetadata;
if (provider instanceof CompileProviderMetadata) {
normalizeProvider = provider;
} else if (provider instanceof CompileTypeMetadata) {
normalizeProvider = new CompileProviderMetadata(
{token: new CompileTokenMetadata({identifier: provider}), useClass: provider});
} else {
targetErrors.push(new ProviderError(`Unknown provider type ${provider}`, sourceSpan));
}
if (isPresent(normalizeProvider)) {
targetProviders.push(normalizeProvider);
}
}
});
}
return targetProviders;
}
function _resolveProvidersFromDirectives( function _resolveProvidersFromDirectives(
directives: CompileDirectiveSummary[], sourceSpan: ParseSourceSpan, directives: CompileDirectiveSummary[], sourceSpan: ParseSourceSpan,
targetErrors: ParseError[]): Map<any, ProviderAst> { targetErrors: ParseError[]): Map<any, ProviderAst> {
const providersByToken = new Map<any, ProviderAst>(); const providersByToken = new Map<any, ProviderAst>();
directives.forEach((directive) => { directives.forEach((directive) => {
const dirProvider = new CompileProviderMetadata( const dirProvider:
{token: new CompileTokenMetadata({identifier: directive.type}), useClass: directive.type}); CompileProviderMetadata = {token: {identifier: directive.type}, useClass: directive.type};
_resolveProviders( _resolveProviders(
[dirProvider], [dirProvider],
directive.isComponent ? ProviderAstType.Component : ProviderAstType.Directive, true, directive.isComponent ? ProviderAstType.Component : ProviderAstType.Directive, true,
@ -454,11 +414,11 @@ function _resolveProvidersFromDirectives(
directives.filter(dir => dir.isComponent).concat(directives.filter(dir => !dir.isComponent)); directives.filter(dir => dir.isComponent).concat(directives.filter(dir => !dir.isComponent));
directivesWithComponentFirst.forEach((directive) => { directivesWithComponentFirst.forEach((directive) => {
_resolveProviders( _resolveProviders(
_normalizeProviders(directive.providers, sourceSpan, targetErrors), directive.providers, ProviderAstType.PublicService, false, sourceSpan, targetErrors,
ProviderAstType.PublicService, false, sourceSpan, targetErrors, providersByToken); providersByToken);
_resolveProviders( _resolveProviders(
_normalizeProviders(directive.viewProviders, sourceSpan, targetErrors), directive.viewProviders, ProviderAstType.PrivateService, false, sourceSpan, targetErrors,
ProviderAstType.PrivateService, false, sourceSpan, targetErrors, providersByToken); providersByToken);
}); });
return providersByToken; return providersByToken;
} }
@ -469,15 +429,15 @@ function _resolveProviders(
targetProvidersByToken: Map<any, ProviderAst>) { targetProvidersByToken: Map<any, ProviderAst>) {
providers.forEach((provider) => { providers.forEach((provider) => {
let resolvedProvider = targetProvidersByToken.get(tokenReference(provider.token)); let resolvedProvider = targetProvidersByToken.get(tokenReference(provider.token));
if (isPresent(resolvedProvider) && resolvedProvider.multiProvider !== provider.multi) { if (isPresent(resolvedProvider) && !!resolvedProvider.multiProvider !== !!provider.multi) {
targetErrors.push(new ProviderError( targetErrors.push(new ProviderError(
`Mixing multi and non multi provider is not possible for token ${tokenName(resolvedProvider.token)}`, `Mixing multi and non multi provider is not possible for token ${tokenName(resolvedProvider.token)}`,
sourceSpan)); sourceSpan));
} }
if (!resolvedProvider) { if (!resolvedProvider) {
const lifecycleHooks = const lifecycleHooks = provider.token.identifier &&
provider.token.identifier && provider.token.identifier instanceof CompileTypeMetadata ? (<CompileTypeMetadata>provider.token.identifier).lifecycleHooks ?
provider.token.identifier.lifecycleHooks : (<CompileTypeMetadata>provider.token.identifier).lifecycleHooks :
[]; [];
resolvedProvider = new ProviderAst( resolvedProvider = new ProviderAst(
provider.token, provider.multi, eager || lifecycleHooks.length > 0, [provider], provider.token, provider.multi, eager || lifecycleHooks.length > 0, [provider],

View File

@ -66,7 +66,7 @@ export class StyleCompiler {
stylesheet.styles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim))); stylesheet.styles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim)));
const dependencies: StylesCompileDependency[] = []; const dependencies: StylesCompileDependency[] = [];
for (let i = 0; i < stylesheet.styleUrls.length; i++) { for (let i = 0; i < stylesheet.styleUrls.length; i++) {
const identifier = new CompileIdentifierMetadata(); const identifier: CompileIdentifierMetadata = {reference: null};
dependencies.push(new StylesCompileDependency( dependencies.push(new StylesCompileDependency(
getStylesVarName(null), stylesheet.styleUrls[i], shim, identifier)); getStylesVarName(null), stylesheet.styleUrls[i], shim, identifier));
styleExpressions.push(new o.ExternalExpr(identifier)); styleExpressions.push(new o.ExternalExpr(identifier));

View File

@ -99,7 +99,7 @@ export class CompileElement extends CompileNode {
private _createComponentFactoryResolver() { private _createComponentFactoryResolver() {
const entryComponents = const entryComponents =
this.component.entryComponents.map((entryComponent: CompileIdentifierMetadata) => { this.component.entryComponents.map((entryComponent: CompileIdentifierMetadata) => {
const id = new CompileIdentifierMetadata(); const id: CompileIdentifierMetadata = {reference: null};
this.view.targetDependencies.push(new ComponentFactoryDependency(entryComponent, id)); this.view.targetDependencies.push(new ComponentFactoryDependency(entryComponent, id));
return id; return id;
}); });
@ -112,10 +112,10 @@ export class CompileElement extends CompileNode {
injectFromViewParentInjector( injectFromViewParentInjector(
this.view, createIdentifierToken(Identifiers.ComponentFactoryResolver), false) this.view, createIdentifierToken(Identifiers.ComponentFactoryResolver), false)
]); ]);
const provider = new CompileProviderMetadata({ const provider: CompileProviderMetadata = {
token: createIdentifierToken(Identifiers.ComponentFactoryResolver), token: createIdentifierToken(Identifiers.ComponentFactoryResolver),
useValue: createComponentFactoryResolverExpr useValue: createComponentFactoryResolverExpr
}); };
// Add ComponentFactoryResolver as first provider as it does not have deps on other providers // Add ComponentFactoryResolver as first provider as it does not have deps on other providers
// ProviderAstType.PrivateService as only the component and its view can see it, // ProviderAstType.PrivateService as only the component and its view can see it,
// but nobody else // but nobody else
@ -140,8 +140,10 @@ export class CompileElement extends CompileNode {
o.importExpr(createIdentifier(Identifiers.TemplateRef_)).instantiate([ o.importExpr(createIdentifier(Identifiers.TemplateRef_)).instantiate([
o.THIS_EXPR, o.literal(this.nodeIndex), this.renderNode o.THIS_EXPR, o.literal(this.nodeIndex), this.renderNode
]); ]);
const provider = new CompileProviderMetadata( const provider: CompileProviderMetadata = {
{token: createIdentifierToken(Identifiers.TemplateRef), useValue: createTemplateRefExpr}); token: createIdentifierToken(Identifiers.TemplateRef),
useValue: createTemplateRefExpr
};
// Add TemplateRef as first provider as it does not have deps on other providers // Add TemplateRef as first provider as it does not have deps on other providers
this._resolvedProvidersArray.unshift(new ProviderAst( this._resolvedProvidersArray.unshift(new ProviderAst(
provider.token, false, true, [provider], ProviderAstType.Builtin, [], provider.token, false, true, [provider], ProviderAstType.Builtin, [],
@ -166,9 +168,7 @@ export class CompileElement extends CompileNode {
resolvedProvider.providerType === ProviderAstType.Directive; resolvedProvider.providerType === ProviderAstType.Directive;
const providerValueExpressions = resolvedProvider.providers.map((provider) => { const providerValueExpressions = resolvedProvider.providers.map((provider) => {
if (provider.useExisting) { if (provider.useExisting) {
return this._getDependency( return this._getDependency(resolvedProvider.providerType, {token: provider.useExisting});
resolvedProvider.providerType,
new CompileDiDependencyMetadata({token: provider.useExisting}));
} else if (provider.useFactory) { } else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps; const deps = provider.deps || provider.useFactory.diDeps;
const depsExpr = const depsExpr =
@ -179,7 +179,7 @@ export class CompileElement extends CompileNode {
const depsExpr = const depsExpr =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep)); deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep));
if (isDirectiveWrapper) { if (isDirectiveWrapper) {
const directiveWrapperIdentifier = new CompileIdentifierMetadata(); const directiveWrapperIdentifier: CompileIdentifierMetadata = {reference: null};
this.view.targetDependencies.push(new DirectiveWrapperDependency( this.view.targetDependencies.push(new DirectiveWrapperDependency(
provider.useClass, DirectiveWrapperCompiler.dirWrapperClassName(provider.useClass), provider.useClass, DirectiveWrapperCompiler.dirWrapperClassName(provider.useClass),
directiveWrapperIdentifier)); directiveWrapperIdentifier));
@ -226,7 +226,7 @@ export class CompileElement extends CompileNode {
varValue = this.renderNode; varValue = this.renderNode;
} }
this.view.locals.set(varName, varValue); this.view.locals.set(varName, varValue);
const varToken = new CompileTokenMetadata({value: varName}); const varToken = {value: varName};
queriesWithReads.push( queriesWithReads.push(
...this._getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken))); ...this._getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
}); });
@ -363,8 +363,7 @@ export class CompileElement extends CompileNode {
// check parent elements // check parent elements
while (!result && !currElement.parent.isNull()) { while (!result && !currElement.parent.isNull()) {
currElement = currElement.parent; currElement = currElement.parent;
result = currElement._getLocalDependency( result = currElement._getLocalDependency(ProviderAstType.PublicService, {token: dep.token});
ProviderAstType.PublicService, new CompileDiDependencyMetadata({token: dep.token}));
} }
if (!result) { if (!result) {

View File

@ -214,7 +214,7 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
this.view.nodes.push(compileElement); this.view.nodes.push(compileElement);
let compViewExpr: o.ReadPropExpr = null; let compViewExpr: o.ReadPropExpr = null;
if (isPresent(component)) { if (isPresent(component)) {
const nestedComponentIdentifier = new CompileIdentifierMetadata(); const nestedComponentIdentifier: CompileIdentifierMetadata = {reference: null};
this.targetDependencies.push(new ViewClassDependency( this.targetDependencies.push(new ViewClassDependency(
component.type, getViewClassName(component, 0), nestedComponentIdentifier)); component.type, getViewClassName(component, 0), nestedComponentIdentifier));

View File

@ -40,7 +40,7 @@ export function main() {
}); });
const component = CompileDirectiveMetadata.create({ const component = CompileDirectiveMetadata.create({
type: new CompileTypeMetadata({reference: {name: 'myCmp', filePath: ''}}), type: {reference: {name: 'myCmp', filePath: ''}, diDeps: [], lifecycleHooks: []},
template: new CompileTemplateMetadata({animations: entries}) template: new CompileTemplateMetadata({animations: entries})
}); });

View File

@ -14,10 +14,12 @@ import {ImportResolver} from '@angular/compiler/src/output/path_util';
const someModuleUrl = 'somePackage/somePath'; const someModuleUrl = 'somePackage/somePath';
const anotherModuleUrl = 'somePackage/someOtherPath'; const anotherModuleUrl = 'somePackage/someOtherPath';
const sameModuleIdentifier = const sameModuleIdentifier: CompileIdentifierMetadata = {
new CompileIdentifierMetadata({reference: {name: 'someLocalId', filePath: someModuleUrl}}); reference: {name: 'someLocalId', filePath: someModuleUrl}
const externalModuleIdentifier = new CompileIdentifierMetadata( };
{reference: {name: 'someExternalId', filePath: anotherModuleUrl}}); const externalModuleIdentifier: CompileIdentifierMetadata = {
reference: {name: 'someExternalId', filePath: anotherModuleUrl}
};
class SimpleJsImportGenerator implements ImportResolver { class SimpleJsImportGenerator implements ImportResolver {
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string { fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {

View File

@ -14,11 +14,13 @@ import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
const someModuleUrl = 'somePackage/somePath'; const someModuleUrl = 'somePackage/somePath';
const anotherModuleUrl = 'somePackage/someOtherPath'; const anotherModuleUrl = 'somePackage/someOtherPath';
const sameModuleIdentifier = const sameModuleIdentifier: CompileIdentifierMetadata = {
new CompileIdentifierMetadata({reference: {name: 'someLocalId', filePath: someModuleUrl}}); reference: {name: 'someLocalId', filePath: someModuleUrl}
};
const externalModuleIdentifier = new CompileIdentifierMetadata( const externalModuleIdentifier: CompileIdentifierMetadata = {
{reference: {name: 'someExternalId', filePath: anotherModuleUrl}}); reference: {name: 'someExternalId', filePath: anotherModuleUrl}
};
class SimpleJsImportGenerator implements ImportResolver { class SimpleJsImportGenerator implements ImportResolver {
fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string { fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {

View File

@ -30,6 +30,11 @@ const MOCK_SCHEMA_REGISTRY = [{
['onEvent'], ['onEvent']), ['onEvent'], ['onEvent']),
}]; }];
function createTypeMeta({reference, diDeps}: {reference: any, diDeps?: any[]}):
CompileTypeMetadata {
return {reference: reference, diDeps: diDeps || [], lifecycleHooks: []};
}
export function main() { export function main() {
let ngIf: CompileDirectiveSummary; let ngIf: CompileDirectiveSummary;
let parse: ( let parse: (
@ -48,18 +53,17 @@ export function main() {
const component = CompileDirectiveMetadata.create({ const component = CompileDirectiveMetadata.create({
selector: 'root', selector: 'root',
template: someTemplate, template: someTemplate,
type: new CompileTypeMetadata({reference: {filePath: someModuleUrl, name: 'Root'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'Root'}}),
isComponent: true isComponent: true
}); });
ngIf = ngIf = CompileDirectiveMetadata
CompileDirectiveMetadata .create({
.create({ selector: '[ngIf]',
selector: '[ngIf]', template: someTemplate,
template: someTemplate, type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'NgIf'}}),
type: new CompileTypeMetadata({reference: {filePath: someModuleUrl, name: 'NgIf'}}), inputs: ['ngIf']
inputs: ['ngIf'] })
}) .toSummary();
.toSummary();
parse = parse =
(template: string, directives: CompileDirectiveSummary[], (template: string, directives: CompileDirectiveSummary[],
@ -300,8 +304,7 @@ export function main() {
inject([TemplateParser], (parser: TemplateParser) => { inject([TemplateParser], (parser: TemplateParser) => {
const component = CompileDirectiveMetadata.create({ const component = CompileDirectiveMetadata.create({
selector: 'test', selector: 'test',
type: type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'Test'}}),
new CompileTypeMetadata({reference: {filePath: someModuleUrl, name: 'Test'}}),
isComponent: true, isComponent: true,
template: new CompileTemplateMetadata({interpolation: ['{%', '%}']}) template: new CompileTemplateMetadata({interpolation: ['{%', '%}']})
}); });
@ -468,7 +471,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
.create({ .create({
selector: 'div', selector: 'div',
template: new CompileTemplateMetadata({animations: animationEntries}), template: new CompileTemplateMetadata({animations: animationEntries}),
type: new CompileTypeMetadata({ type: createTypeMeta({
reference: {filePath: someModuleUrl, name: 'DirA'}, reference: {filePath: someModuleUrl, name: 'DirA'},
}), }),
host: {'[@prop]': 'expr'} host: {'[@prop]': 'expr'}
@ -480,14 +483,14 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
}); });
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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'broken', .create({
type: new CompileTypeMetadata( selector: 'broken',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'[class.foo]': null} host: {'[class.foo]': null}
}) })
.toSummary(); .toSummary();
expect(() => { parse('<broken></broken>', [dirA]); }) expect(() => { parse('<broken></broken>', [dirA]); })
.toThrowError( .toThrowError(
@ -495,14 +498,14 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'broken', .create({
type: new CompileTypeMetadata( selector: 'broken',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'(click)': null} host: {'(click)': null}
}) })
.toSummary(); .toSummary();
expect(() => { parse('<broken></broken>', [dirA]); }) expect(() => { parse('<broken></broken>', [dirA]); })
.toThrowError( .toThrowError(
@ -566,7 +569,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
.create({ .create({
selector: 'template', selector: 'template',
outputs: ['e'], outputs: ['e'],
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}}) {reference: {filePath: someModuleUrl, name: 'DirA'}})
}) })
.toSummary(); .toSummary();
@ -605,21 +608,21 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
const dirA = CompileDirectiveMetadata const dirA = CompileDirectiveMetadata
.create({ .create({
selector: '[a]', selector: '[a]',
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}}) {reference: {filePath: someModuleUrl, name: 'DirA'}})
}) })
.toSummary(); .toSummary();
const dirB = CompileDirectiveMetadata const dirB = CompileDirectiveMetadata
.create({ .create({
selector: '[b]', selector: '[b]',
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirB'}}) {reference: {filePath: someModuleUrl, name: 'DirB'}})
}) })
.toSummary(); .toSummary();
const dirC = CompileDirectiveMetadata const dirC = CompileDirectiveMetadata
.create({ .create({
selector: '[c]', selector: '[c]',
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirC'}}) {reference: {filePath: someModuleUrl, name: 'DirC'}})
}) })
.toSummary(); .toSummary();
@ -631,20 +634,20 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a=b]', .create({
type: new CompileTypeMetadata( selector: '[a=b]',
{reference: {filePath: someModuleUrl, name: 'DirA'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
}) })
.toSummary(); .toSummary();
const dirB = CompileDirectiveMetadata const dirB =
.create({ CompileDirectiveMetadata
selector: '[b]', .create({
type: new CompileTypeMetadata( selector: '[b]',
{reference: {filePath: someModuleUrl, name: 'DirB'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirB'}})
}) })
.toSummary(); .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],
@ -653,13 +656,13 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a]', .create({
type: new CompileTypeMetadata( selector: '[a]',
{reference: {filePath: someModuleUrl, name: 'DirB'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirB'}})
}) })
.toSummary(); .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]
@ -667,14 +670,14 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
}); });
it('should parse directive host properties', () => { it('should parse directive host properties', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'[a]': 'expr'} host: {'[a]': 'expr'}
}) })
.toSummary(); .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]
@ -682,28 +685,28 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
}); });
it('should parse directive host listeners', () => { it('should parse directive host listeners', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'(a)': 'expr'} host: {'(a)': 'expr'}
}) })
.toSummary(); .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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['aProp'] inputs: ['aProp']
}) })
.toSummary(); .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']
@ -711,14 +714,14 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
}); });
it('should parse renamed directive properties', () => { it('should parse renamed directive properties', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['b:a'] inputs: ['b:a']
}) })
.toSummary(); .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']
@ -726,14 +729,14 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
}); });
it('should parse literal directive properties', () => { it('should parse literal directive properties', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['a'] inputs: ['a']
}) })
.toSummary(); .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"']
@ -741,14 +744,14 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['a'] inputs: ['a']
}) })
.toSummary(); .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],
@ -757,14 +760,14 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
}); });
it('should support optional directive properties', () => { it('should support optional directive properties', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['a'] inputs: ['a']
}) })
.toSummary(); .toSummary();
expect(humanizeTplAst(parse('<div></div>', [dirA]))).toEqual([ expect(humanizeTplAst(parse('<div></div>', [dirA]))).toEqual([
[ElementAst, 'div'], [DirectiveAst, dirA] [ElementAst, 'div'], [DirectiveAst, dirA]
]); ]);
@ -779,10 +782,9 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
let token: CompileTokenMetadata; let token: CompileTokenMetadata;
if (value.startsWith('type:')) { if (value.startsWith('type:')) {
const name = value.substring(5); const name = value.substring(5);
token = new CompileTokenMetadata( token = {identifier: createTypeMeta({reference: <any>name})};
{identifier: new CompileTypeMetadata({reference: <any>name})});
} else { } else {
token = new CompileTokenMetadata({value: value}); token = {value: value};
} }
return token; return token;
} }
@ -803,12 +805,12 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
isHost = true; isHost = true;
value = value.substring(5); value = value.substring(5);
} }
return new CompileDiDependencyMetadata({ return {
token: createToken(value), token: createToken(value),
isOptional: isOptional, isOptional: isOptional,
isSelf: isSelf, isSelf: isSelf,
isHost: isHost isHost: isHost
}); };
} }
function createProvider( function createProvider(
@ -816,12 +818,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
CompileProviderMetadata { CompileProviderMetadata {
const name = `provider${nextProviderId++}`; const name = `provider${nextProviderId++}`;
const compileToken = createToken(token); const compileToken = createToken(token);
return new CompileProviderMetadata({ return {
token: compileToken, token: compileToken,
multi: multi, multi: multi,
useClass: new CompileTypeMetadata({reference: tokenReference(compileToken)}), useClass: createTypeMeta({reference: tokenReference(compileToken)}),
deps: deps.map(createDep) deps: deps.map(createDep),
}); useExisting: undefined,
useFactory: undefined,
useValue: undefined
};
} }
function createDir( function createDir(
@ -836,7 +841,7 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
return CompileDirectiveMetadata return CompileDirectiveMetadata
.create({ .create({
selector: selector, selector: selector,
type: new CompileTypeMetadata({ type: createTypeMeta({
reference: <any>selector, reference: <any>selector,
diDeps: deps.map(createDep), diDeps: deps.map(createDep),
}), }),
@ -844,8 +849,15 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
template: new CompileTemplateMetadata({ngContentSelectors: []}), template: new CompileTemplateMetadata({ngContentSelectors: []}),
providers: providers, providers: providers,
viewProviders: viewProviders, viewProviders: viewProviders,
queries: queries.map( queries: queries.map((value) => {
(value) => new CompileQueryMetadata({selectors: [createToken(value)]})) return {
selectors: [createToken(value)],
descendants: false,
first: false,
propertyName: 'test',
read: undefined
};
})
}) })
.toSummary(); .toSummary();
} }
@ -1087,14 +1099,14 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a]', .create({
type: new CompileTypeMetadata( selector: '[a]',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
exportAs: 'dirA' exportAs: 'dirA'
}) })
.toSummary(); .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', ''],
@ -1133,16 +1145,16 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a]', .create({
isComponent: true, selector: '[a]',
type: new CompileTypeMetadata( isComponent: true,
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
exportAs: 'dirA', exportAs: 'dirA',
template: new CompileTemplateMetadata({ngContentSelectors: []}) template: new CompileTemplateMetadata({ngContentSelectors: []})
}) })
.toSummary(); .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', ''],
@ -1152,13 +1164,13 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a]', .create({
type: new CompileTypeMetadata( selector: '[a]',
{reference: {filePath: someModuleUrl, name: 'DirA'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
}) })
.toSummary(); .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]
]); ]);
@ -1201,13 +1213,13 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a]', .create({
type: new CompileTypeMetadata( selector: '[a]',
{reference: {filePath: someModuleUrl, name: 'DirA'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
}) })
.toSummary(); .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']
]); ]);
@ -1249,7 +1261,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
const dirA = CompileDirectiveMetadata const dirA = CompileDirectiveMetadata
.create({ .create({
selector: '[a=b]', selector: '[a=b]',
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}}), {reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['a'] inputs: ['a']
}) })
@ -1257,7 +1269,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
const dirB = CompileDirectiveMetadata const dirB = CompileDirectiveMetadata
.create({ .create({
selector: '[b]', selector: '[b]',
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirB'}}) {reference: {filePath: someModuleUrl, name: 'DirB'}})
}) })
.toSummary(); .toSummary();
@ -1272,7 +1284,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
const dirA = CompileDirectiveMetadata const dirA = CompileDirectiveMetadata
.create({ .create({
selector: '[a]', selector: '[a]',
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}}) {reference: {filePath: someModuleUrl, name: 'DirA'}})
}) })
.toSummary(); .toSummary();
@ -1285,7 +1297,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
const dirA = CompileDirectiveMetadata const dirA = CompileDirectiveMetadata
.create({ .create({
selector: '[a]', selector: '[a]',
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'DirA'}}) {reference: {filePath: someModuleUrl, name: 'DirA'}})
}) })
.toSummary(); .toSummary();
@ -1322,7 +1334,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
.create({ .create({
selector: selector, selector: selector,
isComponent: true, isComponent: true,
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: `SomeComp${compCounter++}`}}), {reference: {filePath: someModuleUrl, name: `SomeComp${compCounter++}`}}),
template: new CompileTemplateMetadata({ngContentSelectors: ngContentSelectors}) template: new CompileTemplateMetadata({ngContentSelectors: ngContentSelectors})
}) })
@ -1333,7 +1345,7 @@ Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>
return CompileDirectiveMetadata return CompileDirectiveMetadata
.create({ .create({
selector: selector, selector: selector,
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: `SomeDir${compCounter++}`}}) {reference: {filePath: someModuleUrl, name: `SomeDir${compCounter++}`}})
}) })
.toSummary(); .toSummary();
@ -1504,14 +1516,14 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
host: {'[invalidProp]': 'someProp'} host: {'[invalidProp]': 'someProp'}
}) })
.toSummary(); .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`);
}); });
@ -1523,36 +1535,36 @@ 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',
() => { () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['invalidProp'] inputs: ['invalidProp']
}) })
.toSummary(); .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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
isComponent: true, selector: 'div',
type: new CompileTypeMetadata( isComponent: true,
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []}) template: new CompileTemplateMetadata({ngContentSelectors: []})
}) })
.toSummary(); .toSummary();
const dirB = CompileDirectiveMetadata const dirB =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
isComponent: true, selector: 'div',
type: new CompileTypeMetadata( isComponent: true,
{reference: {filePath: someModuleUrl, name: 'DirB'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirB'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []}) template: new CompileTemplateMetadata({ngContentSelectors: []})
}) })
.toSummary(); .toSummary();
expect(() => parse('<div>', [dirB, dirA])) expect(() => parse('<div>', [dirB, dirA]))
.toThrowError( .toThrowError(
`Template parse errors:\n` + `Template parse errors:\n` +
@ -1563,15 +1575,15 @@ 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',
() => { () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a]', .create({
isComponent: true, selector: '[a]',
type: new CompileTypeMetadata( isComponent: true,
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []}) template: new CompileTemplateMetadata({ngContentSelectors: []})
}) })
.toSummary(); .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
@ -1580,15 +1592,15 @@ 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', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a]', .create({
isComponent: true, selector: '[a]',
type: new CompileTypeMetadata( isComponent: true,
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []}) template: new CompileTemplateMetadata({ngContentSelectors: []})
}) })
.toSummary(); .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`);
@ -1740,22 +1752,22 @@ Property binding a not used by any directive on an embedded template. Make sure
}); });
it('should support directive', () => { it('should support directive', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: '[a]', .create({
type: new CompileTypeMetadata( selector: '[a]',
{reference: {filePath: someModuleUrl, name: 'DirA'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
}) })
.toSummary(); .toSummary();
const comp = CompileDirectiveMetadata const comp =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
isComponent: true, selector: 'div',
type: new CompileTypeMetadata( isComponent: true,
{reference: {filePath: someModuleUrl, name: 'ZComp'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'ZComp'}}),
template: new CompileTemplateMetadata({ngContentSelectors: []}) template: new CompileTemplateMetadata({ngContentSelectors: []})
}) })
.toSummary(); .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>']
@ -1763,17 +1775,17 @@ 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', () => {
const tagSel = CompileDirectiveMetadata const tagSel =
.create({ CompileDirectiveMetadata
selector: 'circle', .create({
type: new CompileTypeMetadata( selector: 'circle',
{reference: {filePath: someModuleUrl, name: 'elDir'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'elDir'}})
}) })
.toSummary(); .toSummary();
const attrSel = CompileDirectiveMetadata const attrSel = CompileDirectiveMetadata
.create({ .create({
selector: '[href]', selector: '[href]',
type: new CompileTypeMetadata( type: createTypeMeta(
{reference: {filePath: someModuleUrl, name: 'attrDir'}}) {reference: {filePath: someModuleUrl, name: 'attrDir'}})
}) })
.toSummary(); .toSummary();
@ -1791,14 +1803,14 @@ Property binding a not used by any directive on an embedded template. Make sure
}); });
it('should support directive property', () => { it('should support directive property', () => {
const dirA = CompileDirectiveMetadata const dirA =
.create({ CompileDirectiveMetadata
selector: 'div', .create({
type: new CompileTypeMetadata( selector: 'div',
{reference: {filePath: someModuleUrl, name: 'DirA'}}), type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}}),
inputs: ['aProp'] inputs: ['aProp']
}) })
.toSummary(); .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">'],
@ -1807,13 +1819,13 @@ 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 const tagSel =
.create({ CompileDirectiveMetadata
selector: 'circle', .create({
type: new CompileTypeMetadata( selector: 'circle',
{reference: {filePath: someModuleUrl, name: 'elDir'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'elDir'}})
}) })
.toSummary(); .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();
@ -1822,20 +1834,20 @@ 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 const ulSel =
.create({ CompileDirectiveMetadata
selector: 'ul', .create({
type: new CompileTypeMetadata( selector: 'ul',
{reference: {filePath: someModuleUrl, name: 'ulDir'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'ulDir'}})
}) })
.toSummary(); .toSummary();
const liSel = CompileDirectiveMetadata const liSel =
.create({ CompileDirectiveMetadata
selector: 'li', .create({
type: new CompileTypeMetadata( selector: 'li',
{reference: {filePath: someModuleUrl, name: 'liDir'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'liDir'}})
}) })
.toSummary(); .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;
@ -1845,11 +1857,11 @@ 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', () => {
const testPipe = new CompilePipeMetadata({ const testPipe =
name: 'test', new CompilePipeMetadata({
type: new CompileTypeMetadata( name: 'test',
{reference: {filePath: someModuleUrl, name: 'DirA'}}) type: createTypeMeta({reference: {filePath: someModuleUrl, name: 'DirA'}})
}).toSummary(); }).toSummary();
expect(() => parse('{{a | test}}', [], [testPipe])).not.toThrow(); expect(() => parse('{{a | test}}', [], [testPipe])).not.toThrow();
}); });

View File

@ -57,7 +57,7 @@ function createCompileView(config: {className: string, parent?: CompileView, fie
config.fields.forEach((fieldName) => { fields.push(new o.ClassField(fieldName)); }); config.fields.forEach((fieldName) => { fields.push(new o.ClassField(fieldName)); });
} }
return <any>{ return <any>{
classType: o.importType(new CompileIdentifierMetadata()), classType: o.importType({reference: null}),
fields: fields, fields: fields,
getters: [], getters: [],
declarationElement: declarationElement declarationElement: declarationElement