feat(core): add @Component.precompile
and ComponentFactoryResolver
Part to #9467 Closes #9543
This commit is contained in:
@ -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