fix(compiler): make view engine work with Aot

This commit is contained in:
Tobias Bosch 2017-02-17 08:56:49 -08:00 committed by Igor Minar
parent 2ddd1c3ed2
commit 58ba4f0409
15 changed files with 176 additions and 75 deletions

View File

@ -28,6 +28,7 @@ export {CompilerConfig, RenderTypes} from './src/config';
export * from './src/compile_metadata'; export * from './src/compile_metadata';
export * from './src/aot/compiler_factory'; export * from './src/aot/compiler_factory';
export * from './src/aot/compiler'; export * from './src/aot/compiler';
export * from './src/aot/compiler_options';
export * from './src/aot/compiler_host'; export * from './src/aot/compiler_host';
export * from './src/aot/static_reflector'; export * from './src/aot/static_reflector';
export * from './src/aot/static_reflection_capabilities'; export * from './src/aot/static_reflection_capabilities';

View File

@ -9,6 +9,7 @@
import {AnimationCompiler} from '../animation/animation_compiler'; import {AnimationCompiler} from '../animation/animation_compiler';
import {AnimationParser} from '../animation/animation_parser'; import {AnimationParser} from '../animation/animation_parser';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, componentFactoryName, createHostComponentMeta, identifierName} from '../compile_metadata'; import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, componentFactoryName, createHostComponentMeta, identifierName} from '../compile_metadata';
import {CompilerConfig} from '../config';
import {DirectiveWrapperCompiler} from '../directive_wrapper_compiler'; import {DirectiveWrapperCompiler} from '../directive_wrapper_compiler';
import {ListWrapper} from '../facade/collection'; import {ListWrapper} from '../facade/collection';
import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers'; import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers';
@ -33,9 +34,10 @@ export class AotCompiler {
private _animationCompiler = new AnimationCompiler(); private _animationCompiler = new AnimationCompiler();
constructor( constructor(
private _host: AotCompilerHost, private _metadataResolver: CompileMetadataResolver, private _config: CompilerConfig, private _host: AotCompilerHost,
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler, private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser,
private _viewCompiler: ViewCompiler, private _dirWrapperCompiler: DirectiveWrapperCompiler, private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
private _dirWrapperCompiler: DirectiveWrapperCompiler,
private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter, private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter,
private _summaryResolver: SummaryResolver<StaticSymbol>, private _localeId: string, private _summaryResolver: SummaryResolver<StaticSymbol>, private _localeId: string,
private _translationFormat: string, private _animationParser: AnimationParser, private _translationFormat: string, private _animationParser: AnimationParser,
@ -77,8 +79,10 @@ export class AotCompiler {
...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements))); ...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements)));
// compile directive wrappers // compile directive wrappers
exportedVars.push(...directives.map( if (!this._config.useViewEngine) {
(directiveType) => this._compileDirectiveWrapper(directiveType, statements))); exportedVars.push(...directives.map(
(directiveType) => this._compileDirectiveWrapper(directiveType, statements)));
}
// compile components // compile components
directives.forEach((dirType) => { directives.forEach((dirType) => {
@ -181,20 +185,35 @@ export class AotCompiler {
hostMeta, ngModule, [compMeta.type], null, fileSuffix, targetStatements) hostMeta, ngModule, [compMeta.type], null, fileSuffix, targetStatements)
.viewClassVar; .viewClassVar;
const compFactoryVar = componentFactoryName(compMeta.type.reference); const compFactoryVar = componentFactoryName(compMeta.type.reference);
targetStatements.push( if (this._config.useViewEngine) {
o.variable(compFactoryVar) targetStatements.push(
.set(o.importExpr( o.variable(compFactoryVar)
createIdentifier(Identifiers.ComponentFactory), [o.importType(compMeta.type)]) .set(o.importExpr(createIdentifier(Identifiers.createComponentFactory)).callFn([
.instantiate( o.literal(compMeta.selector),
[ o.importExpr(compMeta.type),
o.literal(compMeta.selector), o.variable(hostViewFactoryVar),
o.variable(hostViewFactoryVar), ]))
o.importExpr(compMeta.type), .toDeclStmt(
], o.importType(
o.importType( createIdentifier(Identifiers.ComponentFactory), [o.importType(compMeta.type)],
createIdentifier(Identifiers.ComponentFactory), [o.TypeModifier.Const]),
[o.importType(compMeta.type)], [o.TypeModifier.Const]))) [o.StmtModifier.Final]));
.toDeclStmt(null, [o.StmtModifier.Final])); } else {
targetStatements.push(
o.variable(compFactoryVar)
.set(o.importExpr(createIdentifier(Identifiers.ComponentFactory), [o.importType(
compMeta.type)])
.instantiate(
[
o.literal(compMeta.selector),
o.variable(hostViewFactoryVar),
o.importExpr(compMeta.type),
],
o.importType(
createIdentifier(Identifiers.ComponentFactory),
[o.importType(compMeta.type)], [o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]));
}
return compFactoryVar; return compFactoryVar;
} }

View File

@ -28,6 +28,7 @@ import {StyleCompiler} from '../style_compiler';
import {TemplateParser} from '../template_parser/template_parser'; import {TemplateParser} from '../template_parser/template_parser';
import {createOfflineCompileUrlResolver} from '../url_resolver'; import {createOfflineCompileUrlResolver} from '../url_resolver';
import {ViewCompiler} from '../view_compiler/view_compiler'; import {ViewCompiler} from '../view_compiler/view_compiler';
import {ViewCompilerNext} from '../view_compiler_next/view_compiler';
import {AotCompiler} from './compiler'; import {AotCompiler} from './compiler';
import {AotCompilerHost} from './compiler_host'; import {AotCompilerHost} from './compiler_host';
@ -61,7 +62,8 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
genDebugInfo: options.debug === true, genDebugInfo: options.debug === true,
defaultEncapsulation: ViewEncapsulation.Emulated, defaultEncapsulation: ViewEncapsulation.Emulated,
logBindingUpdate: false, logBindingUpdate: false,
useJit: false useJit: false,
useViewEngine: options.useViewEngine
}); });
const normalizer = new DirectiveNormalizer( const normalizer = new DirectiveNormalizer(
{get: (url: string) => compilerHost.loadResource(url)}, urlResolver, htmlParser, config); {get: (url: string) => compilerHost.loadResource(url)}, urlResolver, htmlParser, config);
@ -80,9 +82,10 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
compilerHost.fileNameToModuleName(fileName, containingFilePath), compilerHost.fileNameToModuleName(fileName, containingFilePath),
getTypeArity: (symbol: StaticSymbol) => symbolResolver.getTypeArity(symbol) getTypeArity: (symbol: StaticSymbol) => symbolResolver.getTypeArity(symbol)
}; };
const viewCompiler = config.useViewEngine ? new ViewCompilerNext(config, elementSchemaRegistry) :
new ViewCompiler(config, elementSchemaRegistry);
const compiler = new AotCompiler( const compiler = new AotCompiler(
compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), config, compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), viewCompiler,
new ViewCompiler(config, elementSchemaRegistry),
new DirectiveWrapperCompiler(config, expressionParser, elementSchemaRegistry, console), new DirectiveWrapperCompiler(config, expressionParser, elementSchemaRegistry, console),
new NgModuleCompiler(), new TypeScriptEmitter(importResolver), summaryResolver, new NgModuleCompiler(), new TypeScriptEmitter(importResolver), summaryResolver,
options.locale, options.i18nFormat, new AnimationParser(elementSchemaRegistry), options.locale, options.i18nFormat, new AnimationParser(elementSchemaRegistry),

