feat(core): add @Component.precompile
and ComponentFactoryResolver
Part to #9467 Closes #9543
This commit is contained in:
@ -675,7 +675,7 @@ export class CompileTemplateMetadata {
|
||||
export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
static create(
|
||||
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
|
||||
lifecycleHooks, providers, viewProviders, queries, viewQueries, template}: {
|
||||
lifecycleHooks, providers, viewProviders, queries, viewQueries, precompile, template}: {
|
||||
type?: CompileTypeMetadata,
|
||||
isComponent?: boolean,
|
||||
selector?: string,
|
||||
@ -691,6 +691,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
||||
queries?: CompileQueryMetadata[],
|
||||
viewQueries?: CompileQueryMetadata[],
|
||||
precompile?: CompileTypeMetadata[],
|
||||
template?: CompileTemplateMetadata
|
||||
} = {}): CompileDirectiveMetadata {
|
||||
var hostListeners: {[key: string]: string} = {};
|
||||
@ -743,6 +744,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
viewProviders: viewProviders,
|
||||
queries: queries,
|
||||
viewQueries: viewQueries,
|
||||
precompile: precompile,
|
||||
template: template
|
||||
});
|
||||
}
|
||||
@ -761,12 +763,13 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
viewProviders: CompileProviderMetadata[];
|
||||
queries: CompileQueryMetadata[];
|
||||
viewQueries: CompileQueryMetadata[];
|
||||
precompile: CompileTypeMetadata[];
|
||||
|
||||
template: CompileTemplateMetadata;
|
||||
constructor(
|
||||
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners,
|
||||
hostProperties, hostAttributes, lifecycleHooks, providers, viewProviders, queries,
|
||||
viewQueries, template}: {
|
||||
viewQueries, precompile, template}: {
|
||||
type?: CompileTypeMetadata,
|
||||
isComponent?: boolean,
|
||||
selector?: string,
|
||||
@ -784,6 +787,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
||||
queries?: CompileQueryMetadata[],
|
||||
viewQueries?: CompileQueryMetadata[],
|
||||
precompile?: CompileTypeMetadata[],
|
||||
template?: CompileTemplateMetadata
|
||||
} = {}) {
|
||||
this.type = type;
|
||||
@ -801,6 +805,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
this.viewProviders = _normalizeArray(viewProviders);
|
||||
this.queries = _normalizeArray(queries);
|
||||
this.viewQueries = _normalizeArray(viewQueries);
|
||||
this.precompile = _normalizeArray(precompile);
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
@ -827,7 +832,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
providers: _arrayFromJson(data['providers'], metadataFromJson),
|
||||
viewProviders: _arrayFromJson(data['viewProviders'], metadataFromJson),
|
||||
queries: _arrayFromJson(data['queries'], CompileQueryMetadata.fromJson),
|
||||
viewQueries: _arrayFromJson(data['viewQueries'], CompileQueryMetadata.fromJson)
|
||||
viewQueries: _arrayFromJson(data['viewQueries'], CompileQueryMetadata.fromJson),
|
||||
precompile: _arrayFromJson(data['precompile'], CompileTypeMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
|
||||
@ -850,7 +856,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
'providers': _arrayToJson(this.providers),
|
||||
'viewProviders': _arrayToJson(this.viewProviders),
|
||||
'queries': _arrayToJson(this.queries),
|
||||
'viewQueries': _arrayToJson(this.viewQueries)
|
||||
'viewQueries': _arrayToJson(this.viewQueries),
|
||||
'precompile': _arrayToJson(this.precompile)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ export class DirectiveNormalizer {
|
||||
viewProviders: directive.viewProviders,
|
||||
queries: directive.queries,
|
||||
viewQueries: directive.viewQueries,
|
||||
precompile: directive.precompile,
|
||||
template: normalizedTemplate
|
||||
}));
|
||||
}
|
||||
|
@ -125,7 +125,8 @@ export class DirectiveResolver {
|
||||
queries: mergedQueries,
|
||||
changeDetection: dm.changeDetection,
|
||||
providers: dm.providers,
|
||||
viewProviders: dm.viewProviders
|
||||
viewProviders: dm.viewProviders,
|
||||
precompile: dm.precompile
|
||||
});
|
||||
|
||||
} else {
|
||||
|
@ -6,9 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppView, ChangeDetectorState, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, SecurityContext, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles, uninitialized} from '../core_private';
|
||||
import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppView, ChangeDetectorState, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, SecurityContext, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles, uninitialized} from '../core_private';
|
||||
|
||||
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
||||
import {assetUrl} from './util';
|
||||
@ -98,6 +98,16 @@ export class Identifiers {
|
||||
moduleUrl: assetUrl('core', 'linker/template_ref'),
|
||||
runtime: impTemplateRef_
|
||||
});
|
||||
static CodegenComponentFactoryResolver = new CompileIdentifierMetadata({
|
||||
name: 'CodegenComponentFactoryResolver',
|
||||
moduleUrl: assetUrl('core', 'linker/component_factory_resolver'),
|
||||
runtime: CodegenComponentFactoryResolver
|
||||
});
|
||||
static ComponentFactoryResolver = new CompileIdentifierMetadata({
|
||||
name: 'ComponentFactoryResolver',
|
||||
moduleUrl: assetUrl('core', 'linker/component_factory_resolver'),
|
||||
runtime: ComponentFactoryResolver
|
||||
});
|
||||
static ValueUnwrapper = new CompileIdentifierMetadata(
|
||||
{name: 'ValueUnwrapper', moduleUrl: CD_MODULE_URL, runtime: impValueUnwrapper});
|
||||
static Injector = new CompileIdentifierMetadata(
|
||||
|
@ -99,6 +99,7 @@ export class CompileMetadataResolver {
|
||||
var changeDetectionStrategy: any /** TODO #9100 */ = null;
|
||||
var viewProviders: any[] /** TODO #9100 */ = [];
|
||||
var moduleUrl = staticTypeModuleUrl(directiveType);
|
||||
var precompileTypes: cpl.CompileTypeMetadata[] = [];
|
||||
if (dirMeta instanceof ComponentMetadata) {
|
||||
assertArrayOfStrings('styles', dirMeta.styles);
|
||||
var cmpMeta = <ComponentMetadata>dirMeta;
|
||||
@ -124,6 +125,10 @@ export class CompileMetadataResolver {
|
||||
verifyNonBlankProviders(directiveType, dirMeta.viewProviders, 'viewProviders'));
|
||||
}
|
||||
moduleUrl = componentModuleUrl(this._reflector, directiveType, cmpMeta);
|
||||
if (cmpMeta.precompile) {
|
||||
precompileTypes = flattenArray(cmpMeta.precompile)
|
||||
.map((cmp) => this.getTypeMetadata(cmp, staticTypeModuleUrl(cmp)));
|
||||
}
|
||||
}
|
||||
|
||||
var providers: any[] /** TODO #9100 */ = [];
|
||||
@ -152,7 +157,8 @@ export class CompileMetadataResolver {
|
||||
providers: providers,
|
||||
viewProviders: viewProviders,
|
||||
queries: queries,
|
||||
viewQueries: viewQueries
|
||||
viewQueries: viewQueries,
|
||||
precompile: precompileTypes
|
||||
});
|
||||
this._directiveCache.set(directiveType, meta);
|
||||
}
|
||||
@ -422,7 +428,7 @@ function flattenPipes(view: ViewMetadata, platformPipes: any[]): Type[] {
|
||||
return pipes;
|
||||
}
|
||||
|
||||
function flattenArray(tree: any[], out: Array<Type|any[]>): void {
|
||||
function flattenArray(tree: any[], out: Array<Type> = []): Array<Type> {
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
var item = resolveForwardRef(tree[i]);
|
||||
if (isArray(item)) {
|
||||
@ -431,6 +437,7 @@ function flattenArray(tree: any[], out: Array<Type|any[]>): void {
|
||||
out.push(item);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function verifyNonBlankProviders(
|
||||
|
@ -17,7 +17,7 @@ import * as o from './output/output_ast';
|
||||
import {StyleCompiler, StylesCompileResult} from './style_compiler';
|
||||
import {TemplateParser} from './template_parser';
|
||||
import {assetUrl} from './util';
|
||||
import {ViewCompileResult, ViewCompiler} from './view_compiler/view_compiler';
|
||||
import {ComponentFactoryDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
|
||||
import {XHR} from './xhr';
|
||||
|
||||
var _COMPONENT_FACTORY_IDENTIFIER = new CompileIdentifierMetadata({
|
||||
@ -57,7 +57,7 @@ export class OfflineCompiler {
|
||||
}
|
||||
var statements: o.DeclareVarStmt[] = [];
|
||||
var exportedVars: string[] = [];
|
||||
var moduleUrl = _templateModuleUrl(components[0].component);
|
||||
var moduleUrl = _ngfactoryModuleUrl(components[0].component.type);
|
||||
components.forEach(componentWithDirs => {
|
||||
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
|
||||
_assertComponent(compMeta);
|
||||
@ -67,7 +67,7 @@ export class OfflineCompiler {
|
||||
|
||||
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||
var hostViewFactoryVar = this._compileComponent(hostMeta, [compMeta], [], statements);
|
||||
var compFactoryVar = `${compMeta.type.name}NgFactory`;
|
||||
var compFactoryVar = _componentFactoryName(compMeta.type);
|
||||
statements.push(
|
||||
o.variable(compFactoryVar)
|
||||
.set(o.importExpr(_COMPONENT_FACTORY_IDENTIFIER, [o.importType(compMeta.type)])
|
||||
@ -129,8 +129,14 @@ export class OfflineCompiler {
|
||||
}
|
||||
|
||||
function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[] {
|
||||
compileResult.dependencies.forEach(
|
||||
(dep) => { dep.factoryPlaceholder.moduleUrl = _templateModuleUrl(dep.comp); });
|
||||
compileResult.dependencies.forEach((dep) => {
|
||||
if (dep instanceof ViewFactoryDependency) {
|
||||
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp.type);
|
||||
} else if (dep instanceof ComponentFactoryDependency) {
|
||||
dep.placeholder.name = _componentFactoryName(dep.comp);
|
||||
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp);
|
||||
}
|
||||
});
|
||||
return compileResult.statements;
|
||||
}
|
||||
|
||||
@ -145,11 +151,15 @@ function _resolveStyleStatements(
|
||||
return compileResult.statements;
|
||||
}
|
||||
|
||||
function _templateModuleUrl(comp: CompileDirectiveMetadata): string {
|
||||
var urlWithSuffix = _splitSuffix(comp.type.moduleUrl);
|
||||
function _ngfactoryModuleUrl(comp: CompileIdentifierMetadata): string {
|
||||
var urlWithSuffix = _splitSuffix(comp.moduleUrl);
|
||||
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
|
||||
}
|
||||
|
||||
function _componentFactoryName(comp: CompileIdentifierMetadata): string {
|
||||
return `${comp.name}NgFactory`;
|
||||
}
|
||||
|
||||
function _stylesModuleUrl(stylesheetUrl: string, shim: boolean, suffix: string): string {
|
||||
return shim ? `${stylesheetUrl}.shim${suffix}` : `${stylesheetUrl}${suffix}`;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ 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} from './view_compiler/view_compiler';
|
||||
import {ViewCompiler, ViewFactoryDependency, ComponentFactoryDependency} from './view_compiler/view_compiler';
|
||||
import {TemplateParser} from './template_parser';
|
||||
import {DirectiveNormalizer} from './directive_normalizer';
|
||||
import {CompileMetadataResolver} from './metadata_resolver';
|
||||
@ -37,7 +37,6 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||
private _styleCache: Map<string, Promise<string>> = new Map<string, Promise<string>>();
|
||||
private _hostCacheKeys = new Map<Type, any>();
|
||||
private _compiledTemplateCache = new Map<any, CompiledTemplate>();
|
||||
private _compiledTemplateDone = new Map<any, Promise<CompiledTemplate>>();
|
||||
|
||||
constructor(
|
||||
private _metadataResolver: CompileMetadataResolver,
|
||||
@ -50,43 +49,38 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||
return PromiseWrapper.reject(
|
||||
new BaseException(`Cannot resolve component using '${component}'.`), null);
|
||||
}
|
||||
return this._loadAndCompileHostComponent(<Type>component).done;
|
||||
}
|
||||
|
||||
let componentType = <Type>component;
|
||||
clearCache(): void {
|
||||
this._styleCache.clear();
|
||||
this._compiledTemplateCache.clear();
|
||||
this._hostCacheKeys.clear();
|
||||
}
|
||||
|
||||
private _loadAndCompileHostComponent(componentType: Type): CompileHostTemplate {
|
||||
var compMeta: CompileDirectiveMetadata =
|
||||
this._metadataResolver.getDirectiveMetadata(componentType);
|
||||
var hostCacheKey = this._hostCacheKeys.get(componentType);
|
||||
var hostCacheKey = this._hostCacheKeys.get(compMeta.type.runtime);
|
||||
if (isBlank(hostCacheKey)) {
|
||||
hostCacheKey = new Object();
|
||||
this._hostCacheKeys.set(componentType, hostCacheKey);
|
||||
this._hostCacheKeys.set(compMeta.type.runtime, hostCacheKey);
|
||||
assertComponent(compMeta);
|
||||
var hostMeta: CompileDirectiveMetadata =
|
||||
createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||
|
||||
this._loadAndCompileComponent(hostCacheKey, hostMeta, [compMeta], [], []);
|
||||
}
|
||||
return this._compiledTemplateDone.get(hostCacheKey)
|
||||
.then(
|
||||
(compiledTemplate: CompiledTemplate) => new ComponentFactory(
|
||||
compMeta.selector, compiledTemplate.viewFactory, componentType));
|
||||
var compTemplate = this._compiledTemplateCache.get(hostCacheKey);
|
||||
return new CompileHostTemplate(compTemplate, compMeta);
|
||||
}
|
||||
|
||||
clearCache(): void {
|
||||
this._styleCache.clear();
|
||||
this._compiledTemplateCache.clear();
|
||||
this._compiledTemplateDone.clear();
|
||||
this._hostCacheKeys.clear();
|
||||
}
|
||||
|
||||
|
||||
private _loadAndCompileComponent(
|
||||
cacheKey: any, compMeta: CompileDirectiveMetadata, viewDirectives: CompileDirectiveMetadata[],
|
||||
pipes: CompilePipeMetadata[], compilingComponentsPath: any[]): CompiledTemplate {
|
||||
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
|
||||
var done = this._compiledTemplateDone.get(cacheKey);
|
||||
if (isBlank(compiledTemplate)) {
|
||||
compiledTemplate = new CompiledTemplate();
|
||||
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
|
||||
done =
|
||||
let done =
|
||||
PromiseWrapper
|
||||
.all([<any>this._compileComponentStyles(compMeta)].concat(viewDirectives.map(
|
||||
dirMeta => this._templateNormalizer.normalizeDirective(dirMeta))))
|
||||
@ -103,7 +97,8 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||
childPromises));
|
||||
return PromiseWrapper.all(childPromises).then((_) => { return compiledTemplate; });
|
||||
});
|
||||
this._compiledTemplateDone.set(cacheKey, done);
|
||||
compiledTemplate = new CompiledTemplate(done);
|
||||
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
|
||||
}
|
||||
return compiledTemplate;
|
||||
}
|
||||
@ -116,26 +111,32 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||
compMeta, parsedTemplate,
|
||||
new ir.ExternalExpr(new CompileIdentifierMetadata({runtime: styles})), pipes);
|
||||
compileResult.dependencies.forEach((dep) => {
|
||||
var childCompilingComponentsPath = ListWrapper.clone(compilingComponentsPath);
|
||||
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 ||
|
||||
childViewDirectives.some(
|
||||
dir => childCompilingComponentsPath.indexOf(dir.type.runtime) > -1);
|
||||
childCompilingComponentsPath.push(childCacheKey);
|
||||
|
||||
var childCacheKey = dep.comp.type.runtime;
|
||||
var childViewDirectives: CompileDirectiveMetadata[] =
|
||||
this._metadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
|
||||
var childViewPipes: CompilePipeMetadata[] =
|
||||
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
|
||||
var childIsRecursive = childCompilingComponentsPath.indexOf(childCacheKey) > -1 ||
|
||||
childViewDirectives.some(
|
||||
dir => childCompilingComponentsPath.indexOf(dir.type.runtime) > -1);
|
||||
childCompilingComponentsPath.push(childCacheKey);
|
||||
|
||||
var childComp = this._loadAndCompileComponent(
|
||||
dep.comp.type.runtime, dep.comp, childViewDirectives, childViewPipes,
|
||||
childCompilingComponentsPath);
|
||||
dep.factoryPlaceholder.runtime = childComp.proxyViewFactory;
|
||||
dep.factoryPlaceholder.name = `viewFactory_${dep.comp.type.name}`;
|
||||
if (!childIsRecursive) {
|
||||
// Only wait for a child if it is not a cycle
|
||||
childPromises.push(this._compiledTemplateDone.get(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);
|
||||
}
|
||||
} else if (dep instanceof ComponentFactoryDependency) {
|
||||
let childComp = this._loadAndCompileHostComponent(dep.comp.runtime);
|
||||
dep.placeholder.runtime = childComp.componentFactory;
|
||||
dep.placeholder.name = `compFactory_${dep.comp.name}`;
|
||||
childPromises.push(childComp.done);
|
||||
}
|
||||
});
|
||||
var factory: any;
|
||||
@ -198,16 +199,27 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
viewFactory: Function = null;
|
||||
private _viewFactory: Function = null;
|
||||
proxyViewFactory: Function;
|
||||
constructor() {
|
||||
constructor(public done: Promise<CompiledTemplate>) {
|
||||
this.proxyViewFactory =
|
||||
(viewUtils: any /** TODO #9100 */, childInjector: any /** TODO #9100 */,
|
||||
contextEl: any /** TODO #9100 */) => this.viewFactory(viewUtils, childInjector, contextEl);
|
||||
contextEl: any /** TODO #9100 */) =>
|
||||
this._viewFactory(viewUtils, childInjector, contextEl);
|
||||
}
|
||||
|
||||
init(viewFactory: Function) { this.viewFactory = viewFactory; }
|
||||
init(viewFactory: Function) { this._viewFactory = viewFactory; }
|
||||
}
|
||||
|
||||
function assertComponent(meta: CompileDirectiveMetadata) {
|
||||
|
@ -91,6 +91,28 @@ export class CompileElement extends CompileNode {
|
||||
this._instances.add(identifierToken(Identifiers.AppElement), this.appElement);
|
||||
}
|
||||
|
||||
public createComponentFactoryResolver(precompileComponent: CompileIdentifierMetadata[]) {
|
||||
if (!precompileComponent || precompileComponent.length === 0) {
|
||||
return;
|
||||
}
|
||||
var createComponentFactoryResolverExpr =
|
||||
o.importExpr(Identifiers.CodegenComponentFactoryResolver).instantiate([
|
||||
o.literalArr(precompileComponent.map(
|
||||
(precompiledComponent) => o.importExpr(precompiledComponent))),
|
||||
injectFromViewParentInjector(identifierToken(Identifiers.ComponentFactoryResolver), false)
|
||||
]);
|
||||
var provider = new CompileProviderMetadata({
|
||||
token: identifierToken(Identifiers.ComponentFactoryResolver),
|
||||
useValue: createComponentFactoryResolverExpr
|
||||
});
|
||||
// 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,
|
||||
// but nobody else
|
||||
this._resolvedProvidersArray.unshift(new ProviderAst(
|
||||
provider.token, false, true, [provider], ProviderAstType.PrivateService,
|
||||
this.sourceAst.sourceSpan));
|
||||
}
|
||||
|
||||
setComponentView(compViewExpr: o.Expression) {
|
||||
this._compViewExpr = compViewExpr;
|
||||
this.contentNodesByNgContentIndex =
|
||||
@ -167,21 +189,20 @@ export class CompileElement extends CompileNode {
|
||||
queriesWithReads,
|
||||
queriesForProvider.map(query => new _QueryWithRead(query, resolvedProvider.token)));
|
||||
});
|
||||
StringMapWrapper.forEach(
|
||||
this.referenceTokens, (_: any /** TODO #9100 */, varName: any /** TODO #9100 */) => {
|
||||
var token = this.referenceTokens[varName];
|
||||
var varValue: any /** TODO #9100 */;
|
||||
if (isPresent(token)) {
|
||||
varValue = this._instances.get(token);
|
||||
} else {
|
||||
varValue = this.renderNode;
|
||||
}
|
||||
this.view.locals.set(varName, varValue);
|
||||
var varToken = new CompileTokenMetadata({value: varName});
|
||||
ListWrapper.addAll(
|
||||
queriesWithReads,
|
||||
this._getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
|
||||
});
|
||||
StringMapWrapper.forEach(this.referenceTokens, (_: CompileTokenMetadata, varName: string) => {
|
||||
var token = this.referenceTokens[varName];
|
||||
var varValue: o.Expression;
|
||||
if (isPresent(token)) {
|
||||
varValue = this._instances.get(token);
|
||||
} else {
|
||||
varValue = this.renderNode;
|
||||
}
|
||||
this.view.locals.set(varName, varValue);
|
||||
var varToken = new CompileTokenMetadata({value: varName});
|
||||
ListWrapper.addAll(
|
||||
queriesWithReads,
|
||||
this._getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
|
||||
});
|
||||
queriesWithReads.forEach((queryWithRead) => {
|
||||
var value: o.Expression;
|
||||
if (isPresent(queryWithRead.read.identifier)) {
|
||||
@ -285,7 +306,7 @@ export class CompileElement extends CompileNode {
|
||||
|
||||
private _getLocalDependency(
|
||||
requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata): o.Expression {
|
||||
var result: any /** TODO #9100 */ = null;
|
||||
var result: o.Expression = null;
|
||||
// constructor content query
|
||||
if (isBlank(result) && isPresent(dep.query)) {
|
||||
result = this._addQuery(dep.query, null).queryList;
|
||||
@ -330,7 +351,7 @@ export class CompileElement extends CompileNode {
|
||||
private _getDependency(requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata):
|
||||
o.Expression {
|
||||
var currElement: CompileElement = this;
|
||||
var result: any /** TODO #9100 */ = null;
|
||||
var result: o.Expression = null;
|
||||
if (dep.isValue) {
|
||||
result = o.literal(dep.value);
|
||||
}
|
||||
@ -357,7 +378,7 @@ export class CompileElement extends CompileNode {
|
||||
function createInjectInternalCondition(
|
||||
nodeIndex: number, childNodeCount: number, provider: ProviderAst,
|
||||
providerExpr: o.Expression): o.Statement {
|
||||
var indexCondition: any /** TODO #9100 */;
|
||||
var indexCondition: o.Expression;
|
||||
if (childNodeCount > 0) {
|
||||
indexCondition = o.literal(nodeIndex)
|
||||
.lowerEquals(InjectMethodVars.requestNodeIndex)
|
||||
@ -375,8 +396,8 @@ function createProviderProperty(
|
||||
propName: string, provider: ProviderAst, providerValueExpressions: o.Expression[],
|
||||
isMulti: boolean, isEager: boolean, compileElement: CompileElement): o.Expression {
|
||||
var view = compileElement.view;
|
||||
var resolvedProviderValueExpr: any /** TODO #9100 */;
|
||||
var type: any /** TODO #9100 */;
|
||||
var resolvedProviderValueExpr: o.Expression;
|
||||
var type: o.Type;
|
||||
if (isMulti) {
|
||||
resolvedProviderValueExpr = o.literalArr(providerValueExpressions);
|
||||
type = new o.ArrayType(o.DYNAMIC_TYPE);
|
||||
@ -421,8 +442,8 @@ class _ValueOutputAstTransformer extends ValueTransformer {
|
||||
return o.literalArr(arr.map(value => visitValue(value, this, context)));
|
||||
}
|
||||
visitStringMap(map: {[key: string]: any}, context: any): o.Expression {
|
||||
var entries: any[] /** TODO #9100 */ = [];
|
||||
StringMapWrapper.forEach(map, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => {
|
||||
var entries: Array<string|o.Expression>[] = [];
|
||||
StringMapWrapper.forEach(map, (value: any, key: string) => {
|
||||
entries.push([key, visitValue(value, this, context)]);
|
||||
});
|
||||
return o.literalMap(entries);
|
||||
|
@ -9,22 +9,18 @@
|
||||
import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {ViewType, isDefaultChangeDetectionStrategy} from '../../core_private';
|
||||
import {AnimationCompiler} from '../animation/animation_compiler';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileTokenMetadata, CompileTypeMetadata} from '../compile_metadata';
|
||||
import {ListWrapper, SetWrapper, StringMapWrapper} from '../facade/collection';
|
||||
import {StringWrapper, isPresent} from '../facade/lang';
|
||||
import {Identifiers, identifierToken} from '../identifiers';
|
||||
import * as o from '../output/output_ast';
|
||||
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ProviderAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_ast';
|
||||
|
||||
import {CompileElement, CompileNode} from './compile_element';
|
||||
import {CompileView} from './compile_view';
|
||||
import {ChangeDetectionStrategyEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
|
||||
|
||||
import {TemplateAst, TemplateAstVisitor, NgContentAst, EmbeddedTemplateAst, ElementAst, ReferenceAst, VariableAst, BoundEventAst, BoundElementPropertyAst, AttrAst, BoundTextAst, TextAst, DirectiveAst, BoundDirectivePropertyAst, templateVisitAll,} from '../template_ast';
|
||||
|
||||
import {getViewFactoryName, createFlatArray, createDiTokenExpression} from './util';
|
||||
|
||||
import {CompileIdentifierMetadata, CompileDirectiveMetadata, CompileTokenMetadata} from '../compile_metadata';
|
||||
|
||||
import {AnimationCompiler} from '../animation/animation_compiler';
|
||||
import {createDiTokenExpression, createFlatArray, getViewFactoryName} from './util';
|
||||
|
||||
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
||||
const CLASS_ATTR = 'class';
|
||||
@ -34,15 +30,20 @@ const NG_CONTAINER_TAG = 'ng-container';
|
||||
var parentRenderNodeVar = o.variable('parentRenderNode');
|
||||
var rootSelectorVar = o.variable('rootSelector');
|
||||
|
||||
export class ViewCompileDependency {
|
||||
export class ViewFactoryDependency {
|
||||
constructor(
|
||||
public comp: CompileDirectiveMetadata, public factoryPlaceholder: CompileIdentifierMetadata) {
|
||||
}
|
||||
public comp: CompileDirectiveMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||
}
|
||||
|
||||
export class ComponentFactoryDependency {
|
||||
constructor(
|
||||
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||
}
|
||||
|
||||
|
||||
export function buildView(
|
||||
view: CompileView, template: TemplateAst[],
|
||||
targetDependencies: ViewCompileDependency[]): number {
|
||||
targetDependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>): number {
|
||||
var builderVisitor = new ViewBuilderVisitor(view, targetDependencies);
|
||||
templateVisitAll(
|
||||
builderVisitor, template,
|
||||
@ -65,7 +66,9 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
||||
|
||||
private _animationCompiler = new AnimationCompiler();
|
||||
|
||||
constructor(public view: CompileView, public targetDependencies: ViewCompileDependency[]) {}
|
||||
constructor(
|
||||
public view: CompileView,
|
||||
public targetDependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>) {}
|
||||
|
||||
private _isRootNode(parent: CompileElement): boolean { return parent.view !== this.view; }
|
||||
|
||||
@ -203,9 +206,17 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
||||
this.view.nodes.push(compileElement);
|
||||
var compViewExpr: o.ReadVarExpr = null;
|
||||
if (isPresent(component)) {
|
||||
var nestedComponentIdentifier =
|
||||
let nestedComponentIdentifier =
|
||||
new CompileIdentifierMetadata({name: getViewFactoryName(component, 0)});
|
||||
this.targetDependencies.push(new ViewCompileDependency(component, nestedComponentIdentifier));
|
||||
this.targetDependencies.push(new ViewFactoryDependency(component, nestedComponentIdentifier));
|
||||
let precompileComponentIdentifiers =
|
||||
component.precompile.map((precompileComp: CompileIdentifierMetadata) => {
|
||||
var id = new CompileIdentifierMetadata({name: precompileComp.name});
|
||||
this.targetDependencies.push(new ComponentFactoryDependency(precompileComp, id));
|
||||
return id;
|
||||
});
|
||||
compileElement.createComponentFactoryResolver(precompileComponentIdentifiers);
|
||||
|
||||
compViewExpr = o.variable(`compView_${nodeIndex}`); // fix highlighting: `
|
||||
compileElement.setComponentView(compViewExpr);
|
||||
this.view.createMethod.addStmt(
|
||||
|
@ -17,12 +17,14 @@ import {TemplateAst} from '../template_ast';
|
||||
import {CompileElement} from './compile_element';
|
||||
import {CompileView} from './compile_view';
|
||||
import {bindView} from './view_binder';
|
||||
import {ViewCompileDependency, buildView, finishView} from './view_builder';
|
||||
import {ComponentFactoryDependency, ViewFactoryDependency, buildView, finishView} from './view_builder';
|
||||
|
||||
export {ComponentFactoryDependency, ViewFactoryDependency} from './view_builder';
|
||||
|
||||
export class ViewCompileResult {
|
||||
constructor(
|
||||
public statements: o.Statement[], public viewFactoryVar: string,
|
||||
public dependencies: ViewCompileDependency[]) {}
|
||||
public dependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>) {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@ -33,9 +35,9 @@ export class ViewCompiler {
|
||||
compileComponent(
|
||||
component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression,
|
||||
pipes: CompilePipeMetadata[]): ViewCompileResult {
|
||||
var dependencies: any[] /** TODO #9100 */ = [];
|
||||
var dependencies: Array<ViewFactoryDependency|ComponentFactoryDependency> = [];
|
||||
var compiledAnimations = this._animationCompiler.compileComponent(component);
|
||||
var statements: any[] /** TODO #9100 */ = [];
|
||||
var statements: o.Statement[] = [];
|
||||
compiledAnimations.map(entry => {
|
||||
statements.push(entry.statesMapStatement);
|
||||
statements.push(entry.fnStatement);
|
||||
|
Reference in New Issue
Block a user