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/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';

View File

@ -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<StaticSymbol>, 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;
}

View File

@ -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),

View File

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

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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);
}
}
}

View File

@ -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<TemplateAst, StaticAndDynamicQueryIds>,
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)]);

View File

@ -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(

View File

@ -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', () => {

View File

@ -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<any>) => void)[] = [];
private _rootComponents: ComponentRef<any>[] = [];
private _rootComponentTypes: Type<any>[] = [];
private _views: AppView<any>[] = [];
private _views: InternalViewRef[] = [];
private _runningTick: boolean = false;
private _enforceNoNewChanges: boolean = false;
private _isStable: Observable<boolean>;
@ -485,15 +485,15 @@ export class ApplicationRef_ extends ApplicationRef {
}
attachView(viewRef: ViewRef): void {
const view = (viewRef as ViewRef_<any>).internalView;
const view = (viewRef as InternalViewRef);
this._views.push(view);
view.attachToAppRef(this);
}
detachView(viewRef: ViewRef): void {
const view = (viewRef as ViewRef_<any>).internalView;
const view = (viewRef as InternalViewRef);
ListWrapper.remove(this._views, view);
view.detach();
view.detachFromContainer();
}
bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>): ComponentRef<C> {
@ -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;

View File

@ -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<C> extends ViewRef {
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 */
_originalMode: ChangeDetectorStatus;
@ -122,4 +130,8 @@ export class ViewRef_<C> implements EmbeddedViewRef<C>, ChangeDetectorRef {
}
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 {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<any> {
export class ViewRef_ implements EmbeddedViewRef<any>, InternalViewRef {
/** @internal */
_view: ViewData;
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.componentRenderElement).toUpperCase()).toEqual('DIV');
expect((<Injector>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');
}
});