View File

@ -11,4 +11,5 @@ export interface AotCompilerOptions {
locale?: string; locale?: string;
i18nFormat?: string; i18nFormat?: string;
translations?: string; translations?: string;
useViewEngine?: boolean;
} }

View File

@ -386,6 +386,25 @@ export class Identifiers {
member: 'createRendererTypeV2', member: 'createRendererTypeV2',
runtime: ɵviewEngine.createRendererTypeV2 runtime: ɵviewEngine.createRendererTypeV2
}; };
static RendererTypeV2: IdentifierSpec = {
name: 'RendererTypeV2',
moduleUrl: CORE,
// type only
runtime: null
};
static ViewDefinition: IdentifierSpec = {
name: 'ɵviewEngine',
moduleUrl: CORE,
member: 'ViewDefinition',
// type only
runtime: null
};
static createComponentFactory: IdentifierSpec = {
name: 'ɵviewEngine',
moduleUrl: CORE,
member: 'createComponentFactory',
runtime: ɵviewEngine.createComponentFactory
};
} }
export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string { export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string {

View File

@ -108,7 +108,10 @@ export class CompileMetadataResolver {
} }
private getDirectiveWrapperClass(dirType: any): StaticSymbol|cpl.ProxyClass { private getDirectiveWrapperClass(dirType: any): StaticSymbol|cpl.ProxyClass {
return this.getGeneratedClass(dirType, cpl.dirWrapperClassName(dirType)); if (!this._config.useViewEngine) {
return this.getGeneratedClass(dirType, cpl.dirWrapperClassName(dirType));
}
return null;
} }
private getComponentViewClass(dirType: any): StaticSymbol|cpl.ProxyClass { private getComponentViewClass(dirType: any): StaticSymbol|cpl.ProxyClass {

View File

@ -34,7 +34,7 @@ export enum BuiltinTypeName {
Int, Int,
Number, Number,
Function, Function,
Null Inferred
} }
export class BuiltinType extends Type { export class BuiltinType extends Type {
@ -66,12 +66,12 @@ export class MapType extends Type {
} }
export const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic); export const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic);
export const INFERRED_TYPE = new BuiltinType(BuiltinTypeName.Inferred);
export const BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool); export const BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool);
export const INT_TYPE = new BuiltinType(BuiltinTypeName.Int); export const INT_TYPE = new BuiltinType(BuiltinTypeName.Int);
export const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number); export const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
export const STRING_TYPE = new BuiltinType(BuiltinTypeName.String); export const STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
export const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function); export const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
export const NULL_TYPE = new BuiltinType(BuiltinTypeName.Null);
export interface TypeVisitor { export interface TypeVisitor {
visitBuiltintType(type: BuiltinType, context: any): any; visitBuiltintType(type: BuiltinType, context: any): any;
@ -493,7 +493,7 @@ export const SUPER_EXPR = new ReadVarExpr(BuiltinVar.Super);
export const CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError); export const CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError);
export const CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack); export const CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack);
export const NULL_EXPR = new LiteralExpr(null, null); export const NULL_EXPR = new LiteralExpr(null, null);
export const TYPED_NULL_EXPR = new LiteralExpr(null, NULL_TYPE); export const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE);
//// Statements //// Statements
export enum StmtModifier { export enum StmtModifier {

View File

@ -102,7 +102,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext): any { visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext): any {
const value = ast.value; const value = ast.value;
if (isBlank(value) && ast.type != o.NULL_TYPE) { if (isBlank(value) && ast.type != o.INFERRED_TYPE) {
ctx.print(ast, `(${value} as any)`); ctx.print(ast, `(${value} as any)`);
return null; return null;
} }
@ -152,8 +152,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
} else { } else {
ctx.print(stmt, `var`); ctx.print(stmt, `var`);
} }
ctx.print(stmt, ` ${stmt.name}:`); ctx.print(stmt, ` ${stmt.name}`);
this.visitType(stmt.type, ctx); this._printColonType(stmt.type, ctx);
ctx.print(stmt, ` = `); ctx.print(stmt, ` = `);
stmt.value.visitExpression(this, ctx); stmt.value.visitExpression(this, ctx);
ctx.println(stmt, `;`); ctx.println(stmt, `;`);
@ -212,8 +212,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
ctx.print(null, `/*private*/ `); ctx.print(null, `/*private*/ `);
} }
ctx.print(null, field.name); ctx.print(null, field.name);
ctx.print(null, ':'); this._printColonType(field.type, ctx);
this.visitType(field.type, ctx);
ctx.println(null, `;`); ctx.println(null, `;`);
} }
@ -222,8 +221,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
ctx.print(null, `private `); ctx.print(null, `private `);
} }
ctx.print(null, `get ${getter.name}()`); ctx.print(null, `get ${getter.name}()`);
ctx.print(null, ':'); this._printColonType(getter.type, ctx);
this.visitType(getter.type, ctx);
ctx.println(null, ` {`); ctx.println(null, ` {`);
ctx.incIndent(); ctx.incIndent();
this.visitAllStatements(getter.body, ctx); this.visitAllStatements(getter.body, ctx);
@ -247,8 +245,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
} }
ctx.print(null, `${method.name}(`); ctx.print(null, `${method.name}(`);
this._visitParams(method.params, ctx); this._visitParams(method.params, ctx);
ctx.print(null, `):`); ctx.print(null, `)`);
this.visitType(method.type, ctx, 'void'); this._printColonType(method.type, ctx, 'void');
ctx.println(null, ` {`); ctx.println(null, ` {`);
ctx.incIndent(); ctx.incIndent();
this.visitAllStatements(method.body, ctx); this.visitAllStatements(method.body, ctx);
@ -259,8 +257,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any { visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any {
ctx.print(ast, `(`); ctx.print(ast, `(`);
this._visitParams(ast.params, ctx); this._visitParams(ast.params, ctx);
ctx.print(ast, `):`); ctx.print(ast, `)`);
this.visitType(ast.type, ctx, 'void'); this._printColonType(ast.type, ctx, 'void');
ctx.println(ast, ` => {`); ctx.println(ast, ` => {`);
ctx.incIndent(); ctx.incIndent();
this.visitAllStatements(ast.statements, ctx); this.visitAllStatements(ast.statements, ctx);
@ -275,8 +273,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
} }
ctx.print(stmt, `function ${stmt.name}(`); ctx.print(stmt, `function ${stmt.name}(`);
this._visitParams(stmt.params, ctx); this._visitParams(stmt.params, ctx);
ctx.print(stmt, `):`); ctx.print(stmt, `)`);
this.visitType(stmt.type, ctx, 'void'); this._printColonType(stmt.type, ctx, 'void');
ctx.println(stmt, ` {`); ctx.println(stmt, ` {`);
ctx.incIndent(); ctx.incIndent();
this.visitAllStatements(stmt.statements, ctx); this.visitAllStatements(stmt.statements, ctx);
@ -369,8 +367,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void { private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void {
this.visitAllObjects(param => { this.visitAllObjects(param => {
ctx.print(null, param.name); ctx.print(null, param.name);
ctx.print(null, ':'); this._printColonType(param.type, ctx);
this.visitType(param.type, ctx);
}, params, ctx, ','); }, params, ctx, ',');
} }
@ -431,4 +428,11 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
} }
} }
} }
private _printColonType(type: o.Type, ctx: EmitterVisitorContext, defaultType?: string) {
if (type !== o.INFERRED_TYPE) {
ctx.print(null, ':');
this.visitType(type, ctx, defaultType);
}
}
} }

View File

@ -38,8 +38,6 @@ export class ViewCompilerNext extends ViewCompiler {
component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression, component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression,
usedPipes: CompilePipeSummary[], usedPipes: CompilePipeSummary[],
compiledAnimations: AnimationEntryCompileResult[]): ViewCompileResult { compiledAnimations: AnimationEntryCompileResult[]): ViewCompileResult {
const compName = identifierName(component.type) + (component.isHost ? `_Host` : '');
let embeddedViewCount = 0; let embeddedViewCount = 0;
const staticQueryIds = findStaticQueryIds(template); const staticQueryIds = findStaticQueryIds(template);
@ -56,13 +54,14 @@ export class ViewCompilerNext extends ViewCompiler {
new o.LiteralMapEntry('data', o.literalMap([])), new o.LiteralMapEntry('data', o.literalMap([])),
]) ])
])) ]))
.toDeclStmt()); .toDeclStmt(
o.importType(createIdentifier(Identifiers.RendererTypeV2)),
[o.StmtModifier.Final]));
const viewBuilderFactory = (parent: ViewBuilder): ViewBuilder => { const viewBuilderFactory = (parent: ViewBuilder): ViewBuilder => {
const embeddedViewIndex = embeddedViewCount++; const embeddedViewIndex = embeddedViewCount++;
const viewName = viewClassName(component.type.reference, embeddedViewIndex);
return new ViewBuilder( return new ViewBuilder(
parent, component, viewName, usedPipes, staticQueryIds, viewBuilderFactory); parent, component, embeddedViewIndex, usedPipes, staticQueryIds, viewBuilderFactory);
}; };
const visitor = viewBuilderFactory(null); const visitor = viewBuilderFactory(null);
@ -109,10 +108,14 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
constructor( constructor(
private parent: ViewBuilder, private component: CompileDirectiveMetadata, private parent: ViewBuilder, private component: CompileDirectiveMetadata,
public viewName: string, private usedPipes: CompilePipeSummary[], private embeddedViewIndex: number, private usedPipes: CompilePipeSummary[],
private staticQueryIds: Map<TemplateAst, StaticAndDynamicQueryIds>, private staticQueryIds: Map<TemplateAst, StaticAndDynamicQueryIds>,
private viewBuilderFactory: ViewBuilderFactory) {} private viewBuilderFactory: ViewBuilderFactory) {}
get viewName(): string {
return viewClassName(this.component.type.reference, this.embeddedViewIndex);
}
visitAll(variables: VariableAst[], astNodes: TemplateAst[]) { visitAll(variables: VariableAst[], astNodes: TemplateAst[]) {
this.variables = variables; this.variables = variables;
// create the pipes for the pure pipes immediately, so that we know their indices. // create the pipes for the pure pipes immediately, so that we know their indices.
@ -155,7 +158,11 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
} }
build(targetStatements: o.Statement[] = []): o.Statement[] { build(targetStatements: o.Statement[] = []): o.Statement[] {
const compType = o.importType(this.component.type); // TODO(tbosch): The old view compiler used to use an `any` type
// for the context in any embedded view. We keep this behaivor for now
// to be able to introduce the new view compiler without too many errors.
const compType =
this.embeddedViewIndex > 0 ? o.DYNAMIC_TYPE : o.importType(this.component.type);
this.children.forEach((child) => child.build(targetStatements)); this.children.forEach((child) => child.build(targetStatements));
const updateDirectivesFn = this._createUpdateFn(this.updateDirectivesExpressions, compType); const updateDirectivesFn = this._createUpdateFn(this.updateDirectivesExpressions, compType);
@ -180,16 +187,20 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
}); });
let handleEventFn: o.Expression; let handleEventFn: o.Expression;
if (handleEventStmts.length > 0) { if (handleEventStmts.length > 0) {
const preStmts: o.Statement[] =
[ALLOW_DEFAULT_VAR.set(o.literal(true)).toDeclStmt(o.BOOL_TYPE)];
if (!this.component.isHost) {
preStmts.push(COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(compType));
}
handleEventFn = o.fn( handleEventFn = o.fn(
[ [
new o.FnParam(VIEW_VAR.name), new o.FnParam(NODE_INDEX_VAR.name), new o.FnParam(VIEW_VAR.name, o.INFERRED_TYPE),
new o.FnParam(EVENT_NAME_VAR.name), new o.FnParam(EventHandlerVars.event.name) new o.FnParam(NODE_INDEX_VAR.name, o.INFERRED_TYPE),
new o.FnParam(EVENT_NAME_VAR.name, o.INFERRED_TYPE),
new o.FnParam(EventHandlerVars.event.name, o.INFERRED_TYPE)
], ],
[ [...preStmts, ...handleEventStmts, new o.ReturnStatement(ALLOW_DEFAULT_VAR)],
ALLOW_DEFAULT_VAR.set(o.literal(true)).toDeclStmt(o.BOOL_TYPE), o.INFERRED_TYPE);
COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(compType), ...handleEventStmts,
new o.ReturnStatement(ALLOW_DEFAULT_VAR)
]);
} else { } else {
handleEventFn = o.NULL_EXPR; handleEventFn = o.NULL_EXPR;
} }
@ -203,7 +214,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
[new o.ReturnStatement(o.importExpr(createIdentifier(Identifiers.viewDef)).callFn([ [new o.ReturnStatement(o.importExpr(createIdentifier(Identifiers.viewDef)).callFn([
o.literal(viewFlags), o.literalArr(this.nodeDefs), updateDirectivesFn, updateRendererFn, o.literal(viewFlags), o.literalArr(this.nodeDefs), updateDirectivesFn, updateRendererFn,
handleEventFn handleEventFn
]))]); ]))],
o.importType(createIdentifier(Identifiers.ViewDefinition)));
targetStatements.push(viewFactory); targetStatements.push(viewFactory);
return targetStatements; return targetStatements;
@ -225,9 +237,16 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
}); });
let updateFn: o.Expression; let updateFn: o.Expression;
if (updateStmts.length > 0) { if (updateStmts.length > 0) {
const preStmts: o.Statement[] = [];
if (!this.component.isHost) {
preStmts.push(COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(compType));
}
updateFn = o.fn( updateFn = o.fn(
[new o.FnParam(CHECK_VAR.name), new o.FnParam(VIEW_VAR.name)], [
[COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(compType), ...updateStmts]); new o.FnParam(CHECK_VAR.name, o.INFERRED_TYPE),
new o.FnParam(VIEW_VAR.name, o.INFERRED_TYPE)
],
[...preStmts, ...updateStmts], o.INFERRED_TYPE);
} else { } else {
updateFn = o.NULL_EXPR; updateFn = o.NULL_EXPR;
} }
@ -306,7 +325,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter
let outputDefs: o.Expression[] = []; let outputDefs: o.Expression[] = [];
if (elName) { if (elName) {
ast.inputs.forEach( ast.inputs.forEach(
(inputAst) => { hostBindings.push({context: COMP_VAR, value: inputAst.value}); }); (inputAst) => hostBindings.push({context: COMP_VAR, value: inputAst.value}));
if (hostBindings.length) { if (hostBindings.length) {
this._addUpdateExpressions(nodeIndex, hostBindings, this.updateRendererExpressions); this._addUpdateExpressions(nodeIndex, hostBindings, this.updateRendererExpressions);
} }
@ -760,7 +779,8 @@ function multiProviderDef(providers: CompileProviderMetadata[]):
} }
return expr; return expr;
}); });
const providerExpr = o.fn(allParams, [new o.ReturnStatement(o.literalArr(exprs))]); const providerExpr =
o.fn(allParams, [new o.ReturnStatement(o.literalArr(exprs))], o.INFERRED_TYPE);
return { return {
providerExpr, providerExpr,
providerType: viewEngine.ProviderType.Factory, providerType: viewEngine.ProviderType.Factory,
@ -880,6 +900,11 @@ function elementBindingDefs(inputAsts: BoundElementPropertyAst[]): o.Expression[
o.literal(viewEngine.BindingType.ElementProperty), o.literal(inputAst.name), o.literal(viewEngine.BindingType.ElementProperty), o.literal(inputAst.name),
o.literal(inputAst.securityContext) o.literal(inputAst.securityContext)
]); ]);
case PropertyBindingType.Animation:
return o.literalArr([
o.literal(viewEngine.BindingType.ElementProperty), o.literal(inputAst.name),
o.literal(inputAst.securityContext)
]);
case PropertyBindingType.Class: case PropertyBindingType.Class:
return o.literalArr( return o.literalArr(
[o.literal(viewEngine.BindingType.ElementClass), o.literal(inputAst.name)]); [o.literal(viewEngine.BindingType.ElementClass), o.literal(inputAst.name)]);

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {AotCompiler, AotCompilerHost, createAotCompiler} from '@angular/compiler'; import {AotCompiler, AotCompilerHost, AotCompilerOptions, createAotCompiler} from '@angular/compiler';
import {RenderComponentType} from '@angular/core'; import {RenderComponentType} from '@angular/core';
import {async} from '@angular/core/testing'; import {async} from '@angular/core/testing';
import {MetadataBundler, MetadataCollector, ModuleMetadata, privateEntriesToIndex} from '@angular/tsc-wrapped'; import {MetadataBundler, MetadataCollector, ModuleMetadata, privateEntriesToIndex} from '@angular/tsc-wrapped';
@ -117,6 +117,19 @@ describe('compiler (bundled Angular)', () => {
expect(generatedFiles.find(f => /app\.module\.ngfactory\.ts/.test(f.genFileUrl))) expect(generatedFiles.find(f => /app\.module\.ngfactory\.ts/.test(f.genFileUrl)))
.toBeDefined(); .toBeDefined();
}))); })));
it('should compile with view engine',
async(() => compile(host, aotHost, expectNoDiagnostics, undefined, {
useViewEngine: true
}).then(generatedFiles => {
const genCompFile =
generatedFiles.find(f => /app\.component\.ngfactory\.ts/.test(f.genFileUrl));
expect(genCompFile).toBeDefined();
expect(genCompFile.source).toContain('viewDef');
expect(genCompFile.source).not.toContain('AppView');
expect(generatedFiles.find(f => /app\.module\.ngfactory\.ts/.test(f.genFileUrl)))
.toBeDefined();
})));
}); });
}); });
@ -203,11 +216,12 @@ function summaryCompile(
function compile( function compile(
host: MockCompilerHost, aotHost: AotCompilerHost, preCompile?: (program: ts.Program) => void, host: MockCompilerHost, aotHost: AotCompilerHost, preCompile?: (program: ts.Program) => void,
postCompile: (program: ts.Program) => void = expectNoDiagnostics) { postCompile: (program: ts.Program) => void = expectNoDiagnostics,
options: AotCompilerOptions = {}) {
const scripts = host.scriptNames.slice(0); const scripts = host.scriptNames.slice(0);
const program = ts.createProgram(scripts, settings, host); const program = ts.createProgram(scripts, settings, host);
if (preCompile) preCompile(program); if (preCompile) preCompile(program);
const {compiler, reflector} = createAotCompiler(aotHost, {}); const {compiler, reflector} = createAotCompiler(aotHost, options);
return compiler.compileAll(program.getSourceFiles().map(sf => sf.fileName)) return compiler.compileAll(program.getSourceFiles().map(sf => sf.fileName))
.then(generatedFiles => { .then(generatedFiles => {
generatedFiles.forEach( generatedFiles.forEach(

View File

@ -63,6 +63,8 @@ export function main() {
.toEqual(`export var someVar:any = 1;`); .toEqual(`export var someVar:any = 1;`);
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(o.INT_TYPE))) expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(o.INT_TYPE)))
.toEqual(`var someVar:number = 1;`); .toEqual(`var someVar:number = 1;`);
expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(o.INFERRED_TYPE)))
.toEqual(`var someVar = 1;`);
}); });
describe('declare variables with ExternExpressions as values', () => { describe('declare variables with ExternExpressions as values', () => {

View File

@ -27,7 +27,7 @@ import {ComponentFactory, ComponentRef} from './linker/component_factory';
import {ComponentFactoryResolver} from './linker/component_factory_resolver'; import {ComponentFactoryResolver} from './linker/component_factory_resolver';
import {NgModuleFactory, NgModuleInjector, NgModuleRef} from './linker/ng_module_factory'; import {NgModuleFactory, NgModuleInjector, NgModuleRef} from './linker/ng_module_factory';
import {AppView} from './linker/view'; import {AppView} from './linker/view';
import {ViewRef, ViewRef_} from './linker/view_ref'; import {InternalViewRef, ViewRef} from './linker/view_ref';
import {WtfScopeFn, wtfCreateScope, wtfLeave} from './profile/profile'; import {WtfScopeFn, wtfCreateScope, wtfLeave} from './profile/profile';
import {Testability, TestabilityRegistry} from './testability/testability'; import {Testability, TestabilityRegistry} from './testability/testability';
import {Type} from './type'; import {Type} from './type';
@ -424,7 +424,7 @@ export class ApplicationRef_ extends ApplicationRef {
private _bootstrapListeners: ((compRef: ComponentRef<any>) => void)[] = []; private _bootstrapListeners: ((compRef: ComponentRef<any>) => void)[] = [];
private _rootComponents: ComponentRef<any>[] = []; private _rootComponents: ComponentRef<any>[] = [];
private _rootComponentTypes: Type<any>[] = []; private _rootComponentTypes: Type<any>[] = [];
private _views: AppView<any>[] = []; private _views: InternalViewRef[] = [];
private _runningTick: boolean = false; private _runningTick: boolean = false;
private _enforceNoNewChanges: boolean = false; private _enforceNoNewChanges: boolean = false;
private _isStable: Observable<boolean>; private _isStable: Observable<boolean>;
@ -485,15 +485,15 @@ export class ApplicationRef_ extends ApplicationRef {
} }
attachView(viewRef: ViewRef): void { attachView(viewRef: ViewRef): void {
const view = (viewRef as ViewRef_<any>).internalView; const view = (viewRef as InternalViewRef);
this._views.push(view); this._views.push(view);
view.attachToAppRef(this); view.attachToAppRef(this);
} }
detachView(viewRef: ViewRef): void { detachView(viewRef: ViewRef): void {
const view = (viewRef as ViewRef_<any>).internalView; const view = (viewRef as InternalViewRef);
ListWrapper.remove(this._views, view); ListWrapper.remove(this._views, view);
view.detach(); view.detachFromContainer();
} }
bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>): ComponentRef<C> { bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>): ComponentRef<C> {
@ -547,9 +547,9 @@ export class ApplicationRef_ extends ApplicationRef {
const scope = ApplicationRef_._tickScope(); const scope = ApplicationRef_._tickScope();
try { try {
this._runningTick = true; this._runningTick = true;
this._views.forEach((view) => view.ref.detectChanges()); this._views.forEach((view) => view.detectChanges());
if (this._enforceNoNewChanges) { if (this._enforceNoNewChanges) {
this._views.forEach((view) => view.ref.checkNoChanges()); this._views.forEach((view) => view.checkNoChanges());
} }
} finally { } finally {
this._runningTick = false; this._runningTick = false;

View File

@ -7,10 +7,13 @@
*/ */
import {AnimationQueue} from '../animation/animation_queue'; import {AnimationQueue} from '../animation/animation_queue';
import {ApplicationRef} from '../application_ref';
import {ChangeDetectorRef} from '../change_detection/change_detector_ref'; import {ChangeDetectorRef} from '../change_detection/change_detector_ref';
import {ChangeDetectorStatus} from '../change_detection/constants'; import {ChangeDetectorStatus} from '../change_detection/constants';
import {AppView} from './view'; import {AppView} from './view';
/** /**
* @stable * @stable
*/ */
@ -85,7 +88,12 @@ export abstract class EmbeddedViewRef<C> extends ViewRef {
abstract get rootNodes(): any[]; abstract get rootNodes(): any[];
} }
export class ViewRef_<C> implements EmbeddedViewRef<C>, ChangeDetectorRef { export interface InternalViewRef extends ViewRef {
detachFromContainer(): void;
attachToAppRef(appRef: ApplicationRef): void;
}
export class ViewRef_<C> implements EmbeddedViewRef<C>, ChangeDetectorRef, InternalViewRef {
/** @internal */ /** @internal */
_originalMode: ChangeDetectorStatus; _originalMode: ChangeDetectorStatus;
@ -122,4 +130,8 @@ export class ViewRef_<C> implements EmbeddedViewRef<C>, ChangeDetectorRef {
} }
destroy() { this._view.detachAndDestroy(); } destroy() { this._view.detachAndDestroy(); }
detachFromContainer() { this._view.detach(); }
attachToAppRef(appRef: ApplicationRef) { this._view.attachToAppRef(appRef); }
} }

View File

@ -14,7 +14,7 @@ import {ComponentFactory, ComponentRef} from '../linker/component_factory';
import {ElementRef} from '../linker/element_ref'; import {ElementRef} from '../linker/element_ref';
import {TemplateRef} from '../linker/template_ref'; import {TemplateRef} from '../linker/template_ref';
import {ViewContainerRef} from '../linker/view_container_ref'; import {ViewContainerRef} from '../linker/view_container_ref';
import {EmbeddedViewRef, ViewRef} from '../linker/view_ref'; import {EmbeddedViewRef, InternalViewRef, ViewRef} from '../linker/view_ref';
import {Renderer as RendererV1, RendererV2} from '../render/api'; import {Renderer as RendererV1, RendererV2} from '../render/api';
import {Type} from '../type'; import {Type} from '../type';
import {VERSION} from '../version'; import {VERSION} from '../version';
@ -162,7 +162,7 @@ export function createChangeDetectorRef(view: ViewData): ChangeDetectorRef {
return new ViewRef_(view); return new ViewRef_(view);
} }
export class ViewRef_ implements EmbeddedViewRef<any> { export class ViewRef_ implements EmbeddedViewRef<any>, InternalViewRef {
/** @internal */ /** @internal */
_view: ViewData; _view: ViewData;
private _viewContainerRef: ViewContainerRef; private _viewContainerRef: ViewContainerRef;

View File

@ -1333,7 +1333,6 @@ function declareTests({useJit, viewEngine}: {useJit: boolean, viewEngine: boolea
expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('INPUT'); expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('INPUT');
expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV'); expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV');
expect((<Injector>c.injector).get).toBeTruthy(); expect((<Injector>c.injector).get).toBeTruthy();
expect(c.source).toContain(':0:7');
expect(c.context).toBe(fixture.componentInstance); expect(c.context).toBe(fixture.componentInstance);
expect(c.references['local']).toBeDefined(); expect(c.references['local']).toBeDefined();
} }
@ -1351,7 +1350,6 @@ function declareTests({useJit, viewEngine}: {useJit: boolean, viewEngine: boolea
} catch (e) { } catch (e) {
const c = getDebugContext(e); const c = getDebugContext(e);
expect(c.renderNode).toBeTruthy(); expect(c.renderNode).toBeTruthy();
expect(c.source).toContain(':0:5');
} }
}); });