From 58ba4f0409fa1504e9974a0f13018844f87ee86f Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Fri, 17 Feb 2017 08:56:49 -0800 Subject: [PATCH] fix(compiler): make view engine work with Aot --- modules/@angular/compiler/index.ts | 1 + modules/@angular/compiler/src/aot/compiler.ts | 57 +++++++++++------ .../compiler/src/aot/compiler_factory.ts | 9 ++- .../compiler/src/aot/compiler_options.ts | 1 + modules/@angular/compiler/src/identifiers.ts | 19 ++++++ .../compiler/src/metadata_resolver.ts | 5 +- .../compiler/src/output/output_ast.ts | 6 +- .../compiler/src/output/ts_emitter.ts | 34 +++++----- .../src/view_compiler_next/view_compiler.ts | 63 +++++++++++++------ .../compiler/test/aot/compiler_spec.ts | 20 +++++- .../compiler/test/output/ts_emitter_spec.ts | 2 + modules/@angular/core/src/application_ref.ts | 14 ++--- modules/@angular/core/src/linker/view_ref.ts | 14 ++++- modules/@angular/core/src/view/refs.ts | 4 +- .../core/test/linker/integration_spec.ts | 2 - 15 files changed, 176 insertions(+), 75 deletions(-) diff --git a/modules/@angular/compiler/index.ts b/modules/@angular/compiler/index.ts index 9b560c25fe..34feab50a4 100644 --- a/modules/@angular/compiler/index.ts +++ b/modules/@angular/compiler/index.ts @@ -28,6 +28,7 @@ export {CompilerConfig, RenderTypes} from './src/config'; export * from './src/compile_metadata'; export * from './src/aot/compiler_factory'; export * from './src/aot/compiler'; +export * from './src/aot/compiler_options'; export * from './src/aot/compiler_host'; export * from './src/aot/static_reflector'; export * from './src/aot/static_reflection_capabilities'; diff --git a/modules/@angular/compiler/src/aot/compiler.ts b/modules/@angular/compiler/src/aot/compiler.ts index 7c9bdb799e..a0ec19cb91 100644 --- a/modules/@angular/compiler/src/aot/compiler.ts +++ b/modules/@angular/compiler/src/aot/compiler.ts @@ -9,6 +9,7 @@ import {AnimationCompiler} from '../animation/animation_compiler'; import {AnimationParser} from '../animation/animation_parser'; import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, componentFactoryName, createHostComponentMeta, identifierName} from '../compile_metadata'; +import {CompilerConfig} from '../config'; import {DirectiveWrapperCompiler} from '../directive_wrapper_compiler'; import {ListWrapper} from '../facade/collection'; import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers'; @@ -33,9 +34,10 @@ export class AotCompiler { private _animationCompiler = new AnimationCompiler(); constructor( - private _host: AotCompilerHost, private _metadataResolver: CompileMetadataResolver, - private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler, - private _viewCompiler: ViewCompiler, private _dirWrapperCompiler: DirectiveWrapperCompiler, + private _config: CompilerConfig, private _host: AotCompilerHost, + private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser, + private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler, + private _dirWrapperCompiler: DirectiveWrapperCompiler, private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter, private _summaryResolver: SummaryResolver, private _localeId: string, private _translationFormat: string, private _animationParser: AnimationParser, @@ -77,8 +79,10 @@ export class AotCompiler { ...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements))); // compile directive wrappers - exportedVars.push(...directives.map( - (directiveType) => this._compileDirectiveWrapper(directiveType, statements))); + if (!this._config.useViewEngine) { + exportedVars.push(...directives.map( + (directiveType) => this._compileDirectiveWrapper(directiveType, statements))); + } // compile components directives.forEach((dirType) => { @@ -181,20 +185,35 @@ export class AotCompiler { hostMeta, ngModule, [compMeta.type], null, fileSuffix, targetStatements) .viewClassVar; const compFactoryVar = componentFactoryName(compMeta.type.reference); - 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])); + if (this._config.useViewEngine) { + targetStatements.push( + o.variable(compFactoryVar) + .set(o.importExpr(createIdentifier(Identifiers.createComponentFactory)).callFn([ + o.literal(compMeta.selector), + o.importExpr(compMeta.type), + o.variable(hostViewFactoryVar), + ])) + .toDeclStmt( + o.importType( + createIdentifier(Identifiers.ComponentFactory), [o.importType(compMeta.type)], + [o.TypeModifier.Const]), + [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; } diff --git a/modules/@angular/compiler/src/aot/compiler_factory.ts b/modules/@angular/compiler/src/aot/compiler_factory.ts index 3a5c002da0..656c4d0f2c 100644 --- a/modules/@angular/compiler/src/aot/compiler_factory.ts +++ b/modules/@angular/compiler/src/aot/compiler_factory.ts @@ -28,6 +28,7 @@ import {StyleCompiler} from '../style_compiler'; import {TemplateParser} from '../template_parser/template_parser'; import {createOfflineCompileUrlResolver} from '../url_resolver'; import {ViewCompiler} from '../view_compiler/view_compiler'; +import {ViewCompilerNext} from '../view_compiler_next/view_compiler'; import {AotCompiler} from './compiler'; import {AotCompilerHost} from './compiler_host'; @@ -61,7 +62,8 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom genDebugInfo: options.debug === true, defaultEncapsulation: ViewEncapsulation.Emulated, logBindingUpdate: false, - useJit: false + useJit: false, + useViewEngine: options.useViewEngine }); const normalizer = new DirectiveNormalizer( {get: (url: string) => compilerHost.loadResource(url)}, urlResolver, htmlParser, config); @@ -80,9 +82,10 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom compilerHost.fileNameToModuleName(fileName, containingFilePath), getTypeArity: (symbol: StaticSymbol) => symbolResolver.getTypeArity(symbol) }; + const viewCompiler = config.useViewEngine ? new ViewCompilerNext(config, elementSchemaRegistry) : + new ViewCompiler(config, elementSchemaRegistry); const compiler = new AotCompiler( - compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), - new ViewCompiler(config, elementSchemaRegistry), + config, compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), viewCompiler, new DirectiveWrapperCompiler(config, expressionParser, elementSchemaRegistry, console), new NgModuleCompiler(), new TypeScriptEmitter(importResolver), summaryResolver, options.locale, options.i18nFormat, new AnimationParser(elementSchemaRegistry), diff --git a/modules/@angular/compiler/src/aot/compiler_options.ts b/modules/@angular/compiler/src/aot/compiler_options.ts index c52fadc557..331b319c71 100644 --- a/modules/@angular/compiler/src/aot/compiler_options.ts +++ b/modules/@angular/compiler/src/aot/compiler_options.ts @@ -11,4 +11,5 @@ export interface AotCompilerOptions { locale?: string; i18nFormat?: string; translations?: string; + useViewEngine?: boolean; } diff --git a/modules/@angular/compiler/src/identifiers.ts b/modules/@angular/compiler/src/identifiers.ts index 3398de93a2..06b021ff1e 100644 --- a/modules/@angular/compiler/src/identifiers.ts +++ b/modules/@angular/compiler/src/identifiers.ts @@ -386,6 +386,25 @@ export class Identifiers { member: '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 { diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index cb22e95922..a7c7603033 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -108,7 +108,10 @@ export class CompileMetadataResolver { } 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 { diff --git a/modules/@angular/compiler/src/output/output_ast.ts b/modules/@angular/compiler/src/output/output_ast.ts index 964700adef..30b7134937 100644 --- a/modules/@angular/compiler/src/output/output_ast.ts +++ b/modules/@angular/compiler/src/output/output_ast.ts @@ -34,7 +34,7 @@ export enum BuiltinTypeName { Int, Number, Function, - Null + Inferred } export class BuiltinType extends Type { @@ -66,12 +66,12 @@ export class MapType extends Type { } 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 INT_TYPE = new BuiltinType(BuiltinTypeName.Int); export const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number); export const STRING_TYPE = new BuiltinType(BuiltinTypeName.String); export const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function); -export const NULL_TYPE = new BuiltinType(BuiltinTypeName.Null); export interface TypeVisitor { 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_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack); 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 export enum StmtModifier { diff --git a/modules/@angular/compiler/src/output/ts_emitter.ts b/modules/@angular/compiler/src/output/ts_emitter.ts index 42d32fdc63..7846655ce7 100644 --- a/modules/@angular/compiler/src/output/ts_emitter.ts +++ b/modules/@angular/compiler/src/output/ts_emitter.ts @@ -102,7 +102,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor visitLiteralExpr(ast: o.LiteralExpr, ctx: EmitterVisitorContext): any { 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)`); return null; } @@ -152,8 +152,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor } else { ctx.print(stmt, `var`); } - ctx.print(stmt, ` ${stmt.name}:`); - this.visitType(stmt.type, ctx); + ctx.print(stmt, ` ${stmt.name}`); + this._printColonType(stmt.type, ctx); ctx.print(stmt, ` = `); stmt.value.visitExpression(this, ctx); ctx.println(stmt, `;`); @@ -212,8 +212,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor ctx.print(null, `/*private*/ `); } ctx.print(null, field.name); - ctx.print(null, ':'); - this.visitType(field.type, ctx); + this._printColonType(field.type, ctx); ctx.println(null, `;`); } @@ -222,8 +221,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor ctx.print(null, `private `); } ctx.print(null, `get ${getter.name}()`); - ctx.print(null, ':'); - this.visitType(getter.type, ctx); + this._printColonType(getter.type, ctx); ctx.println(null, ` {`); ctx.incIndent(); this.visitAllStatements(getter.body, ctx); @@ -247,8 +245,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor } ctx.print(null, `${method.name}(`); this._visitParams(method.params, ctx); - ctx.print(null, `):`); - this.visitType(method.type, ctx, 'void'); + ctx.print(null, `)`); + this._printColonType(method.type, ctx, 'void'); ctx.println(null, ` {`); ctx.incIndent(); this.visitAllStatements(method.body, ctx); @@ -259,8 +257,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor visitFunctionExpr(ast: o.FunctionExpr, ctx: EmitterVisitorContext): any { ctx.print(ast, `(`); this._visitParams(ast.params, ctx); - ctx.print(ast, `):`); - this.visitType(ast.type, ctx, 'void'); + ctx.print(ast, `)`); + this._printColonType(ast.type, ctx, 'void'); ctx.println(ast, ` => {`); ctx.incIndent(); this.visitAllStatements(ast.statements, ctx); @@ -275,8 +273,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor } ctx.print(stmt, `function ${stmt.name}(`); this._visitParams(stmt.params, ctx); - ctx.print(stmt, `):`); - this.visitType(stmt.type, ctx, 'void'); + ctx.print(stmt, `)`); + this._printColonType(stmt.type, ctx, 'void'); ctx.println(stmt, ` {`); ctx.incIndent(); this.visitAllStatements(stmt.statements, ctx); @@ -369,8 +367,7 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor private _visitParams(params: o.FnParam[], ctx: EmitterVisitorContext): void { this.visitAllObjects(param => { ctx.print(null, param.name); - ctx.print(null, ':'); - this.visitType(param.type, ctx); + this._printColonType(param.type, 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); + } + } } diff --git a/modules/@angular/compiler/src/view_compiler_next/view_compiler.ts b/modules/@angular/compiler/src/view_compiler_next/view_compiler.ts index 5683ffa6dd..9c70dd44ab 100644 --- a/modules/@angular/compiler/src/view_compiler_next/view_compiler.ts +++ b/modules/@angular/compiler/src/view_compiler_next/view_compiler.ts @@ -38,8 +38,6 @@ export class ViewCompilerNext extends ViewCompiler { component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression, usedPipes: CompilePipeSummary[], compiledAnimations: AnimationEntryCompileResult[]): ViewCompileResult { - const compName = identifierName(component.type) + (component.isHost ? `_Host` : ''); - let embeddedViewCount = 0; const staticQueryIds = findStaticQueryIds(template); @@ -56,13 +54,14 @@ export class ViewCompilerNext extends ViewCompiler { new o.LiteralMapEntry('data', o.literalMap([])), ]) ])) - .toDeclStmt()); + .toDeclStmt( + o.importType(createIdentifier(Identifiers.RendererTypeV2)), + [o.StmtModifier.Final])); const viewBuilderFactory = (parent: ViewBuilder): ViewBuilder => { const embeddedViewIndex = embeddedViewCount++; - const viewName = viewClassName(component.type.reference, embeddedViewIndex); return new ViewBuilder( - parent, component, viewName, usedPipes, staticQueryIds, viewBuilderFactory); + parent, component, embeddedViewIndex, usedPipes, staticQueryIds, viewBuilderFactory); }; const visitor = viewBuilderFactory(null); @@ -109,10 +108,14 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter constructor( private parent: ViewBuilder, private component: CompileDirectiveMetadata, - public viewName: string, private usedPipes: CompilePipeSummary[], + private embeddedViewIndex: number, private usedPipes: CompilePipeSummary[], private staticQueryIds: Map, private viewBuilderFactory: ViewBuilderFactory) {} + get viewName(): string { + return viewClassName(this.component.type.reference, this.embeddedViewIndex); + } + visitAll(variables: VariableAst[], astNodes: TemplateAst[]) { this.variables = variables; // 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[] { - 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)); const updateDirectivesFn = this._createUpdateFn(this.updateDirectivesExpressions, compType); @@ -180,16 +187,20 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter }); let handleEventFn: o.Expression; 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( [ - new o.FnParam(VIEW_VAR.name), new o.FnParam(NODE_INDEX_VAR.name), - new o.FnParam(EVENT_NAME_VAR.name), new o.FnParam(EventHandlerVars.event.name) + new o.FnParam(VIEW_VAR.name, o.INFERRED_TYPE), + 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) ], - [ - ALLOW_DEFAULT_VAR.set(o.literal(true)).toDeclStmt(o.BOOL_TYPE), - COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(compType), ...handleEventStmts, - new o.ReturnStatement(ALLOW_DEFAULT_VAR) - ]); + [...preStmts, ...handleEventStmts, new o.ReturnStatement(ALLOW_DEFAULT_VAR)], + o.INFERRED_TYPE); } else { handleEventFn = o.NULL_EXPR; } @@ -203,7 +214,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter [new o.ReturnStatement(o.importExpr(createIdentifier(Identifiers.viewDef)).callFn([ o.literal(viewFlags), o.literalArr(this.nodeDefs), updateDirectivesFn, updateRendererFn, handleEventFn - ]))]); + ]))], + o.importType(createIdentifier(Identifiers.ViewDefinition))); targetStatements.push(viewFactory); return targetStatements; @@ -225,9 +237,16 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter }); let updateFn: o.Expression; 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( - [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 { updateFn = o.NULL_EXPR; } @@ -306,7 +325,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver, BuiltinConverter let outputDefs: o.Expression[] = []; if (elName) { ast.inputs.forEach( - (inputAst) => { hostBindings.push({context: COMP_VAR, value: inputAst.value}); }); + (inputAst) => hostBindings.push({context: COMP_VAR, value: inputAst.value})); if (hostBindings.length) { this._addUpdateExpressions(nodeIndex, hostBindings, this.updateRendererExpressions); } @@ -760,7 +779,8 @@ function multiProviderDef(providers: CompileProviderMetadata[]): } 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 { providerExpr, 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(inputAst.securityContext) ]); + case PropertyBindingType.Animation: + return o.literalArr([ + o.literal(viewEngine.BindingType.ElementProperty), o.literal(inputAst.name), + o.literal(inputAst.securityContext) + ]); case PropertyBindingType.Class: return o.literalArr( [o.literal(viewEngine.BindingType.ElementClass), o.literal(inputAst.name)]); diff --git a/modules/@angular/compiler/test/aot/compiler_spec.ts b/modules/@angular/compiler/test/aot/compiler_spec.ts index 8196a6c04c..923757eefe 100644 --- a/modules/@angular/compiler/test/aot/compiler_spec.ts +++ b/modules/@angular/compiler/test/aot/compiler_spec.ts @@ -6,7 +6,7 @@ * 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 {async} from '@angular/core/testing'; 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))) .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( 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 program = ts.createProgram(scripts, settings, host); if (preCompile) preCompile(program); - const {compiler, reflector} = createAotCompiler(aotHost, {}); + const {compiler, reflector} = createAotCompiler(aotHost, options); return compiler.compileAll(program.getSourceFiles().map(sf => sf.fileName)) .then(generatedFiles => { generatedFiles.forEach( diff --git a/modules/@angular/compiler/test/output/ts_emitter_spec.ts b/modules/@angular/compiler/test/output/ts_emitter_spec.ts index fb3ee21bd3..4c0018ff63 100644 --- a/modules/@angular/compiler/test/output/ts_emitter_spec.ts +++ b/modules/@angular/compiler/test/output/ts_emitter_spec.ts @@ -63,6 +63,8 @@ export function main() { .toEqual(`export var someVar:any = 1;`); expect(emitStmt(someVar.set(o.literal(1)).toDeclStmt(o.INT_TYPE))) .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', () => { diff --git a/modules/@angular/core/src/application_ref.ts b/modules/@angular/core/src/application_ref.ts index d84ec4d89e..f94ecc2e41 100644 --- a/modules/@angular/core/src/application_ref.ts +++ b/modules/@angular/core/src/application_ref.ts @@ -27,7 +27,7 @@ import {ComponentFactory, ComponentRef} from './linker/component_factory'; import {ComponentFactoryResolver} from './linker/component_factory_resolver'; import {NgModuleFactory, NgModuleInjector, NgModuleRef} from './linker/ng_module_factory'; 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 {Testability, TestabilityRegistry} from './testability/testability'; import {Type} from './type'; @@ -424,7 +424,7 @@ export class ApplicationRef_ extends ApplicationRef { private _bootstrapListeners: ((compRef: ComponentRef) => void)[] = []; private _rootComponents: ComponentRef[] = []; private _rootComponentTypes: Type[] = []; - private _views: AppView[] = []; + private _views: InternalViewRef[] = []; private _runningTick: boolean = false; private _enforceNoNewChanges: boolean = false; private _isStable: Observable; @@ -485,15 +485,15 @@ export class ApplicationRef_ extends ApplicationRef { } attachView(viewRef: ViewRef): void { - const view = (viewRef as ViewRef_).internalView; + const view = (viewRef as InternalViewRef); this._views.push(view); view.attachToAppRef(this); } detachView(viewRef: ViewRef): void { - const view = (viewRef as ViewRef_).internalView; + const view = (viewRef as InternalViewRef); ListWrapper.remove(this._views, view); - view.detach(); + view.detachFromContainer(); } bootstrap(componentOrFactory: ComponentFactory|Type): ComponentRef { @@ -547,9 +547,9 @@ export class ApplicationRef_ extends ApplicationRef { const scope = ApplicationRef_._tickScope(); try { this._runningTick = true; - this._views.forEach((view) => view.ref.detectChanges()); + this._views.forEach((view) => view.detectChanges()); if (this._enforceNoNewChanges) { - this._views.forEach((view) => view.ref.checkNoChanges()); + this._views.forEach((view) => view.checkNoChanges()); } } finally { this._runningTick = false; diff --git a/modules/@angular/core/src/linker/view_ref.ts b/modules/@angular/core/src/linker/view_ref.ts index 1df1318bf9..bceff42160 100644 --- a/modules/@angular/core/src/linker/view_ref.ts +++ b/modules/@angular/core/src/linker/view_ref.ts @@ -7,10 +7,13 @@ */ import {AnimationQueue} from '../animation/animation_queue'; +import {ApplicationRef} from '../application_ref'; import {ChangeDetectorRef} from '../change_detection/change_detector_ref'; import {ChangeDetectorStatus} from '../change_detection/constants'; + import {AppView} from './view'; + /** * @stable */ @@ -85,7 +88,12 @@ export abstract class EmbeddedViewRef extends ViewRef { abstract get rootNodes(): any[]; } -export class ViewRef_ implements EmbeddedViewRef, ChangeDetectorRef { +export interface InternalViewRef extends ViewRef { + detachFromContainer(): void; + attachToAppRef(appRef: ApplicationRef): void; +} + +export class ViewRef_ implements EmbeddedViewRef, ChangeDetectorRef, InternalViewRef { /** @internal */ _originalMode: ChangeDetectorStatus; @@ -122,4 +130,8 @@ export class ViewRef_ implements EmbeddedViewRef, ChangeDetectorRef { } destroy() { this._view.detachAndDestroy(); } + + detachFromContainer() { this._view.detach(); } + + attachToAppRef(appRef: ApplicationRef) { this._view.attachToAppRef(appRef); } } diff --git a/modules/@angular/core/src/view/refs.ts b/modules/@angular/core/src/view/refs.ts index 89c3bac280..01740a973d 100644 --- a/modules/@angular/core/src/view/refs.ts +++ b/modules/@angular/core/src/view/refs.ts @@ -14,7 +14,7 @@ import {ComponentFactory, ComponentRef} from '../linker/component_factory'; import {ElementRef} from '../linker/element_ref'; import {TemplateRef} from '../linker/template_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 {Type} from '../type'; import {VERSION} from '../version'; @@ -162,7 +162,7 @@ export function createChangeDetectorRef(view: ViewData): ChangeDetectorRef { return new ViewRef_(view); } -export class ViewRef_ implements EmbeddedViewRef { +export class ViewRef_ implements EmbeddedViewRef, InternalViewRef { /** @internal */ _view: ViewData; private _viewContainerRef: ViewContainerRef; diff --git a/modules/@angular/core/test/linker/integration_spec.ts b/modules/@angular/core/test/linker/integration_spec.ts index 39e8d3609a..3749e655f9 100644 --- a/modules/@angular/core/test/linker/integration_spec.ts +++ b/modules/@angular/core/test/linker/integration_spec.ts @@ -1333,7 +1333,6 @@ function declareTests({useJit, viewEngine}: {useJit: boolean, viewEngine: boolea expect(getDOM().nodeName(c.renderNode).toUpperCase()).toEqual('INPUT'); expect(getDOM().nodeName(c.componentRenderElement).toUpperCase()).toEqual('DIV'); expect((c.injector).get).toBeTruthy(); - expect(c.source).toContain(':0:7'); expect(c.context).toBe(fixture.componentInstance); expect(c.references['local']).toBeDefined(); } @@ -1351,7 +1350,6 @@ function declareTests({useJit, viewEngine}: {useJit: boolean, viewEngine: boolea } catch (e) { const c = getDebugContext(e); expect(c.renderNode).toBeTruthy(); - expect(c.source).toContain(':0:5'); } });