feat(compiler): support sync runtime compile

Adds new abstraction `Compiler` with methods
`compileComponentAsync` and `compileComponentSync`.
This is in preparation of deprecating `ComponentResolver`.

`compileComponentSync` is able to compile components
synchronously given all components either have an inline
template or they have been compiled before.

Also changes `TestComponentBuilder.createSync` to
take a `Type` and use the new `compileComponentSync` method.

Also supports overriding the component metadata even if
the component has already been compiled.

Also fixes #7084 in a better way.

BREAKING CHANGE:
`TestComponentBuilder.createSync` now takes a component type
and throws if not all templates are either inlined
are compiled before via `createAsync`.

Closes #9594
This commit is contained in:
Tobias Bosch
2016-06-24 08:46:43 -07:00
parent 24eb8389d2
commit bf598d6b8b
35 changed files with 1093 additions and 700 deletions

View File

@ -600,6 +600,31 @@ export class CompileQueryMetadata {
}
}
/**
* Metadata about a stylesheet
*/
export class CompileStylesheetMetadata {
moduleUrl: string;
styles: string[];
styleUrls: string[];
constructor(
{moduleUrl, styles,
styleUrls}: {moduleUrl?: string, styles?: string[], styleUrls?: string[]} = {}) {
this.moduleUrl = moduleUrl;
this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls);
}
static fromJson(data: {[key: string]: any}): CompileStylesheetMetadata {
return new CompileStylesheetMetadata(
{moduleUrl: data['moduleUrl'], styles: data['styles'], styleUrls: data['styleUrls']});
}
toJson(): {[key: string]: any} {
return {'moduleUrl': this.moduleUrl, 'styles': this.styles, 'styleUrls': this.styleUrls};
}
}
/**
* Metadata regarding compilation of a template.
*/
@ -609,17 +634,19 @@ export class CompileTemplateMetadata {
templateUrl: string;
styles: string[];
styleUrls: string[];
externalStylesheets: CompileStylesheetMetadata[];
animations: CompileAnimationEntryMetadata[];
ngContentSelectors: string[];
interpolation: [string, string];
constructor(
{encapsulation, template, templateUrl, styles, styleUrls, animations, ngContentSelectors,
interpolation}: {
{encapsulation, template, templateUrl, styles, styleUrls, externalStylesheets, animations,
ngContentSelectors, interpolation}: {
encapsulation?: ViewEncapsulation,
template?: string,
templateUrl?: string,
styles?: string[],
styleUrls?: string[],
externalStylesheets?: CompileStylesheetMetadata[],
ngContentSelectors?: string[],
animations?: CompileAnimationEntryMetadata[],
interpolation?: [string, string]
@ -627,8 +654,9 @@ export class CompileTemplateMetadata {
this.encapsulation = encapsulation;
this.template = template;
this.templateUrl = templateUrl;
this.styles = isPresent(styles) ? styles : [];
this.styleUrls = isPresent(styleUrls) ? styleUrls : [];
this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls);
this.externalStylesheets = _normalizeArray(externalStylesheets);
this.animations = isPresent(animations) ? ListWrapper.flatten(animations) : [];
this.ngContentSelectors = isPresent(ngContentSelectors) ? ngContentSelectors : [];
if (isPresent(interpolation) && interpolation.length != 2) {
@ -648,6 +676,8 @@ export class CompileTemplateMetadata {
templateUrl: data['templateUrl'],
styles: data['styles'],
styleUrls: data['styleUrls'],
externalStylesheets:
_arrayFromJson(data['externalStylesheets'], CompileStylesheetMetadata.fromJson),
animations: animations,
ngContentSelectors: data['ngContentSelectors'],
interpolation: data['interpolation']
@ -662,6 +692,7 @@ export class CompileTemplateMetadata {
'templateUrl': this.templateUrl,
'styles': this.styles,
'styleUrls': this.styleUrls,
'externalStylesheets': _objToJson(this.externalStylesheets),
'animations': _objToJson(this.animations),
'ngContentSelectors': this.ngContentSelectors,
'interpolation': this.interpolation

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ComponentResolver, Type} from '@angular/core';
import {Compiler, ComponentResolver, Type} from '@angular/core';
export * from './template_ast';
export {TEMPLATE_TRANSFORMS} from './template_parser';
@ -49,6 +49,7 @@ export const COMPILER_PROVIDERS: Array<any|Type|{[k: string]: any}|any[]> =
/*@ts2dart_Provider*/ {provide: CompilerConfig, useValue: new CompilerConfig()},
RuntimeCompiler,
/*@ts2dart_Provider*/ {provide: ComponentResolver, useExisting: RuntimeCompiler},
/*@ts2dart_Provider*/ {provide: Compiler, useExisting: RuntimeCompiler},
DomElementSchemaRegistry,
/*@ts2dart_Provider*/ {provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
UrlResolver, ViewResolver, DirectiveResolver, PipeResolver

View File

@ -12,65 +12,92 @@ import {PromiseWrapper} from '../src/facade/async';
import {BaseException} from '../src/facade/exceptions';
import {isBlank, isPresent} from '../src/facade/lang';
import {CompileTypeMetadata, CompileDirectiveMetadata, CompileTemplateMetadata,} from './compile_metadata';
import {XHR} from './xhr';
import {UrlResolver} from './url_resolver';
import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver';
import {HtmlAstVisitor, HtmlElementAst, HtmlTextAst, HtmlAttrAst, HtmlCommentAst, HtmlExpansionAst, HtmlExpansionCaseAst, htmlVisitAll} from './html_ast';
import {HtmlParser} from './html_parser';
import {CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from './compile_metadata';
import {CompilerConfig} from './config';
import {HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from './html_ast';
import {HtmlParser} from './html_parser';
import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver';
import {PreparsedElementType, preparseElement} from './template_preparser';
import {UrlResolver} from './url_resolver';
import {XHR} from './xhr';
import {preparseElement, PreparsedElementType} from './template_preparser';
export class NormalizeDirectiveResult {
constructor(
public syncResult: CompileDirectiveMetadata,
public asyncResult: Promise<CompileDirectiveMetadata>) {}
}
@Injectable()
export class DirectiveNormalizer {
private _xhrCache = new Map<string, Promise<string>>();
constructor(
private _xhr: XHR, private _urlResolver: UrlResolver, private _htmlParser: HtmlParser,
private _config: CompilerConfig) {}
normalizeDirective(directive: CompileDirectiveMetadata): Promise<CompileDirectiveMetadata> {
if (!directive.isComponent) {
// For non components there is nothing to be normalized yet.
return PromiseWrapper.resolve(directive);
clearCache() { this._xhrCache.clear(); }
clearCacheFor(normalizedDirective: CompileDirectiveMetadata) {
if (!normalizedDirective.isComponent) {
return;
}
return this.normalizeTemplate(directive.type, directive.template)
.then((normalizedTemplate: CompileTemplateMetadata) => new CompileDirectiveMetadata({
type: directive.type,
isComponent: directive.isComponent,
selector: directive.selector,
exportAs: directive.exportAs,
changeDetection: directive.changeDetection,
inputs: directive.inputs,
outputs: directive.outputs,
hostListeners: directive.hostListeners,
hostProperties: directive.hostProperties,
hostAttributes: directive.hostAttributes,
lifecycleHooks: directive.lifecycleHooks,
providers: directive.providers,
viewProviders: directive.viewProviders,
queries: directive.queries,
viewQueries: directive.viewQueries,
precompile: directive.precompile,
template: normalizedTemplate
}));
this._xhrCache.delete(normalizedDirective.template.templateUrl);
normalizedDirective.template.externalStylesheets.forEach(
(stylesheet) => { this._xhrCache.delete(stylesheet.moduleUrl); });
}
normalizeTemplate(directiveType: CompileTypeMetadata, template: CompileTemplateMetadata):
Promise<CompileTemplateMetadata> {
if (isPresent(template.template)) {
return PromiseWrapper.resolve(this.normalizeLoadedTemplate(
directiveType, template, template.template, directiveType.moduleUrl));
} else if (isPresent(template.templateUrl)) {
var sourceAbsUrl = this._urlResolver.resolve(directiveType.moduleUrl, template.templateUrl);
return this._xhr.get(sourceAbsUrl)
.then(
templateContent => this.normalizeLoadedTemplate(
directiveType, template, templateContent, sourceAbsUrl));
} else {
throw new BaseException(`No template specified for component ${directiveType.name}`);
private _fetch(url: string): Promise<string> {
var result = this._xhrCache.get(url);
if (!result) {
result = this._xhr.get(url);
this._xhrCache.set(url, result);
}
return result;
}
normalizeDirective(directive: CompileDirectiveMetadata): NormalizeDirectiveResult {
if (!directive.isComponent) {
// For non components there is nothing to be normalized yet.
return new NormalizeDirectiveResult(directive, Promise.resolve(directive));
}
let normalizedTemplateSync: CompileTemplateMetadata = null;
let normalizedTemplateAsync: Promise<CompileTemplateMetadata>;
if (isPresent(directive.template.template)) {
normalizedTemplateSync = this.normalizeTemplateSync(directive.type, directive.template);
normalizedTemplateAsync = Promise.resolve(normalizedTemplateSync);
} else if (directive.template.templateUrl) {
normalizedTemplateAsync = this.normalizeTemplateAsync(directive.type, directive.template);
} else {
throw new BaseException(`No template specified for component ${directive.type.name}`);
}
if (normalizedTemplateSync && normalizedTemplateSync.styleUrls.length === 0) {
// sync case
let normalizedDirective = _cloneDirectiveWithTemplate(directive, normalizedTemplateSync);
return new NormalizeDirectiveResult(
normalizedDirective, Promise.resolve(normalizedDirective));
} else {
// async case
return new NormalizeDirectiveResult(
null,
normalizedTemplateAsync
.then((normalizedTemplate) => this.normalizeExternalStylesheets(normalizedTemplate))
.then(
(normalizedTemplate) =>
_cloneDirectiveWithTemplate(directive, normalizedTemplate)));
}
}
normalizeTemplateSync(directiveType: CompileTypeMetadata, template: CompileTemplateMetadata):
CompileTemplateMetadata {
return this.normalizeLoadedTemplate(
directiveType, template, template.template, directiveType.moduleUrl);
}
normalizeTemplateAsync(directiveType: CompileTypeMetadata, template: CompileTemplateMetadata):
Promise<CompileTemplateMetadata> {
let templateUrl = this._urlResolver.resolve(directiveType.moduleUrl, template.templateUrl);
return this._fetch(templateUrl)
.then((value) => this.normalizeLoadedTemplate(directiveType, template, value, templateUrl));
}
normalizeLoadedTemplate(
@ -81,42 +108,87 @@ export class DirectiveNormalizer {
var errorString = rootNodesAndErrors.errors.join('\n');
throw new BaseException(`Template parse errors:\n${errorString}`);
}
var templateMetadataStyles = this.normalizeStylesheet(new CompileStylesheetMetadata({
styles: templateMeta.styles,
styleUrls: templateMeta.styleUrls,
moduleUrl: directiveType.moduleUrl
}));
var visitor = new TemplatePreparseVisitor();
htmlVisitAll(visitor, rootNodesAndErrors.rootNodes);
var allStyles = templateMeta.styles.concat(visitor.styles);
var templateStyles = this.normalizeStylesheet(new CompileStylesheetMetadata(
{styles: visitor.styles, styleUrls: visitor.styleUrls, moduleUrl: templateAbsUrl}));
var allStyleAbsUrls =
visitor.styleUrls.filter(isStyleUrlResolvable)
.map(url => this._urlResolver.resolve(templateAbsUrl, url))
.concat(templateMeta.styleUrls.filter(isStyleUrlResolvable)
.map(url => this._urlResolver.resolve(directiveType.moduleUrl, url)));
var allResolvedStyles = allStyles.map(style => {
var styleWithImports = extractStyleUrls(this._urlResolver, templateAbsUrl, style);
styleWithImports.styleUrls.forEach(styleUrl => allStyleAbsUrls.push(styleUrl));
return styleWithImports.style;
});
var allStyles = templateMetadataStyles.styles.concat(templateStyles.styles);
var allStyleUrls = templateMetadataStyles.styleUrls.concat(templateStyles.styleUrls);
var encapsulation = templateMeta.encapsulation;
if (isBlank(encapsulation)) {
encapsulation = this._config.defaultEncapsulation;
}
if (encapsulation === ViewEncapsulation.Emulated && allResolvedStyles.length === 0 &&
allStyleAbsUrls.length === 0) {
if (encapsulation === ViewEncapsulation.Emulated && allStyles.length === 0 &&
allStyleUrls.length === 0) {
encapsulation = ViewEncapsulation.None;
}
return new CompileTemplateMetadata({
encapsulation: encapsulation,
template: template,
templateUrl: templateAbsUrl,
styles: allResolvedStyles,
styleUrls: allStyleAbsUrls,
styles: allStyles,
styleUrls: allStyleUrls,
externalStylesheets: templateMeta.externalStylesheets,
ngContentSelectors: visitor.ngContentSelectors,
animations: templateMeta.animations,
interpolation: templateMeta.interpolation
});
}
normalizeExternalStylesheets(templateMeta: CompileTemplateMetadata):
Promise<CompileTemplateMetadata> {
return this._loadMissingExternalStylesheets(templateMeta.styleUrls)
.then((externalStylesheets) => new CompileTemplateMetadata({
encapsulation: templateMeta.encapsulation,
template: templateMeta.template,
templateUrl: templateMeta.templateUrl,
styles: templateMeta.styles,
styleUrls: templateMeta.styleUrls,
externalStylesheets: externalStylesheets,
ngContentSelectors: templateMeta.ngContentSelectors,
animations: templateMeta.animations,
interpolation: templateMeta.interpolation
}));
}
private _loadMissingExternalStylesheets(
styleUrls: string[],
loadedStylesheets:
Map<string, CompileStylesheetMetadata> = new Map<string, CompileStylesheetMetadata>()):
Promise<CompileStylesheetMetadata[]> {
return Promise
.all(styleUrls.filter((styleUrl) => !loadedStylesheets.has(styleUrl))
.map(styleUrl => this._fetch(styleUrl).then((loadedStyle) => {
var stylesheet = this.normalizeStylesheet(
new CompileStylesheetMetadata({styles: [loadedStyle], moduleUrl: styleUrl}));
loadedStylesheets.set(styleUrl, stylesheet);
return this._loadMissingExternalStylesheets(
stylesheet.styleUrls, loadedStylesheets);
})))
.then((_) => Array.from(loadedStylesheets.values()));
}
normalizeStylesheet(stylesheet: CompileStylesheetMetadata): CompileStylesheetMetadata {
var allStyleUrls = stylesheet.styleUrls.filter(isStyleUrlResolvable)
.map(url => this._urlResolver.resolve(stylesheet.moduleUrl, url));
var allStyles = stylesheet.styles.map(style => {
var styleWithImports = extractStyleUrls(this._urlResolver, stylesheet.moduleUrl, style);
allStyleUrls.push(...styleWithImports.styleUrls);
return styleWithImports.style;
});
return new CompileStylesheetMetadata(
{styles: allStyles, styleUrls: allStyleUrls, moduleUrl: stylesheet.moduleUrl});
}
}
class TemplatePreparseVisitor implements HtmlAstVisitor {
@ -166,3 +238,27 @@ class TemplatePreparseVisitor implements HtmlAstVisitor {
visitExpansionCase(ast: HtmlExpansionCaseAst, context: any): any { return null; }
}
function _cloneDirectiveWithTemplate(
directive: CompileDirectiveMetadata,
template: CompileTemplateMetadata): CompileDirectiveMetadata {
return new CompileDirectiveMetadata({
type: directive.type,
isComponent: directive.isComponent,
selector: directive.selector,
exportAs: directive.exportAs,
changeDetection: directive.changeDetection,
inputs: directive.inputs,
outputs: directive.outputs,
hostListeners: directive.hostListeners,
hostProperties: directive.hostProperties,
hostAttributes: directive.hostAttributes,
lifecycleHooks: directive.lifecycleHooks,
providers: directive.providers,
viewProviders: directive.viewProviders,
queries: directive.queries,
viewQueries: directive.viewQueries,
precompile: directive.precompile,
template: template
});
}

View File

@ -49,6 +49,16 @@ export class CompileMetadataResolver {
return sanitizeIdentifier(identifier);
}
clearCacheFor(compType: Type) {
this._directiveCache.delete(compType);
this._pipeCache.delete(compType);
}
clearCache() {
this._directiveCache.clear();
this._pipeCache.clear();
}
getAnimationEntryMetadata(entry: AnimationEntryMetadata): cpl.CompileAnimationEntryMetadata {
var defs = entry.definitions.map(def => this.getAnimationStateMetadata(def));
return new cpl.CompileAnimationEntryMetadata(entry.name, defs);
@ -101,7 +111,6 @@ export class CompileMetadataResolver {
var moduleUrl = staticTypeModuleUrl(directiveType);
var precompileTypes: cpl.CompileTypeMetadata[] = [];
if (dirMeta instanceof ComponentMetadata) {
assertArrayOfStrings('styles', dirMeta.styles);
var cmpMeta = <ComponentMetadata>dirMeta;
var viewMeta = this._viewResolver.resolve(directiveType);
assertArrayOfStrings('styles', viewMeta.styles);
@ -109,6 +118,8 @@ export class CompileMetadataResolver {
var animations = isPresent(viewMeta.animations) ?
viewMeta.animations.map(e => this.getAnimationEntryMetadata(e)) :
null;
assertArrayOfStrings('styles', viewMeta.styles);
assertArrayOfStrings('styleUrls', viewMeta.styleUrls);
templateMeta = new cpl.CompileTemplateMetadata({
encapsulation: viewMeta.encapsulation,

View File

@ -14,7 +14,7 @@ import {ListWrapper} from './facade/collection';
import {BaseException} from './facade/exceptions';
import {OutputEmitter} from './output/abstract_emitter';
import * as o from './output/output_ast';
import {StyleCompiler, StylesCompileResult} from './style_compiler';
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
import {TemplateParser} from './template_parser';
import {assetUrl} from './util';
import {ComponentFactoryDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
@ -44,29 +44,38 @@ export class OfflineCompiler {
constructor(
private _directiveNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
private _outputEmitter: OutputEmitter, private _xhr: XHR) {}
private _outputEmitter: OutputEmitter) {}
normalizeDirectiveMetadata(directive: CompileDirectiveMetadata):
Promise<CompileDirectiveMetadata> {
return this._directiveNormalizer.normalizeDirective(directive);
return this._directiveNormalizer.normalizeDirective(directive).asyncResult;
}
compileTemplates(components: NormalizedComponentWithViewDirectives[]): SourceModule {
compileTemplates(components: NormalizedComponentWithViewDirectives[]): SourceModule[] {
if (components.length === 0) {
throw new BaseException('No components given');
}
var statements: o.DeclareVarStmt[] = [];
var exportedVars: string[] = [];
var moduleUrl = _ngfactoryModuleUrl(components[0].component.type);
var outputSourceModules: SourceModule[] = [];
components.forEach(componentWithDirs => {
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
_assertComponent(compMeta);
var fileSuffix = _splitLastSuffix(compMeta.type.moduleUrl)[1];
var stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
stylesCompileResults.externalStylesheets.forEach((compiledStyleSheet) => {
outputSourceModules.push(this._codgenStyles(compiledStyleSheet, fileSuffix));
});
var compViewFactoryVar = this._compileComponent(
compMeta, componentWithDirs.directives, componentWithDirs.pipes, statements);
compMeta, componentWithDirs.directives, componentWithDirs.pipes,
stylesCompileResults.componentStylesheet, fileSuffix, statements);
exportedVars.push(compViewFactoryVar);
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
var hostViewFactoryVar = this._compileComponent(hostMeta, [compMeta], [], statements);
var hostViewFactoryVar =
this._compileComponent(hostMeta, [compMeta], [], null, fileSuffix, statements);
var compFactoryVar = _componentFactoryName(compMeta.type);
statements.push(
o.variable(compFactoryVar)
@ -82,43 +91,32 @@ export class OfflineCompiler {
.toDeclStmt(null, [o.StmtModifier.Final]));
exportedVars.push(compFactoryVar);
});
return this._codegenSourceModule(moduleUrl, statements, exportedVars);
}
loadAndCompileStylesheet(stylesheetUrl: string, shim: boolean, suffix: string):
Promise<StyleSheetSourceWithImports> {
return this._xhr.get(stylesheetUrl).then((cssText) => {
var compileResult = this._styleCompiler.compileStylesheet(stylesheetUrl, cssText, shim);
var importedUrls: string[] = [];
compileResult.dependencies.forEach((dep) => {
importedUrls.push(dep.moduleUrl);
dep.valuePlaceholder.moduleUrl = _stylesModuleUrl(dep.moduleUrl, dep.isShimmed, suffix);
});
return new StyleSheetSourceWithImports(
this._codgenStyles(stylesheetUrl, shim, suffix, compileResult), importedUrls);
});
outputSourceModules.unshift(this._codegenSourceModule(moduleUrl, statements, exportedVars));
return outputSourceModules;
}
private _compileComponent(
compMeta: CompileDirectiveMetadata, directives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[], targetStatements: o.Statement[]): string {
var styleResult = this._styleCompiler.compileComponent(compMeta);
pipes: CompilePipeMetadata[], componentStyles: CompiledStylesheet, fileSuffix: string,
targetStatements: o.Statement[]): string {
var parsedTemplate = this._templateParser.parse(
compMeta, compMeta.template.template, directives, pipes, compMeta.type.name);
var viewResult = this._viewCompiler.compileComponent(
compMeta, parsedTemplate, o.variable(styleResult.stylesVar), pipes);
ListWrapper.addAll(
targetStatements, _resolveStyleStatements(compMeta.type.moduleUrl, styleResult));
var stylesExpr = componentStyles ? o.variable(componentStyles.stylesVar) : o.literalArr([]);
var viewResult =
this._viewCompiler.compileComponent(compMeta, parsedTemplate, stylesExpr, pipes);
if (componentStyles) {
ListWrapper.addAll(targetStatements, _resolveStyleStatements(componentStyles, fileSuffix));
}
ListWrapper.addAll(targetStatements, _resolveViewStatements(viewResult));
return viewResult.viewFactoryVar;
}
private _codgenStyles(
inputUrl: string, shim: boolean, suffix: string,
stylesCompileResult: StylesCompileResult): SourceModule {
private _codgenStyles(stylesCompileResult: CompiledStylesheet, fileSuffix: string): SourceModule {
_resolveStyleStatements(stylesCompileResult, fileSuffix);
return this._codegenSourceModule(
_stylesModuleUrl(inputUrl, shim, suffix), stylesCompileResult.statements,
[stylesCompileResult.stylesVar]);
_stylesModuleUrl(
stylesCompileResult.meta.moduleUrl, stylesCompileResult.isShimmed, fileSuffix),
stylesCompileResult.statements, [stylesCompileResult.stylesVar]);
}
private _codegenSourceModule(
@ -131,7 +129,7 @@ export class OfflineCompiler {
function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[] {
compileResult.dependencies.forEach((dep) => {
if (dep instanceof ViewFactoryDependency) {
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp.type);
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp);
} else if (dep instanceof ComponentFactoryDependency) {
dep.placeholder.name = _componentFactoryName(dep.comp);
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp);
@ -142,17 +140,15 @@ function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[]
function _resolveStyleStatements(
containingModuleUrl: string, compileResult: StylesCompileResult): o.Statement[] {
var containingSuffix = _splitSuffix(containingModuleUrl)[1];
compileResult: CompiledStylesheet, fileSuffix: string): o.Statement[] {
compileResult.dependencies.forEach((dep) => {
dep.valuePlaceholder.moduleUrl =
_stylesModuleUrl(dep.moduleUrl, dep.isShimmed, containingSuffix);
dep.valuePlaceholder.moduleUrl = _stylesModuleUrl(dep.moduleUrl, dep.isShimmed, fileSuffix);
});
return compileResult.statements;
}
function _ngfactoryModuleUrl(comp: CompileIdentifierMetadata): string {
var urlWithSuffix = _splitSuffix(comp.moduleUrl);
var urlWithSuffix = _splitLastSuffix(comp.moduleUrl);
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
}
@ -170,7 +166,7 @@ function _assertComponent(meta: CompileDirectiveMetadata) {
}
}
function _splitSuffix(path: string): string[] {
function _splitLastSuffix(path: string): string[] {
let lastDot = path.lastIndexOf('.');
if (lastDot !== -1) {
return [path.substring(0, lastDot), path.substring(lastDot)];

View File

@ -6,26 +6,25 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ComponentFactory, ComponentResolver, Injectable} from '@angular/core';
import {Compiler, ComponentFactory, ComponentResolver, Injectable} from '@angular/core';
import {BaseException} from '../src/facade/exceptions';
import {IS_DART, Type, isBlank, isString} from '../src/facade/lang';
import {ConcreteType, IS_DART, Type, isBlank, isString, stringify} from '../src/facade/lang';
import {ListWrapper,} from '../src/facade/collection';
import {PromiseWrapper} from '../src/facade/async';
import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata, CompileIdentifierMetadata} from './compile_metadata';
import {TemplateAst,} from './template_ast';
import {StyleCompiler, StylesCompileDependency, StylesCompileResult} from './style_compiler';
import {ViewCompiler, ViewFactoryDependency, ComponentFactoryDependency} from './view_compiler/view_compiler';
import {StyleCompiler, StylesCompileDependency, CompiledStylesheet} from './style_compiler';
import {ViewCompiler, ViewCompileResult, ViewFactoryDependency, ComponentFactoryDependency} from './view_compiler/view_compiler';
import {TemplateParser} from './template_parser';
import {DirectiveNormalizer} from './directive_normalizer';
import {DirectiveNormalizer, NormalizeDirectiveResult} from './directive_normalizer';
import {CompileMetadataResolver} from './metadata_resolver';
import {CompilerConfig} from './config';
import * as ir from './output/output_ast';
import {jitStatements} from './output/output_jit';
import {interpretStatements} from './output/output_interpreter';
import {InterpretiveAppViewInstanceFactory} from './output/interpretive_view';
import {XHR} from './xhr';
/**
* An internal module of the Angular compiler that begins with component types,
@ -33,15 +32,14 @@ import {XHR} from './xhr';
* ready for linking into an application.
*/
@Injectable()
export class RuntimeCompiler implements ComponentResolver {
private _styleCache: Map<string, Promise<string>> = new Map<string, Promise<string>>();
private _hostCacheKeys = new Map<Type, any>();
export class RuntimeCompiler implements ComponentResolver, Compiler {
private _compiledTemplateCache = new Map<any, CompiledTemplate>();
private _compiledHostTemplateCache = new Map<any, CompiledTemplate>();
constructor(
private _metadataResolver: CompileMetadataResolver,
private _templateNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler, private _xhr: XHR,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
private _genConfig: CompilerConfig) {}
resolveComponent(component: Type|string): Promise<ComponentFactory<any>> {
@ -49,175 +47,215 @@ export class RuntimeCompiler implements ComponentResolver {
return PromiseWrapper.reject(
new BaseException(`Cannot resolve component using '${component}'.`), null);
}
return this._loadAndCompileHostComponent(<Type>component).done;
return this.compileComponentAsync(<ConcreteType<any>>component);
}
compileComponentAsync<T>(compType: ConcreteType<T>): Promise<ComponentFactory<T>> {
var templates = this._getTransitiveCompiledTemplates(compType, true);
var loadingPromises: Promise<any>[] = [];
templates.forEach((template) => {
if (template.loading) {
loadingPromises.push(template.loading);
}
});
return Promise.all(loadingPromises).then(() => {
templates.forEach((template) => { this._compileTemplate(template); });
return this._getCompiledHostTemplate(compType).proxyComponentFactory;
});
}
compileComponentSync<T>(compType: ConcreteType<T>): ComponentFactory<T> {
var templates = this._getTransitiveCompiledTemplates(compType, true);
templates.forEach((template) => {
if (template.loading) {
throw new BaseException(
`Can't compile synchronously as ${template.compType.name} is still being loaded!`);
}
});
templates.forEach((template) => { this._compileTemplate(template); });
return this._getCompiledHostTemplate(compType).proxyComponentFactory;
}
clearCacheFor(compType: Type) {
this._metadataResolver.clearCacheFor(compType);
this._compiledHostTemplateCache.delete(compType);
var compiledTemplate = this._compiledTemplateCache.get(compType);
if (compiledTemplate) {
this._templateNormalizer.clearCacheFor(compiledTemplate.normalizedCompMeta);
this._compiledTemplateCache.delete(compType);
}
}
clearCache(): void {
this._styleCache.clear();
this._metadataResolver.clearCache();
this._compiledTemplateCache.clear();
this._hostCacheKeys.clear();
this._compiledHostTemplateCache.clear();
this._templateNormalizer.clearCache();
}
private _loadAndCompileHostComponent(componentType: Type): CompileHostTemplate {
var compMeta: CompileDirectiveMetadata =
this._metadataResolver.getDirectiveMetadata(componentType);
var hostCacheKey = this._hostCacheKeys.get(compMeta.type.runtime);
if (isBlank(hostCacheKey)) {
hostCacheKey = new Object();
this._hostCacheKeys.set(compMeta.type.runtime, hostCacheKey);
assertComponent(compMeta);
var hostMeta: CompileDirectiveMetadata =
createHostComponentMeta(compMeta.type, compMeta.selector);
this._loadAndCompileComponent(hostCacheKey, hostMeta, [compMeta], [], []);
}
var compTemplate = this._compiledTemplateCache.get(hostCacheKey);
return new CompileHostTemplate(compTemplate, compMeta);
}
private _loadAndCompileComponent(
cacheKey: any, compMeta: CompileDirectiveMetadata, viewDirectives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[], compilingComponentsPath: any[]): CompiledTemplate {
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
private _getCompiledHostTemplate(type: Type): CompiledTemplate {
var compiledTemplate = this._compiledHostTemplateCache.get(type);
if (isBlank(compiledTemplate)) {
let done =
PromiseWrapper
.all([<any>this._compileComponentStyles(compMeta)].concat(viewDirectives.map(
dirMeta => this._templateNormalizer.normalizeDirective(dirMeta))))
.then((stylesAndNormalizedViewDirMetas: any[]) => {
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
var styles = stylesAndNormalizedViewDirMetas[0];
var parsedTemplate = this._templateParser.parse(
compMeta, compMeta.template.template, normalizedViewDirMetas, pipes,
compMeta.type.name);
var childPromises: Promise<any>[] = [];
compiledTemplate.init(this._compileComponent(
compMeta, parsedTemplate, styles, pipes, compilingComponentsPath,
childPromises));
return PromiseWrapper.all(childPromises).then((_) => { return compiledTemplate; });
});
compiledTemplate = new CompiledTemplate(done);
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
var compMeta = this._metadataResolver.getDirectiveMetadata(type);
assertComponent(compMeta);
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
compiledTemplate = new CompiledTemplate(
true, compMeta.selector, compMeta.type, [], [type], [], [],
this._templateNormalizer.normalizeDirective(hostMeta));
this._compiledHostTemplateCache.set(type, compiledTemplate);
}
return compiledTemplate;
}
private _compileComponent(
compMeta: CompileDirectiveMetadata, parsedTemplate: TemplateAst[], styles: string[],
pipes: CompilePipeMetadata[], compilingComponentsPath: any[],
childPromises: Promise<any>[]): Function {
var compileResult = this._viewCompiler.compileComponent(
compMeta, parsedTemplate,
new ir.ExternalExpr(new CompileIdentifierMetadata({runtime: styles})), pipes);
compileResult.dependencies.forEach((dep) => {
if (dep instanceof ViewFactoryDependency) {
let childCompilingComponentsPath = ListWrapper.clone(compilingComponentsPath);
let childCacheKey = dep.comp.type.runtime;
let childViewDirectives: CompileDirectiveMetadata[] =
this._metadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
let childViewPipes: CompilePipeMetadata[] =
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
let childIsRecursive = childCompilingComponentsPath.indexOf(childCacheKey) > -1;
childCompilingComponentsPath.push(childCacheKey);
let childComp = this._loadAndCompileComponent(
dep.comp.type.runtime, dep.comp, childViewDirectives, childViewPipes,
childCompilingComponentsPath);
dep.placeholder.runtime = childComp.proxyViewFactory;
dep.placeholder.name = `viewFactory_${dep.comp.type.name}`;
if (!childIsRecursive) {
// Only wait for a child if it is not a cycle
childPromises.push(childComp.done);
private _getCompiledTemplate(type: Type): CompiledTemplate {
var compiledTemplate = this._compiledTemplateCache.get(type);
if (isBlank(compiledTemplate)) {
var compMeta = this._metadataResolver.getDirectiveMetadata(type);
assertComponent(compMeta);
var viewDirectives: CompileDirectiveMetadata[] = [];
var viewComponentTypes: Type[] = [];
this._metadataResolver.getViewDirectivesMetadata(type).forEach(dirOrComp => {
if (dirOrComp.isComponent) {
viewComponentTypes.push(dirOrComp.type.runtime);
} else {
viewDirectives.push(dirOrComp);
}
});
var precompileComponentTypes = compMeta.precompile.map((typeMeta) => typeMeta.runtime);
var pipes = this._metadataResolver.getViewPipesMetadata(type);
compiledTemplate = new CompiledTemplate(
false, compMeta.selector, compMeta.type, viewDirectives, viewComponentTypes,
precompileComponentTypes, pipes, this._templateNormalizer.normalizeDirective(compMeta));
this._compiledTemplateCache.set(type, compiledTemplate);
}
return compiledTemplate;
}
private _getTransitiveCompiledTemplates(
compType: Type, isHost: boolean,
target: Set<CompiledTemplate> = new Set<CompiledTemplate>()): Set<CompiledTemplate> {
var template =
isHost ? this._getCompiledHostTemplate(compType) : this._getCompiledTemplate(compType);
if (!target.has(template)) {
target.add(template);
template.viewComponentTypes.forEach(
(compType) => { this._getTransitiveCompiledTemplates(compType, false, target); });
template.precompileHostComponentTypes.forEach(
(compType) => { this._getTransitiveCompiledTemplates(compType, true, target); });
}
return target;
}
private _compileTemplate(template: CompiledTemplate) {
if (template.isCompiled) {
return;
}
var compMeta = template.normalizedCompMeta;
var externalStylesheetsByModuleUrl = new Map<string, CompiledStylesheet>();
var stylesCompileResult = this._styleCompiler.compileComponent(compMeta);
stylesCompileResult.externalStylesheets.forEach(
(r) => { externalStylesheetsByModuleUrl.set(r.meta.moduleUrl, r); });
this._resolveStylesCompileResult(
stylesCompileResult.componentStylesheet, externalStylesheetsByModuleUrl);
var viewCompMetas = template.viewComponentTypes.map(
(compType) => this._getCompiledTemplate(compType).normalizedCompMeta);
var parsedTemplate = this._templateParser.parse(
compMeta, compMeta.template.template, template.viewDirectives.concat(viewCompMetas),
template.viewPipes, compMeta.type.name);
var compileResult = this._viewCompiler.compileComponent(
compMeta, parsedTemplate, ir.variable(stylesCompileResult.componentStylesheet.stylesVar),
template.viewPipes);
var depTemplates = compileResult.dependencies.map((dep) => {
let depTemplate: CompiledTemplate;
if (dep instanceof ViewFactoryDependency) {
depTemplate = this._getCompiledTemplate(dep.comp.runtime);
dep.placeholder.runtime = depTemplate.proxyViewFactory;
dep.placeholder.name = `viewFactory_${dep.comp.name}`;
} else if (dep instanceof ComponentFactoryDependency) {
let childComp = this._loadAndCompileHostComponent(dep.comp.runtime);
dep.placeholder.runtime = childComp.componentFactory;
depTemplate = this._getCompiledHostTemplate(dep.comp.runtime);
dep.placeholder.runtime = depTemplate.proxyComponentFactory;
dep.placeholder.name = `compFactory_${dep.comp.name}`;
childPromises.push(childComp.done);
}
return depTemplate;
});
var statements =
stylesCompileResult.componentStylesheet.statements.concat(compileResult.statements);
var factory: any;
if (IS_DART || !this._genConfig.useJit) {
factory = interpretStatements(
compileResult.statements, compileResult.viewFactoryVar,
new InterpretiveAppViewInstanceFactory());
statements, compileResult.viewFactoryVar, new InterpretiveAppViewInstanceFactory());
} else {
factory = jitStatements(
`${compMeta.type.name}.template.js`, compileResult.statements,
compileResult.viewFactoryVar);
`${template.compType.name}.template.js`, statements, compileResult.viewFactoryVar);
}
return factory;
template.compiled(factory);
}
private _compileComponentStyles(compMeta: CompileDirectiveMetadata): Promise<string[]> {
var compileResult = this._styleCompiler.compileComponent(compMeta);
return this._resolveStylesCompileResult(compMeta.type.name, compileResult);
private _resolveStylesCompileResult(
result: CompiledStylesheet, externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>) {
result.dependencies.forEach((dep, i) => {
var nestedCompileResult = externalStylesheetsByModuleUrl.get(dep.moduleUrl);
var nestedStylesArr = this._resolveAndEvalStylesCompileResult(
nestedCompileResult, externalStylesheetsByModuleUrl);
dep.valuePlaceholder.runtime = nestedStylesArr;
dep.valuePlaceholder.name = `importedStyles${i}`;
});
}
private _resolveStylesCompileResult(sourceUrl: string, result: StylesCompileResult):
Promise<string[]> {
var promises = result.dependencies.map((dep) => this._loadStylesheetDep(dep));
return PromiseWrapper.all(promises)
.then((cssTexts) => {
var nestedCompileResultPromises: Promise<string[]>[] = [];
for (var i = 0; i < result.dependencies.length; i++) {
var dep = result.dependencies[i];
var cssText = cssTexts[i];
var nestedCompileResult =
this._styleCompiler.compileStylesheet(dep.moduleUrl, cssText, dep.isShimmed);
nestedCompileResultPromises.push(
this._resolveStylesCompileResult(dep.moduleUrl, nestedCompileResult));
}
return PromiseWrapper.all(nestedCompileResultPromises);
})
.then((nestedStylesArr) => {
for (var i = 0; i < result.dependencies.length; i++) {
var dep = result.dependencies[i];
dep.valuePlaceholder.runtime = nestedStylesArr[i];
dep.valuePlaceholder.name = `importedStyles${i}`;
}
if (IS_DART || !this._genConfig.useJit) {
return interpretStatements(
result.statements, result.stylesVar, new InterpretiveAppViewInstanceFactory());
} else {
return jitStatements(`${sourceUrl}.css.js`, result.statements, result.stylesVar);
}
});
}
private _loadStylesheetDep(dep: StylesCompileDependency): Promise<string> {
var cacheKey = `${dep.moduleUrl}${dep.isShimmed ? '.shim' : ''}`;
var cssTextPromise = this._styleCache.get(cacheKey);
if (isBlank(cssTextPromise)) {
cssTextPromise = this._xhr.get(dep.moduleUrl);
this._styleCache.set(cacheKey, cssTextPromise);
private _resolveAndEvalStylesCompileResult(
result: CompiledStylesheet,
externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>): string[] {
this._resolveStylesCompileResult(result, externalStylesheetsByModuleUrl);
if (IS_DART || !this._genConfig.useJit) {
return interpretStatements(
result.statements, result.stylesVar, new InterpretiveAppViewInstanceFactory());
} else {
return jitStatements(`${result.meta.moduleUrl}.css.js`, result.statements, result.stylesVar);
}
return cssTextPromise;
}
}
class CompileHostTemplate {
componentFactory: ComponentFactory<any>;
done: Promise<ComponentFactory<any>>;
constructor(_template: CompiledTemplate, compMeta: CompileDirectiveMetadata) {
this.componentFactory = new ComponentFactory<any>(
compMeta.selector, _template.proxyViewFactory, compMeta.type.runtime);
this.done = _template.done.then((_) => this.componentFactory);
}
}
class CompiledTemplate {
private _viewFactory: Function = null;
proxyViewFactory: Function;
constructor(public done: Promise<CompiledTemplate>) {
this.proxyViewFactory =
(viewUtils: any /** TODO #9100 */, childInjector: any /** TODO #9100 */,
contextEl: any /** TODO #9100 */) =>
this._viewFactory(viewUtils, childInjector, contextEl);
proxyComponentFactory: ComponentFactory<any>;
loading: Promise<any> = null;
private _normalizedCompMeta: CompileDirectiveMetadata = null;
isCompiled = false;
isCompiledWithDeps = false;
constructor(
public isHost: boolean, selector: string, public compType: CompileIdentifierMetadata,
public viewDirectives: CompileDirectiveMetadata[], public viewComponentTypes: Type[],
public precompileHostComponentTypes: Type[], public viewPipes: CompilePipeMetadata[],
private _normalizeResult: NormalizeDirectiveResult) {
this.proxyViewFactory = (...args: any[]) => this._viewFactory.apply(null, args);
this.proxyComponentFactory = isHost ?
new ComponentFactory<any>(selector, this.proxyViewFactory, compType.runtime) :
null;
if (_normalizeResult.syncResult) {
this._normalizedCompMeta = _normalizeResult.syncResult;
} else {
this.loading = _normalizeResult.asyncResult.then((normalizedCompMeta) => {
this._normalizedCompMeta = normalizedCompMeta;
this.loading = null;
});
}
}
init(viewFactory: Function) { this._viewFactory = viewFactory; }
get normalizedCompMeta(): CompileDirectiveMetadata {
if (this.loading) {
throw new BaseException(`Template is still loading for ${this.compType.name}!`);
}
return this._normalizedCompMeta;
}
compiled(viewFactory: Function) {
this._viewFactory = viewFactory;
this.isCompiled = true;
}
depsCompiled() { this.isCompiledWithDeps = true; }
}
function assertComponent(meta: CompileDirectiveMetadata) {

View File

@ -10,7 +10,7 @@ import {Injectable, ViewEncapsulation} from '@angular/core';
import {isPresent} from '../src/facade/lang';
import {CompileDirectiveMetadata, CompileIdentifierMetadata} from './compile_metadata';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileStylesheetMetadata} from './compile_metadata';
import * as o from './output/output_ast';
import {ShadowCss} from './shadow_css';
import {extractStyleUrls} from './style_url_resolver';
@ -27,9 +27,16 @@ export class StylesCompileDependency {
}
export class StylesCompileResult {
constructor(
public componentStylesheet: CompiledStylesheet,
public externalStylesheets: CompiledStylesheet[]) {}
}
export class CompiledStylesheet {
constructor(
public statements: o.Statement[], public stylesVar: string,
public dependencies: StylesCompileDependency[]) {}
public dependencies: StylesCompileDependency[], public isShimmed: boolean,
public meta: CompileStylesheetMetadata) {}
}
@Injectable()
@ -40,35 +47,41 @@ export class StyleCompiler {
compileComponent(comp: CompileDirectiveMetadata): StylesCompileResult {
var shim = comp.template.encapsulation === ViewEncapsulation.Emulated;
return this._compileStyles(
getStylesVarName(comp), comp.template.styles, comp.template.styleUrls, shim);
}
compileStylesheet(stylesheetUrl: string, cssText: string, isShimmed: boolean):
StylesCompileResult {
var styleWithImports = extractStyleUrls(this._urlResolver, stylesheetUrl, cssText);
return this._compileStyles(
getStylesVarName(null), [styleWithImports.style], styleWithImports.styleUrls, isShimmed);
var externalStylesheets: CompiledStylesheet[] = [];
var componentStylesheet: CompiledStylesheet = this._compileStyles(
comp, new CompileStylesheetMetadata({
styles: comp.template.styles,
styleUrls: comp.template.styleUrls,
moduleUrl: comp.type.moduleUrl
}),
true);
comp.template.externalStylesheets.forEach((stylesheetMeta) => {
var compiledStylesheet = this._compileStyles(comp, stylesheetMeta, false);
externalStylesheets.push(compiledStylesheet);
});
return new StylesCompileResult(componentStylesheet, externalStylesheets);
}
private _compileStyles(
stylesVar: string, plainStyles: string[], absUrls: string[],
shim: boolean): StylesCompileResult {
comp: CompileDirectiveMetadata, stylesheet: CompileStylesheetMetadata,
isComponentStylesheet: boolean): CompiledStylesheet {
var shim = comp.template.encapsulation === ViewEncapsulation.Emulated;
var styleExpressions =
plainStyles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim)));
stylesheet.styles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim)));
var dependencies: StylesCompileDependency[] = [];
for (var i = 0; i < absUrls.length; i++) {
for (var i = 0; i < stylesheet.styleUrls.length; i++) {
var identifier = new CompileIdentifierMetadata({name: getStylesVarName(null)});
dependencies.push(new StylesCompileDependency(absUrls[i], shim, identifier));
dependencies.push(new StylesCompileDependency(stylesheet.styleUrls[i], shim, identifier));
styleExpressions.push(new o.ExternalExpr(identifier));
}
// styles variable contains plain strings and arrays of other styles arrays (recursive),
// so we set its type to dynamic.
var stylesVar = getStylesVarName(isComponentStylesheet ? comp : null);
var stmt = o.variable(stylesVar)
.set(o.literalArr(
styleExpressions, new o.ArrayType(o.DYNAMIC_TYPE, [o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]);
return new StylesCompileResult([stmt], stylesVar, dependencies);
return new CompiledStylesheet([stmt], stylesVar, dependencies, shim, stylesheet);
}
private _shimIfNeeded(style: string, shim: boolean): string {
@ -78,7 +91,7 @@ export class StyleCompiler {
function getStylesVarName(component: CompileDirectiveMetadata): string {
var result = `styles`;
if (isPresent(component)) {
if (component) {
result += `_${component.type.name}`;
}
return result;

View File

@ -32,7 +32,7 @@ var rootSelectorVar = o.variable('rootSelector');
export class ViewFactoryDependency {
constructor(
public comp: CompileDirectiveMetadata, public placeholder: CompileIdentifierMetadata) {}
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
}
export class ComponentFactoryDependency {
@ -208,7 +208,8 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
if (isPresent(component)) {
let nestedComponentIdentifier =
new CompileIdentifierMetadata({name: getViewFactoryName(component, 0)});
this.targetDependencies.push(new ViewFactoryDependency(component, nestedComponentIdentifier));
this.targetDependencies.push(
new ViewFactoryDependency(component.type, nestedComponentIdentifier));
let precompileComponentIdentifiers =
component.precompile.map((precompileComp: CompileIdentifierMetadata) => {
var id = new CompileIdentifierMetadata({name: precompileComp.name});

View File

@ -19,24 +19,9 @@ import {Map} from '../src/facade/collection';
*/
@Injectable()
export class ViewResolver {
/** @internal */
_cache = new Map<Type, ViewMetadata>();
constructor(private _reflector: ReflectorReader = reflector) {}
resolve(component: Type): ViewMetadata {
var view = this._cache.get(component);
if (isBlank(view)) {
view = this._resolve(component);
this._cache.set(component, view);
}
return view;
}
/** @internal */
_resolve(component: Type): ViewMetadata {
var compMeta: ComponentMetadata;
this._reflector.annotations(component).forEach(m => {