From 68b2407a835945ea2fa642541caf8fa9a12ddccc Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Thu, 2 Feb 2017 15:01:35 -0800 Subject: [PATCH] feat(compiler): integrate compiler with view engine - hello world Part of #14013 --- modules/@angular/compiler/src/config.ts | 11 +- modules/@angular/compiler/src/identifiers.ts | 39 +++- .../compiler/src/jit/compiler_factory.ts | 15 +- .../compiler/src/metadata_resolver.ts | 12 +- .../compiler/src/private_import_core.ts | 1 + .../compiler/src/view_compiler_next/README.md | 5 + .../src/view_compiler_next/view_compiler.ts | 181 ++++++++++++++++++ .../@angular/core/src/core_private_export.ts | 3 + modules/@angular/core/src/view/element.ts | 7 +- modules/@angular/core/src/view/refs.ts | 54 +++--- modules/@angular/core/src/view/types.ts | 13 +- modules/@angular/core/src/view/view.ts | 5 +- .../core/test/linker/integration_next_spec.ts | 59 ++++++ .../@angular/core/test/view/anchor_spec.ts | 2 +- .../core/test/view/component_view_spec.ts | 28 ++- .../@angular/core/test/view/element_spec.ts | 2 +- .../core/test/view/embedded_view_spec.ts | 6 +- .../core/test/view/ng_content_spec.ts | 6 +- .../@angular/core/test/view/provider_spec.ts | 6 +- .../core/test/view/pure_expression_spec.ts | 2 +- modules/@angular/core/test/view/query_spec.ts | 68 +++---- modules/@angular/core/test/view/refs_spec.ts | 2 +- modules/@angular/core/test/view/text_spec.ts | 2 +- .../@angular/core/test/view/view_def_spec.ts | 2 +- modules/benchmarks/src/tree/ng2_next/tree.ts | 12 +- 25 files changed, 419 insertions(+), 124 deletions(-) create mode 100644 modules/@angular/compiler/src/view_compiler_next/README.md create mode 100644 modules/@angular/compiler/src/view_compiler_next/view_compiler.ts create mode 100644 modules/@angular/core/test/linker/integration_next_spec.ts diff --git a/modules/@angular/compiler/src/config.ts b/modules/@angular/compiler/src/config.ts index c88ebdfb90d09a..1619006f2d7931 100644 --- a/modules/@angular/compiler/src/config.ts +++ b/modules/@angular/compiler/src/config.ts @@ -6,11 +6,20 @@ * found in the LICENSE file at https://angular.io/license */ -import {MissingTranslationStrategy, ViewEncapsulation, isDevMode} from '@angular/core'; +import {InjectionToken, MissingTranslationStrategy, ViewEncapsulation, isDevMode} from '@angular/core'; import {CompileIdentifierMetadata} from './compile_metadata'; import {Identifiers, createIdentifier} from './identifiers'; + +/** + * Temporal switch for the compiler to use the new view engine, + * until it is fully integrated. + * + * Only works in Jit for now. + */ +export const USE_VIEW_ENGINE = new InjectionToken('UseViewEngine'); + export class CompilerConfig { public renderTypes: RenderTypes; public defaultEncapsulation: ViewEncapsulation; diff --git a/modules/@angular/compiler/src/identifiers.ts b/modules/@angular/compiler/src/identifiers.ts index c5588414771e6d..e578b9c075ef04 100644 --- a/modules/@angular/compiler/src/identifiers.ts +++ b/modules/@angular/compiler/src/identifiers.ts @@ -9,10 +9,11 @@ import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core'; import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata'; -import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, ComponentRef_, DebugAppView, DebugContext, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewContainer, ViewType, balanceAnimationKeyframes, clearStyles, collectAndResolveStyles, devModeEqual, prepareFinalAnimationStyles, reflector, registerModuleFactory, renderStyles, view_utils} from './private_import_core'; +import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, ComponentRef_, DebugAppView, DebugContext, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewContainer, ViewType, balanceAnimationKeyframes, clearStyles, collectAndResolveStyles, devModeEqual, prepareFinalAnimationStyles, reflector, registerModuleFactory, renderStyles, viewEngine, view_utils} from './private_import_core'; const APP_VIEW_MODULE_URL = assetUrl('core', 'linker/view'); const VIEW_UTILS_MODULE_URL = assetUrl('core', 'linker/view_utils'); +const VIEW_ENGINE_MODULE_URL = assetUrl('core', 'view/index'); const CD_MODULE_URL = assetUrl('core', 'change_detection/change_detection'); const ANIMATION_STYLE_UTIL_ASSET_URL = assetUrl('core', 'animation/animation_style_util'); @@ -363,6 +364,42 @@ export class Identifiers { }; static noop: IdentifierSpec = {name: 'noop', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.noop}; + + static viewDef: IdentifierSpec = { + name: 'viewDef', + moduleUrl: VIEW_ENGINE_MODULE_URL, + runtime: viewEngine.viewDef + }; + static elementDef: IdentifierSpec = { + name: 'elementDef', + moduleUrl: VIEW_ENGINE_MODULE_URL, + runtime: viewEngine.elementDef + }; + static textDef: IdentifierSpec = { + name: 'textDef', + moduleUrl: VIEW_ENGINE_MODULE_URL, + runtime: viewEngine.textDef + }; + static directiveDef: IdentifierSpec = { + name: 'directiveDef', + moduleUrl: VIEW_ENGINE_MODULE_URL, + runtime: viewEngine.directiveDef + }; + static setCurrentNode: IdentifierSpec = { + name: 'setCurrentNode', + moduleUrl: VIEW_ENGINE_MODULE_URL, + runtime: viewEngine.setCurrentNode + }; + static checkNodeInline: IdentifierSpec = { + name: 'checkNodeInline', + moduleUrl: VIEW_ENGINE_MODULE_URL, + runtime: viewEngine.checkNodeInline + }; + static checkNodeDynamic: IdentifierSpec = { + name: 'checkNodeDynamic', + moduleUrl: VIEW_ENGINE_MODULE_URL, + runtime: viewEngine.checkNodeDynamic + }; } export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string { diff --git a/modules/@angular/compiler/src/jit/compiler_factory.ts b/modules/@angular/compiler/src/jit/compiler_factory.ts index 0da4a2ff108883..4d04a46c21e672 100644 --- a/modules/@angular/compiler/src/jit/compiler_factory.ts +++ b/modules/@angular/compiler/src/jit/compiler_factory.ts @@ -9,7 +9,7 @@ import {COMPILER_OPTIONS, Compiler, CompilerFactory, CompilerOptions, Inject, InjectionToken, MissingTranslationStrategy, Optional, PLATFORM_INITIALIZER, PlatformRef, Provider, ReflectiveInjector, TRANSLATIONS, TRANSLATIONS_FORMAT, Type, ViewEncapsulation, createPlatformFactory, isDevMode, platformCore} from '@angular/core'; import {AnimationParser} from '../animation/animation_parser'; -import {CompilerConfig} from '../config'; +import {CompilerConfig, USE_VIEW_ENGINE} from '../config'; import {DirectiveNormalizer} from '../directive_normalizer'; import {DirectiveResolver} from '../directive_resolver'; import {DirectiveWrapperCompiler} from '../directive_wrapper_compiler'; @@ -31,6 +31,7 @@ import {SummaryResolver} from '../summary_resolver'; import {TemplateParser} from '../template_parser/template_parser'; import {DEFAULT_PACKAGE_URL_PROVIDER, UrlResolver} from '../url_resolver'; import {ViewCompiler} from '../view_compiler/view_compiler'; +import {ViewCompilerNext} from '../view_compiler_next/view_compiler'; import {JitCompiler} from './compiler'; @@ -42,6 +43,11 @@ const _NO_RESOURCE_LOADER: ResourceLoader = { const baseHtmlParser = new InjectionToken('HtmlParser'); +function viewCompilerFactory( + useViewEngine: boolean, cc: CompilerConfig, sr: ElementSchemaRegistry) { + return useViewEngine ? new ViewCompilerNext(cc, sr) : new ViewCompiler(cc, sr); +} + /** * A set of providers that provide `JitCompiler` and its dependencies to use for * template compilation. @@ -81,7 +87,12 @@ export const COMPILER_PROVIDERS: Array|{[k: string]: any}|any[]> = CompileMetadataResolver, DEFAULT_PACKAGE_URL_PROVIDER, StyleCompiler, - ViewCompiler, + {provide: USE_VIEW_ENGINE, useValue: false}, + { + provide: ViewCompiler, + useFactory: viewCompilerFactory, + deps: [USE_VIEW_ENGINE, CompilerConfig, ElementSchemaRegistry] + }, NgModuleCompiler, DirectiveWrapperCompiler, {provide: CompilerConfig, useValue: new CompilerConfig()}, diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index e7ccd1df97cbd8..36846d574059ff 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -12,6 +12,7 @@ import {StaticSymbol, StaticSymbolCache} from './aot/static_symbol'; import {ngfactoryFilePath} from './aot/util'; import {assertArrayOfStrings, assertInterpolationSymbols} from './assertions'; import * as cpl from './compile_metadata'; +import {USE_VIEW_ENGINE} from './config'; import {DirectiveNormalizer} from './directive_normalizer'; import {DirectiveResolver} from './directive_resolver'; import {stringify} from './facade/lang'; @@ -20,7 +21,7 @@ import {CompilerInjectable} from './injectable'; import {hasLifecycleHook} from './lifecycle_reflector'; import {NgModuleResolver} from './ng_module_resolver'; import {PipeResolver} from './pipe_resolver'; -import {ComponentStillLoadingError, LIFECYCLE_HOOKS_VALUES, ReflectorReader, reflector} from './private_import_core'; +import {ComponentStillLoadingError, LIFECYCLE_HOOKS_VALUES, ReflectorReader, reflector, viewEngine} from './private_import_core'; import {ElementSchemaRegistry} from './schema/element_schema_registry'; import {SummaryResolver} from './summary_resolver'; import {getUrlScheme} from './url_resolver'; @@ -53,7 +54,8 @@ export class CompileMetadataResolver { private _directiveNormalizer: DirectiveNormalizer, @Optional() private _staticSymbolCache: StaticSymbolCache, private _reflector: ReflectorReader = reflector, - @Optional() @Inject(ERROR_COLLECTOR_TOKEN) private _errorCollector?: ErrorCollector) {} + @Optional() @Inject(ERROR_COLLECTOR_TOKEN) private _errorCollector?: ErrorCollector, + @Optional() @Inject(USE_VIEW_ENGINE) private _useViewEngine?: boolean) {} clearCacheFor(type: Type) { const dirMeta = this._directiveCache.get(type); @@ -135,7 +137,11 @@ export class CompileMetadataResolver { ngfactoryFilePath(dirType.filePath), cpl.componentFactoryName(dirType)); } else { const hostView = this.getHostComponentViewClass(dirType); - return new ComponentFactory(selector, hostView, dirType); + if (this._useViewEngine) { + return viewEngine.createComponentFactory(selector, dirType, hostView); + } else { + return new ComponentFactory(selector, hostView, dirType); + } } } diff --git a/modules/@angular/compiler/src/private_import_core.ts b/modules/@angular/compiler/src/private_import_core.ts index 0aee872445e58e..7861e32f961e17 100644 --- a/modules/@angular/compiler/src/private_import_core.ts +++ b/modules/@angular/compiler/src/private_import_core.ts @@ -29,6 +29,7 @@ export const registerModuleFactory: typeof r.registerModuleFactory = r.registerM export type ViewType = typeof r._ViewType; export const ViewType: typeof r.ViewType = r.ViewType; export const view_utils: typeof r.view_utils = r.view_utils; +export const viewEngine: typeof r.viewEngine = r.viewEngine; export const DebugContext: typeof r.DebugContext = r.DebugContext; export const StaticNodeDebugInfo: typeof r.StaticNodeDebugInfo = r.StaticNodeDebugInfo; export const devModeEqual: typeof r.devModeEqual = r.devModeEqual; diff --git a/modules/@angular/compiler/src/view_compiler_next/README.md b/modules/@angular/compiler/src/view_compiler_next/README.md new file mode 100644 index 00000000000000..cf1157a073a47b --- /dev/null +++ b/modules/@angular/compiler/src/view_compiler_next/README.md @@ -0,0 +1,5 @@ +# Compiler Integration for new View Engine + +This folder contains the code to integrate the compiler with the new view engine. + +Note: This is work in progress, and once complete will replace the regular view_compiler folder. \ No newline at end of file diff --git a/modules/@angular/compiler/src/view_compiler_next/view_compiler.ts b/modules/@angular/compiler/src/view_compiler_next/view_compiler.ts new file mode 100644 index 00000000000000..0058b02ccd56e9 --- /dev/null +++ b/modules/@angular/compiler/src/view_compiler_next/view_compiler.ts @@ -0,0 +1,181 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {AnimationEntryCompileResult} from '../animation/animation_compiler'; +import {CompileDirectiveMetadata, CompilePipeSummary, identifierModuleUrl, identifierName} from '../compile_metadata'; +import {convertPropertyBinding} from '../compiler_util/expression_converter'; +import {CompilerConfig} from '../config'; +import {ASTWithSource, Interpolation} from '../expression_parser/ast'; +import {Identifiers, createIdentifier} from '../identifiers'; +import {CompilerInjectable} from '../injectable'; +import * as o from '../output/output_ast'; +import {viewEngine} from '../private_import_core'; +import {ElementSchemaRegistry} from '../schema/element_schema_registry'; +import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast'; +import {ViewEncapsulationEnum} from '../view_compiler/constants'; +import {ComponentFactoryDependency, ComponentViewDependency, DirectiveWrapperDependency, ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler'; + +@CompilerInjectable() +export class ViewCompilerNext extends ViewCompiler { + constructor( + private _genConfigNext: CompilerConfig, private _schemaRegistryNext: ElementSchemaRegistry) { + super(_genConfigNext, _schemaRegistryNext); + } + + compileComponent( + component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression, + pipes: CompilePipeSummary[], + compiledAnimations: AnimationEntryCompileResult[]): ViewCompileResult { + const visitor = new ViewBuilderVisitor(); + templateVisitAll(visitor, template); + + const statements: o.Statement[] = []; + const compName = identifierName(component.type) + (component.isHost ? `_Host` : ''); + const viewName = `view_${compName}`; + + const renderCompTypeName = `renderType_${compName}`; + statements.push( + createRenderComponentType(renderCompTypeName, component, styles, compiledAnimations)); + const renderCompType = o.variable(renderCompTypeName); + statements.push(...visitor.build(viewName, o.importType(component.type), renderCompType)); + + return new ViewCompileResult(statements, viewName, []); + } +} + +function createRenderComponentType( + renderCompTypeName: string, component: CompileDirectiveMetadata, styles: o.Expression, + animations: AnimationEntryCompileResult[]): o.Statement { + const compName = identifierName(component.type); + const compFilePath = identifierModuleUrl(component.type); + const renderCompTypeVar: o.ReadVarExpr = o.variable(renderCompTypeName); + return renderCompTypeVar + .set(o.importExpr(createIdentifier(Identifiers.createRenderComponentType)).callFn([ + o.literal(''), + o.literal(component.template.ngContentSelectors.length), + ViewEncapsulationEnum.fromValue(component.template.encapsulation), + styles, + o.literalMap( + animations.map((entry): [string, o.Expression] => [entry.name, entry.fnExp]), null, + true), + ])) + .toDeclStmt(o.importType(createIdentifier(Identifiers.RenderComponentType))); +} + +const VIEW_VAR = o.variable('view'); +const COMP_VAR = o.variable('comp'); + +class ViewBuilderVisitor implements TemplateAstVisitor { + private nodeDefs: o.Expression[] = []; + private updateStmts: o.Statement[] = []; + private bindingCount = 0; + private nodeCount = 0; + + build(viewName: string, compType: o.Type, renderCompType: o.Expression): o.Statement[] { + const viewFlags = 0; + let updateFn: o.Expression; + if (this.updateStmts.length > 0) { + updateFn = o.fn( + [new o.FnParam(VIEW_VAR.name)], + [COMP_VAR.set(VIEW_VAR.prop('component')).toDeclStmt(compType), ...this.updateStmts]); + } else { + updateFn = o.NULL_EXPR; + } + const handleEventFn = o.NULL_EXPR; + const viewFactory = new o.DeclareFunctionStmt( + viewName, [], + [new o.ReturnStatement(o.importExpr(createIdentifier(Identifiers.viewDef)).callFn([ + o.literal(viewFlags), o.literalArr(this.nodeDefs.slice().reverse()), updateFn, + handleEventFn, renderCompType + ]))]); + + return [viewFactory]; + } + + visitNgContent(ast: NgContentAst, context: any): any {} + visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any {} + visitElement(ast: ElementAst, context: any): any { + // elementDef( + // flags: NodeFlags, matchedQueries: [string, QueryValueType][], ngContentIndex: number, + // childCount: number, name: string, fixedAttrs: {[name: string]: string} = {}, + // bindings?: + // ([BindingType.ElementClass, string] | [BindingType.ElementStyle, string, string] | + // [BindingType.ElementAttribute | BindingType.ElementProperty, string, + // SecurityContext])[], + // outputs?: (string | [string, string])[]): NodeDef; + const nodeIndex = this.nodeCount++; + templateVisitAll(this, ast.directives); + templateVisitAll(this, ast.children); + const childCount = this.nodeCount - nodeIndex - 1; + + const flags = o.literal(0); + const fixedAttrs = o.literalMap([]); + this.nodeDefs.push(o.importExpr(createIdentifier(Identifiers.elementDef)).callFn([ + flags, o.NULL_EXPR, o.NULL_EXPR, o.literal(childCount), o.literal(ast.name), fixedAttrs + ])); + } + visitReference(ast: ReferenceAst, context: any): any {} + visitVariable(ast: VariableAst, context: any): any {} + visitEvent(ast: BoundEventAst, context: any): any {} + visitElementProperty(ast: BoundElementPropertyAst, context: any): any {} + visitAttr(ast: AttrAst, context: any): any {} + visitBoundText(ast: BoundTextAst, context: any): any { + const nodeIndex = this.nodeCount++; + const astWithSource = ast.value; + const inter = astWithSource.ast; + this.updateStmts.push(o.importExpr(createIdentifier(Identifiers.setCurrentNode)) + .callFn([o.variable('view'), o.literal(nodeIndex)]) + .toStmt()); + const exprs = inter.expressions.map((expr) => { + const bindingId = `bind_${this.bindingCount++}`; + const converted = convertPropertyBinding(null, null, COMP_VAR, expr, bindingId); + this.updateStmts.push(...converted.stmts); + return converted.currValExpr; + }); + if (exprs.length > 10) { + this.updateStmts.push(o.importExpr(createIdentifier(Identifiers.checkNodeDynamic)) + .callFn([o.literalArr(exprs)]) + .toStmt()); + } else { + this.updateStmts.push( + o.importExpr(createIdentifier(Identifiers.checkNodeInline)).callFn(exprs).toStmt()); + } + + // textDef(ngContentIndex: number, constants: string[]): NodeDef; + this.nodeDefs.push(o.importExpr(createIdentifier(Identifiers.textDef)).callFn([ + o.NULL_EXPR, o.literalArr(inter.strings.map(s => o.literal(s))) + ])); + } + visitText(ast: TextAst, context: any): any { + this.nodeCount++; + // textDef(ngContentIndex: number, constants: string[]): NodeDef; + this.nodeDefs.push(o.importExpr(createIdentifier(Identifiers.textDef)).callFn([ + o.NULL_EXPR, o.literalArr([o.literal(ast.value)]) + ])); + } + visitDirective(ast: DirectiveAst, context: any): any { + this.nodeCount++; + const flags = 0; + const childCount = 0; + const deps: o.Expression[] = []; + let compView = o.NULL_EXPR; + if (ast.directive.isComponent) { + compView = o.importExpr({reference: ast.directive.componentViewType}); + } + // directiveDef( + // flags: NodeFlags, matchedQueries: [string, QueryValueType][], childCount: number, ctor: + // any, + // deps: ([DepFlags, any] | any)[], props?: {[name: string]: [number, string]}, + // outputs?: {[name: string]: string}, component?: () => ViewDefinition): NodeDef; + this.nodeDefs.push(o.importExpr(createIdentifier(Identifiers.directiveDef)).callFn([ + o.literal(flags), o.NULL_EXPR, o.literal(childCount), o.importExpr(ast.directive.type), + o.literalArr(deps), o.NULL_EXPR, o.NULL_EXPR, compView + ])); + } + visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any {} +} \ No newline at end of file diff --git a/modules/@angular/core/src/core_private_export.ts b/modules/@angular/core/src/core_private_export.ts index c39c0e5229d398..e78b9bd8176b96 100644 --- a/modules/@angular/core/src/core_private_export.ts +++ b/modules/@angular/core/src/core_private_export.ts @@ -42,6 +42,7 @@ import * as reflection_types from './reflection/types'; import * as api from './render/api'; import * as decorators from './util/decorators'; import {isObservable, isPromise} from './util/lang'; +import * as viewEngine from './view/index'; export const __core_private__: { isDefaultChangeDetectionStrategy: typeof constants.isDefaultChangeDetectionStrategy, @@ -110,6 +111,7 @@ export const __core_private__: { isObservable: typeof isObservable, AnimationTransition: typeof AnimationTransition view_utils: typeof view_utils, + viewEngine: typeof viewEngine, } = { isDefaultChangeDetectionStrategy: constants.isDefaultChangeDetectionStrategy, ChangeDetectorStatus: constants.ChangeDetectorStatus, @@ -126,6 +128,7 @@ export const __core_private__: { registerModuleFactory: ng_module_factory_loader.registerModuleFactory, ViewType: view_type.ViewType, view_utils: view_utils, + viewEngine: viewEngine, ViewMetadata: metadata_view.ViewMetadata, DebugContext: debug_context.DebugContext, StaticNodeDebugInfo: debug_context.StaticNodeDebugInfo, diff --git a/modules/@angular/core/src/view/element.ts b/modules/@angular/core/src/view/element.ts index 829c86ef361eb9..04f523c5643d96 100644 --- a/modules/@angular/core/src/view/element.ts +++ b/modules/@angular/core/src/view/element.ts @@ -9,16 +9,17 @@ import {isDevMode} from '../application_ref'; import {SecurityContext} from '../security'; -import {BindingDef, BindingType, DebugContext, DisposableFn, ElementData, ElementOutputDef, EntryAction, NodeData, NodeDef, NodeFlags, NodeType, QueryValueType, Refs, ViewData, ViewDefinition, ViewFlags, asElementData} from './types'; -import {checkAndUpdateBinding, dispatchEvent, entryAction, setBindingDebugInfo, setCurrentNode, sliceErrorStack, unwrapValue} from './util'; +import {BindingDef, BindingType, DebugContext, DisposableFn, ElementData, ElementOutputDef, EntryAction, NodeData, NodeDef, NodeFlags, NodeType, QueryValueType, Refs, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, asElementData} from './types'; +import {checkAndUpdateBinding, dispatchEvent, entryAction, resolveViewDefinition, setBindingDebugInfo, setCurrentNode, sliceErrorStack, unwrapValue} from './util'; export function anchorDef( flags: NodeFlags, matchedQueries: [string, QueryValueType][], ngContentIndex: number, - childCount: number, template?: ViewDefinition): NodeDef { + childCount: number, templateFactory?: ViewDefinitionFactory): NodeDef { const matchedQueryDefs: {[queryId: string]: QueryValueType} = {}; if (matchedQueries) { matchedQueries.forEach(([queryId, valueType]) => { matchedQueryDefs[queryId] = valueType; }); } + const template = templateFactory ? resolveViewDefinition(templateFactory) : undefined; // skip the call to sliceErrorStack itself + the call to this function. const source = isDevMode() ? sliceErrorStack(2, 3) : ''; return { diff --git a/modules/@angular/core/src/view/refs.ts b/modules/@angular/core/src/view/refs.ts index 6bb5eee15b78f9..abdb276dce87ea 100644 --- a/modules/@angular/core/src/view/refs.ts +++ b/modules/@angular/core/src/view/refs.ts @@ -20,7 +20,7 @@ import {Type} from '../type'; import {resolveDep, tokenKey} from './provider'; import {getQueryValue} from './query'; import {DebugContext, DepFlags, ElementData, NodeData, NodeDef, NodeType, Refs, RootData, ViewData, ViewDefinition, ViewDefinitionFactory, ViewState, asElementData, asProviderData} from './types'; -import {findElementDef, isComponentView, parentDiIndex, renderNode, resolveViewDefinition, rootRenderNodes} from './util'; +import {findElementDef, isComponentView, parentDiIndex, renderNode, rootRenderNodes} from './util'; import {checkAndUpdateView, checkNoChangesView, createEmbeddedView, createRootView, destroyView} from './view'; import {attachEmbeddedView, detachEmbeddedView, moveEmbeddedView} from './view_attach'; @@ -31,9 +31,10 @@ export function createRefs() { } export class Refs_ implements Refs { - createComponentFactory(selector: string, viewDefFactory: ViewDefinitionFactory): - ComponentFactory { - return new ComponentFactory_(selector, viewDefFactory); + createComponentFactory( + selector: string, componentType: Type, + viewDefFactory: ViewDefinitionFactory): ComponentFactory { + return new ComponentFactory_(selector, componentType, viewDefFactory); } createViewRef(data: ViewData): ViewRef { return new ViewRef_(data); } createViewContainerRef(view: ViewData, elIndex: number): ViewContainerRef { @@ -50,30 +51,13 @@ export class Refs_ implements Refs { class ComponentFactory_ implements ComponentFactory { /** - * Only needed so that we can implement ComponentFactory * @internal */ _viewClass: any; - private _viewDef: ViewDefinition; - private _componentNodeIndex: number; - - constructor(public selector: string, viewDefFactory: ViewDefinitionFactory) { - const viewDef = this._viewDef = resolveViewDefinition(viewDefFactory); - const len = viewDef.nodes.length; - for (let i = 0; i < len; i++) { - const nodeDef = viewDef.nodes[i]; - if (nodeDef.provider && nodeDef.provider.component) { - this._componentNodeIndex = i; - break; - } - } - if (this._componentNodeIndex == null) { - throw new Error(`Illegal State: Could not find a component in the view definition!`); - } - } - - get componentType(): Type { - return this._viewDef.nodes[this._componentNodeIndex].provider.value; + constructor( + public selector: string, public componentType: Type, + viewDefFactory: ViewDefinitionFactory) { + this._viewClass = viewDefFactory; } /** @@ -94,15 +78,27 @@ class ComponentFactory_ implements ComponentFactory { const root: RootData = {injector, projectableNodes, selectorOrNode: rootSelectorOrNode, sanitizer, renderer}; - const view = createRootView(root, this._viewDef, EMPTY_CONTEXT); - const component = asProviderData(view, this._componentNodeIndex).instance; - return new ComponentRef_(view, component); + const view = createRootView(root, this._viewClass, EMPTY_CONTEXT); + return new ComponentRef_(view); } } class ComponentRef_ implements ComponentRef { private _viewRef: ViewRef_; - constructor(private _view: ViewData, private _component: any) { + private _component: any; + constructor(private _view: ViewData) { + const viewDef = _view.def; + const len = viewDef.nodes.length; + for (let i = 0; i < len; i++) { + const nodeDef = viewDef.nodes[i]; + if (nodeDef.provider && nodeDef.provider.component) { + this._component = asProviderData(_view, i).instance; + break; + } + } + if (!this._component) { + throw new Error(`Illegal State: Could not find a component in the view definition!`); + } this._viewRef = new ViewRef_(_view); } get location(): ElementRef { return new ElementRef(asElementData(this._view, 0).renderElement); } diff --git a/modules/@angular/core/src/view/types.ts b/modules/@angular/core/src/view/types.ts index f8faf32c160394..b9879c7f012aac 100644 --- a/modules/@angular/core/src/view/types.ts +++ b/modules/@angular/core/src/view/types.ts @@ -15,6 +15,7 @@ import {ViewContainerRef} from '../linker/view_container_ref'; import {ViewRef} from '../linker/view_ref'; import {RenderComponentType, RenderDebugInfo, Renderer, RootRenderer} from '../render/api'; import {Sanitizer, SecurityContext} from '../security'; +import {Type} from '../type'; // ------------------------------------- // Defs @@ -419,9 +420,10 @@ export abstract class Refs { private static instance: Refs; static setInstance(instance: Refs) { Refs.instance = instance; } - static createComponentFactory(selector: string, viewDefFactory: ViewDefinitionFactory): - ComponentFactory { - return Refs.instance.createComponentFactory(selector, viewDefFactory); + static createComponentFactory( + selector: string, componentType: Type, + viewDefFactory: ViewDefinitionFactory): ComponentFactory { + return Refs.instance.createComponentFactory(selector, componentType, viewDefFactory); } static createViewRef(data: ViewData): ViewRef { return Refs.instance.createViewRef(data); } static createViewContainerRef(view: ViewData, elIndex: number): ViewContainerRef { @@ -437,8 +439,9 @@ export abstract class Refs { return Refs.instance.createDebugContext(view, nodeIndex); } - abstract createComponentFactory(selector: string, viewDefFactory: ViewDefinitionFactory): - ComponentFactory; + abstract createComponentFactory( + selector: string, componentType: Type, + viewDefFactory: ViewDefinitionFactory): ComponentFactory; abstract createViewRef(data: ViewData): ViewRef; abstract createViewContainerRef(view: ViewData, elIndex: number): ViewContainerRef; abstract createTemplateRef(parentView: ViewData, def: NodeDef): TemplateRef; diff --git a/modules/@angular/core/src/view/view.ts b/modules/@angular/core/src/view/view.ts index d25e2302b56e5d..f4547692aec9be 100644 --- a/modules/@angular/core/src/view/view.ts +++ b/modules/@angular/core/src/view/view.ts @@ -230,8 +230,9 @@ export function createEmbeddedView(parent: ViewData, anchorDef: NodeDef, context return view; } -export function createRootView(root: RootData, def: ViewDefinition, context?: any): ViewData { - const view = createView(root, null, null, def); +export function createRootView( + root: RootData, defFactory: ViewDefinitionFactory, context?: any): ViewData { + const view = createView(root, null, null, defFactory()); initView(view, context, context); createViewNodes(view); return view; diff --git a/modules/@angular/core/test/linker/integration_next_spec.ts b/modules/@angular/core/test/linker/integration_next_spec.ts new file mode 100644 index 00000000000000..ce6b696acbc635 --- /dev/null +++ b/modules/@angular/core/test/linker/integration_next_spec.ts @@ -0,0 +1,59 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +// Temporal tests for integrating the new view engine into the compiler. +// The tests here will be deleted once the integration is complete! + +import {USE_VIEW_ENGINE} from '@angular/compiler/src/config'; +import {Compiler, Component, Injectable, InjectionToken} from '@angular/core'; +import {TestBed} from '@angular/core/testing'; +import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; +import {expect} from '@angular/platform-browser/testing/matchers'; + +export function main() { + describe('jit', () => { declareTests({useJit: true}); }); + + describe('no jit', () => { declareTests({useJit: false}); }); +} + +function declareTests({useJit}: {useJit: boolean}) { + describe('integration next tests', function() { + + beforeEach(() => { + TestBed.configureCompiler( + {useJit: useJit, providers: [{provide: USE_VIEW_ENGINE, useValue: true}]}); + }); + + it('should consume text node changes', () => { + TestBed.configureTestingModule({declarations: [MyComp]}); + const template = '
{{ctxProp}}
'; + TestBed.overrideComponent(MyComp, {set: {template}}); + const fixture = TestBed.createComponent(MyComp); + fixture.componentInstance.ctxProp = 'Hello World!'; + + fixture.detectChanges(); + expect(fixture.nativeElement).toHaveText('Hello World!'); + }); + }); +} + +@Component({selector: 'my-comp', template: ''}) +class MyComp { + ctxProp: string; + ctxNumProp: number; + ctxBoolProp: boolean; + toStringThrow = {toString: function() { throw 'boom'; }}; + + constructor() { + this.ctxProp = 'initial value'; + this.ctxNumProp = 0; + this.ctxBoolProp = false; + } + + throwError() { throw 'boom'; } +} diff --git a/modules/@angular/core/test/view/anchor_spec.ts b/modules/@angular/core/test/view/anchor_spec.ts index 3624f4a6c5589a..8f372c780fcbb7 100644 --- a/modules/@angular/core/test/view/anchor_spec.ts +++ b/modules/@angular/core/test/view/anchor_spec.ts @@ -40,7 +40,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { function createAndGetRootNodes( viewDef: ViewDefinition, ctx?: any): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef, ctx); + const view = createRootView(rootData, () => viewDef, ctx); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } diff --git a/modules/@angular/core/test/view/component_view_spec.ts b/modules/@angular/core/test/view/component_view_spec.ts index 44470b0ed90c71..84280e41627f98 100644 --- a/modules/@angular/core/test/view/component_view_spec.ts +++ b/modules/@angular/core/test/view/component_view_spec.ts @@ -40,7 +40,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { } function createAndGetRootNodes(viewDef: ViewDefinition): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef); + const view = createRootView(rootData, () => viewDef); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } @@ -80,38 +80,36 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { it('should select root elements based on a selector', () => { rootData.selectorOrNode = 'root'; - const view = createRootView(rootData, compViewDef([ - elementDef(NodeFlags.None, null, null, 1, 'div'), - ])); + const {view} = createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div'), + ])); const rootNodes = rootRenderNodes(view); expect(rootNodes).toEqual([rootNode]); }); it('should select root elements based on a node', () => { rootData.selectorOrNode = rootNode; - const view = createRootView(rootData, compViewDef([ - elementDef(NodeFlags.None, null, null, 1, 'div'), - ])); + const {view} = createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div'), + ])); const rootNodes = rootRenderNodes(view); expect(rootNodes).toEqual([rootNode]); }); it('should set attributes on the root node', () => { rootData.selectorOrNode = rootNode; - const view = - createRootView(rootData, compViewDef([ - elementDef(NodeFlags.None, null, null, 1, 'div', {'a': 'b'}), - ])); + const {view} = createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div', {'a': 'b'}), + ])); expect(rootNode.getAttribute('a')).toBe('b'); }); it('should clear the content of the root node', () => { rootData.selectorOrNode = rootNode; rootNode.appendChild(document.createElement('div')); - const view = - createRootView(rootData, compViewDef([ - elementDef(NodeFlags.None, null, null, 1, 'div', {'a': 'b'}), - ])); + const {view} = createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div', {'a': 'b'}), + ])); expect(rootNode.childNodes.length).toBe(0); }); }); diff --git a/modules/@angular/core/test/view/element_spec.ts b/modules/@angular/core/test/view/element_spec.ts index 0ac0107b85913e..b5f77340bea824 100644 --- a/modules/@angular/core/test/view/element_spec.ts +++ b/modules/@angular/core/test/view/element_spec.ts @@ -40,7 +40,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { function createAndGetRootNodes( viewDef: ViewDefinition, context?: any): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef, context); + const view = createRootView(rootData, () => viewDef, context); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } diff --git a/modules/@angular/core/test/view/embedded_view_spec.ts b/modules/@angular/core/test/view/embedded_view_spec.ts index 2f71cbe071f76f..b9105baf47adc5 100644 --- a/modules/@angular/core/test/view/embedded_view_spec.ts +++ b/modules/@angular/core/test/view/embedded_view_spec.ts @@ -38,13 +38,13 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { return viewDef(config.viewFlags, nodes, update, handleEvent, renderComponentType); } - function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinition { - return viewDef(config.viewFlags, nodes, update); + function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn) { + return () => viewDef(config.viewFlags, nodes, update); } function createAndGetRootNodes( viewDef: ViewDefinition, context: any = null): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef, context); + const view = createRootView(rootData, () => viewDef, context); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } diff --git a/modules/@angular/core/test/view/ng_content_spec.ts b/modules/@angular/core/test/view/ng_content_spec.ts index ba8cb453ba7d0d..65bf2cfa5e4793 100644 --- a/modules/@angular/core/test/view/ng_content_spec.ts +++ b/modules/@angular/core/test/view/ng_content_spec.ts @@ -38,8 +38,8 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { return viewDef(config.viewFlags, nodes, update, handleEvent, renderComponentType); } - function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinition { - return viewDef(config.viewFlags, nodes, update); + function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn) { + return () => viewDef(config.viewFlags, nodes, update); } function hostElDef(contentNodes: NodeDef[], viewNodes: NodeDef[]): NodeDef[] { @@ -56,7 +56,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { function createAndGetRootNodes( viewDef: ViewDefinition, ctx?: any): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef, ctx || {}); + const view = createRootView(rootData, () => viewDef, ctx || {}); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } diff --git a/modules/@angular/core/test/view/provider_spec.ts b/modules/@angular/core/test/view/provider_spec.ts index a1065501698835..4447006df18fb0 100644 --- a/modules/@angular/core/test/view/provider_spec.ts +++ b/modules/@angular/core/test/view/provider_spec.ts @@ -38,12 +38,12 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { return viewDef(config.viewFlags, nodes, update, handleEvent, renderComponentType); } - function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinition { - return viewDef(config.viewFlags, nodes, update); + function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn) { + return () => viewDef(config.viewFlags, nodes, update); } function createAndGetRootNodes(viewDef: ViewDefinition): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef); + const view = createRootView(rootData, () => viewDef); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } diff --git a/modules/@angular/core/test/view/pure_expression_spec.ts b/modules/@angular/core/test/view/pure_expression_spec.ts index dacd73a8a983d6..3b90181711f7a5 100644 --- a/modules/@angular/core/test/view/pure_expression_spec.ts +++ b/modules/@angular/core/test/view/pure_expression_spec.ts @@ -29,7 +29,7 @@ export function main() { } function createAndGetRootNodes(viewDef: ViewDefinition): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef); + const view = createRootView(rootData, () => viewDef); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } diff --git a/modules/@angular/core/test/view/query_spec.ts b/modules/@angular/core/test/view/query_spec.ts index b55a2f326f8797..4b9be917557596 100644 --- a/modules/@angular/core/test/view/query_spec.ts +++ b/modules/@angular/core/test/view/query_spec.ts @@ -29,13 +29,13 @@ export function main() { return viewDef(ViewFlags.None, nodes, update, handleEvent, renderComponentType); } - function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn): ViewDefinition { - return viewDef(ViewFlags.None, nodes, update); + function embeddedViewDef(nodes: NodeDef[], update?: ViewUpdateFn) { + return () => viewDef(ViewFlags.None, nodes, update); } function createAndGetRootNodes( viewDef: ViewDefinition, context: any = null): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef, context); + const view = createRootView(rootData, () => viewDef, context); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } @@ -141,14 +141,10 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 5, 'div'), ...contentQueryProviders(), - anchorDef( - NodeFlags.HasEmbeddedViews, null, null, 2, - viewDef( - ViewFlags.None, - [ - elementDef(NodeFlags.None, null, null, 1, 'div'), - aServiceProvider(), - ])), + anchorDef(NodeFlags.HasEmbeddedViews, null, null, 2, embeddedViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div'), + aServiceProvider(), + ])), ...contentQueryProviders(), ])); @@ -171,14 +167,10 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 3, 'div'), ...contentQueryProviders(), - anchorDef( - NodeFlags.HasEmbeddedViews, null, null, 0, - viewDef( - ViewFlags.None, - [ - elementDef(NodeFlags.None, null, null, 1, 'div'), - aServiceProvider(), - ])), + anchorDef(NodeFlags.HasEmbeddedViews, null, null, 0, embeddedViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div'), + aServiceProvider(), + ])), elementDef(NodeFlags.None, null, null, 3, 'div'), ...contentQueryProviders(), anchorDef(NodeFlags.HasEmbeddedViews, null, null, 0), @@ -204,14 +196,10 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 3, 'div'), ...contentQueryProviders(), - anchorDef( - NodeFlags.HasEmbeddedViews, null, null, 0, - viewDef( - ViewFlags.None, - [ - elementDef(NodeFlags.None, null, null, 1, 'div'), - aServiceProvider(), - ])), + anchorDef(NodeFlags.HasEmbeddedViews, null, null, 0, embeddedViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div'), + aServiceProvider(), + ])), ])); checkAndUpdateView(view); @@ -235,14 +223,10 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 2, 'div'), ...viewQueryProviders(compViewDef([ - anchorDef( - NodeFlags.HasEmbeddedViews, null, null, 0, - viewDef( - ViewFlags.None, - [ - elementDef(NodeFlags.None, null, null, 1, 'div'), - aServiceProvider(), - ])), + anchorDef(NodeFlags.HasEmbeddedViews, null, null, 0, embeddedViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div'), + aServiceProvider(), + ])), ])), ])); @@ -335,7 +319,7 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ anchorDef( NodeFlags.None, [['query1', QueryValueType.TemplateRef]], null, 2, - viewDef(ViewFlags.None, [anchorDef(NodeFlags.None, null, null, 0)])), + embeddedViewDef([anchorDef(NodeFlags.None, null, null, 0)])), directiveDef(NodeFlags.None, null, 1, QueryService, []), queryDef(NodeFlags.HasContentQuery, 'query1', {'a': QueryBindingType.First}), ])); @@ -369,14 +353,10 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 4, 'div'), ...contentQueryProviders(), - anchorDef( - NodeFlags.HasEmbeddedViews, null, null, 1, - viewDef( - ViewFlags.None, - [ - elementDef(NodeFlags.None, null, null, 1, 'div'), - aServiceProvider(), - ])), + anchorDef(NodeFlags.HasEmbeddedViews, null, null, 1, embeddedViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div'), + aServiceProvider(), + ])), ])); checkAndUpdateView(view); diff --git a/modules/@angular/core/test/view/refs_spec.ts b/modules/@angular/core/test/view/refs_spec.ts index 7c9abceb0526f7..f275d824481b33 100644 --- a/modules/@angular/core/test/view/refs_spec.ts +++ b/modules/@angular/core/test/view/refs_spec.ts @@ -31,7 +31,7 @@ export function main() { function createAndGetRootNodes( viewDef: ViewDefinition, context: any = null): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef, context); + const view = createRootView(rootData, () => viewDef, context); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } diff --git a/modules/@angular/core/test/view/text_spec.ts b/modules/@angular/core/test/view/text_spec.ts index 23a18f7475d03e..174ecb2d853673 100644 --- a/modules/@angular/core/test/view/text_spec.ts +++ b/modules/@angular/core/test/view/text_spec.ts @@ -40,7 +40,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { function createAndGetRootNodes( viewDef: ViewDefinition, context?: any): {rootNodes: any[], view: ViewData} { - const view = createRootView(rootData, viewDef, context); + const view = createRootView(rootData, () => viewDef, context); const rootNodes = rootRenderNodes(view); return {rootNodes, view}; } diff --git a/modules/@angular/core/test/view/view_def_spec.ts b/modules/@angular/core/test/view/view_def_spec.ts index e2f042c82ad578..02e033c9dd5be1 100644 --- a/modules/@angular/core/test/view/view_def_spec.ts +++ b/modules/@angular/core/test/view/view_def_spec.ts @@ -228,7 +228,7 @@ export function main() { elementDef(NodeFlags.None, null, null, 1, 'span'), anchorDef( NodeFlags.None, null, null, 0, - viewDef( + () => viewDef( ViewFlags.None, [ elementDef(NodeFlags.None, [['q1', QueryValueType.Provider]], null, 1, 'span'), diff --git a/modules/benchmarks/src/tree/ng2_next/tree.ts b/modules/benchmarks/src/tree/ng2_next/tree.ts index 88473fe844f182..f527857f40fe25 100644 --- a/modules/benchmarks/src/tree/ng2_next/tree.ts +++ b/modules/benchmarks/src/tree/ng2_next/tree.ts @@ -30,8 +30,8 @@ function TreeComponent_Host(): ViewDefinition { ]); } -function TreeComponent_0(): ViewDefinition { - const TreeComponent_1: ViewDefinition = viewDef( +function TreeComponent_1() { + return viewDef( viewFlags, [ elementDef(NodeFlags.None, null, null, 1, 'tree'), @@ -43,8 +43,10 @@ function TreeComponent_0(): ViewDefinition { setCurrentNode(view, 1); checkNodeInline(cmp.data.left); }); +} - const TreeComponent_2: ViewDefinition = viewDef( +function TreeComponent_2() { + return viewDef( viewFlags, [ elementDef(NodeFlags.None, null, null, 1, 'tree'), @@ -56,7 +58,9 @@ function TreeComponent_0(): ViewDefinition { setCurrentNode(view, 1); checkNodeInline(cmp.data.right); }); +} +function TreeComponent_0(): ViewDefinition { return viewDef( viewFlags, [ @@ -93,7 +97,7 @@ export class AppModule implements Injector { this.sanitizer = new DomSanitizerImpl(); trustedEmptyColor = this.sanitizer.bypassSecurityTrustStyle(''); trustedGreyColor = this.sanitizer.bypassSecurityTrustStyle('grey'); - this.componentFactory = createComponentFactory('#root', TreeComponent_Host); + this.componentFactory = createComponentFactory('#root', TreeComponent, TreeComponent_Host); } get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {