From faa347851416a4c0abbe713884752d1ff5f01069 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Wed, 19 Oct 2016 09:17:36 -0700 Subject: [PATCH] refactor(compiler): set element attributes via one call This makes the cost of using directives that have host attributes smaller. Part of #11683 --- .../src/compiler_util/identifier_util.ts | 36 +++++ modules/@angular/compiler/src/identifiers.ts | 42 ++++- .../compiler/src/ng_module_compiler.ts | 2 +- modules/@angular/compiler/src/util.ts | 23 +-- .../src/view_compiler/compile_element.ts | 2 +- .../compiler/src/view_compiler/util.ts | 2 +- .../src/view_compiler/view_builder.ts | 74 ++++----- .../output/output_emitter_codegen_typed.ts | 2 +- .../output/output_emitter_codegen_untyped.ts | 2 +- .../test/output/output_emitter_util.ts | 2 +- modules/@angular/core/src/linker/view.ts | 11 -- .../@angular/core/src/linker/view_utils.ts | 152 +++++++++++++++++- .../src/tree/ng2_ftl/tree_host.ngfactory.ts | 3 +- .../ng2_static_ftl/tree_root.ngfactory.ts | 3 +- 14 files changed, 269 insertions(+), 87 deletions(-) create mode 100644 modules/@angular/compiler/src/compiler_util/identifier_util.ts diff --git a/modules/@angular/compiler/src/compiler_util/identifier_util.ts b/modules/@angular/compiler/src/compiler_util/identifier_util.ts new file mode 100644 index 0000000000..6f5e4fe70a --- /dev/null +++ b/modules/@angular/compiler/src/compiler_util/identifier_util.ts @@ -0,0 +1,36 @@ +/** + * @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 {CompileTokenMetadata} from '../compile_metadata'; +import {isPresent} from '../facade/lang'; +import {Identifiers, resolveIdentifier} from '../identifiers'; +import * as o from '../output/output_ast'; + +export function createDiTokenExpression(token: CompileTokenMetadata): o.Expression { + if (isPresent(token.value)) { + return o.literal(token.value); + } else if (token.identifierIsInstance) { + return o.importExpr(token.identifier) + .instantiate([], o.importType(token.identifier, [], [o.TypeModifier.Const])); + } else { + return o.importExpr(token.identifier); + } +} + +export function createFastArray(values: o.Expression[]): o.Expression { + if (values.length === 0) { + return o.importExpr(resolveIdentifier(Identifiers.EMPTY_FAST_ARRAY)); + } + const index = Math.ceil(values.length / 2) - 1; + const identifierSpec = index < Identifiers.fastArrays.length ? Identifiers.fastArrays[index] : + Identifiers.FastArrayDynamic; + const identifier = resolveIdentifier(identifierSpec); + return o.importExpr(identifier).instantiate([ + o.literal(values.length) + ].concat(values)); +} diff --git a/modules/@angular/compiler/src/identifiers.ts b/modules/@angular/compiler/src/identifiers.ts index 49f549743c..1056b8aaf8 100644 --- a/modules/@angular/compiler/src/identifiers.ts +++ b/modules/@angular/compiler/src/identifiers.ts @@ -10,7 +10,6 @@ import {ANALYZE_FOR_ENTRY_COMPONENTS, AnimationTransitionEvent, ChangeDetectionS import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata'; import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppElement, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, balanceAnimationKeyframes, clearStyles, collectAndResolveStyles, devModeEqual, prepareFinalAnimationStyles, reflector, registerModuleFactory, renderStyles, view_utils} from './private_import_core'; -import {assetUrl} from './util'; var APP_VIEW_MODULE_URL = assetUrl('core', 'linker/view'); var VIEW_UTILS_MODULE_URL = assetUrl('core', 'linker/view_utils'); @@ -190,8 +189,17 @@ export class Identifiers { moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.EMPTY_MAP }; - - static pureProxies = [ + static createRenderElement: IdentifierSpec = { + name: 'createRenderElement', + moduleUrl: VIEW_UTILS_MODULE_URL, + runtime: view_utils.createRenderElement + }; + static selectOrCreateRenderHostElement: IdentifierSpec = { + name: 'selectOrCreateRenderHostElement', + moduleUrl: VIEW_UTILS_MODULE_URL, + runtime: view_utils.selectOrCreateRenderHostElement + }; + static pureProxies: IdentifierSpec[] = [ null, {name: 'pureProxy1', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy1}, {name: 'pureProxy2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy2}, @@ -284,6 +292,34 @@ export class Identifiers { moduleUrl: assetUrl('core', 'animation/animation_transition'), runtime: AnimationTransition }; + + // This is just the interface! + static FastArray: + IdentifierSpec = {name: 'FastArray', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: null}; + static fastArrays: IdentifierSpec[] = [ + {name: 'FastArray2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.FastArray2}, + {name: 'FastArray4', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.FastArray4}, + {name: 'FastArray8', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.FastArray8}, + {name: 'FastArray16', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.FastArray16}, + ]; + static EMPTY_FAST_ARRAY: IdentifierSpec = { + name: 'EMPTY_FAST_ARRAY', + moduleUrl: VIEW_UTILS_MODULE_URL, + runtime: view_utils.EMPTY_FAST_ARRAY + }; + static FastArrayDynamic: IdentifierSpec = { + name: 'FastArrayDynamic', + moduleUrl: VIEW_UTILS_MODULE_URL, + runtime: view_utils.FastArrayDynamic + }; +} + +export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string { + if (path == null) { + return `asset:@angular/lib/${pkg}/index`; + } else { + return `asset:@angular/lib/${pkg}/src/${path}`; + } } export function resolveIdentifier(identifier: IdentifierSpec) { diff --git a/modules/@angular/compiler/src/ng_module_compiler.ts b/modules/@angular/compiler/src/ng_module_compiler.ts index 3573247cb9..3bb1f49b1c 100644 --- a/modules/@angular/compiler/src/ng_module_compiler.ts +++ b/modules/@angular/compiler/src/ng_module_compiler.ts @@ -9,6 +9,7 @@ import {Injectable} from '@angular/core'; import {CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTokenMetadata} from './compile_metadata'; +import {createDiTokenExpression} from './compiler_util/identifier_util'; import {isPresent} from './facade/lang'; import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers'; import * as o from './output/output_ast'; @@ -17,7 +18,6 @@ import {ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util'; import {LifecycleHooks} from './private_import_core'; import {NgModuleProviderAnalyzer} from './provider_analyzer'; import {ProviderAst} from './template_parser/template_ast'; -import {createDiTokenExpression} from './util'; export class ComponentFactoryDependency { constructor( diff --git a/modules/@angular/compiler/src/util.ts b/modules/@angular/compiler/src/util.ts index 7147cf6035..901bb383a3 100644 --- a/modules/@angular/compiler/src/util.ts +++ b/modules/@angular/compiler/src/util.ts @@ -6,9 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {CompileTokenMetadata} from './compile_metadata'; -import {isBlank, isPresent, isPrimitive, isStrictStringMap} from './facade/lang'; -import * as o from './output/output_ast'; +import {isBlank, isPrimitive, isStrictStringMap} from './facade/lang'; export const MODULE_SUFFIX = ''; @@ -72,25 +70,6 @@ export class ValueTransformer implements ValueVisitor { visitOther(value: any, context: any): any { return value; } } -export function assetUrl(pkg: string, path: string = null, type: string = 'src'): string { - if (path == null) { - return `asset:@angular/lib/${pkg}/index`; - } else { - return `asset:@angular/lib/${pkg}/src/${path}`; - } -} - -export function createDiTokenExpression(token: CompileTokenMetadata): o.Expression { - if (isPresent(token.value)) { - return o.literal(token.value); - } else if (token.identifierIsInstance) { - return o.importExpr(token.identifier) - .instantiate([], o.importType(token.identifier, [], [o.TypeModifier.Const])); - } else { - return o.importExpr(token.identifier); - } -} - export class SyncAsyncResult { constructor(public syncResult: T, public asyncResult: Promise = null) { if (!asyncResult) { diff --git a/modules/@angular/compiler/src/view_compiler/compile_element.ts b/modules/@angular/compiler/src/view_compiler/compile_element.ts index 5b7733f25b..b1dda9d55d 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_element.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_element.ts @@ -8,6 +8,7 @@ import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileIdentifierMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata} from '../compile_metadata'; +import {createDiTokenExpression} from '../compiler_util/identifier_util'; import {DirectiveWrapperCompiler} from '../directive_wrapper_compiler'; import {MapWrapper} from '../facade/collection'; import {isPresent} from '../facade/lang'; @@ -15,7 +16,6 @@ import {Identifiers, identifierToken, resolveIdentifier, resolveIdentifierToken} import * as o from '../output/output_ast'; import {convertValueToOutputAst} from '../output/value_util'; import {ProviderAst, ProviderAstType, ReferenceAst, TemplateAst} from '../template_parser/template_ast'; -import {createDiTokenExpression} from '../util'; import {CompileMethod} from './compile_method'; import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query'; diff --git a/modules/@angular/compiler/src/view_compiler/util.ts b/modules/@angular/compiler/src/view_compiler/util.ts index 42921b7385..2649a55c7f 100644 --- a/modules/@angular/compiler/src/view_compiler/util.ts +++ b/modules/@angular/compiler/src/view_compiler/util.ts @@ -8,10 +8,10 @@ import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata'; +import {createDiTokenExpression} from '../compiler_util/identifier_util'; import {isPresent} from '../facade/lang'; import {Identifiers, resolveIdentifier} from '../identifiers'; import * as o from '../output/output_ast'; -import {createDiTokenExpression} from '../util'; import {CompileView} from './compile_view'; diff --git a/modules/@angular/compiler/src/view_compiler/view_builder.ts b/modules/@angular/compiler/src/view_compiler/view_builder.ts index 87ae787443..3a403ff442 100644 --- a/modules/@angular/compiler/src/view_compiler/view_builder.ts +++ b/modules/@angular/compiler/src/view_compiler/view_builder.ts @@ -9,12 +9,12 @@ import {ViewEncapsulation} from '@angular/core'; import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata'; +import {createDiTokenExpression, createFastArray} from '../compiler_util/identifier_util'; import {isPresent} from '../facade/lang'; import {Identifiers, identifierToken, resolveIdentifier} from '../identifiers'; import * as o from '../output/output_ast'; import {ChangeDetectorStatus, ViewType, isDefaultChangeDetectionStrategy} from '../private_import_core'; import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast'; -import {createDiTokenExpression} from '../util'; import {CompileElement, CompileNode} from './compile_element'; import {CompileView} from './compile_view'; @@ -156,19 +156,29 @@ class ViewBuilderVisitor implements TemplateAstVisitor { visitElement(ast: ElementAst, parent: CompileElement): any { var nodeIndex = this.view.nodes.length; - var createRenderNodeExpr: o.InvokeMethodExpr; + var createRenderNodeExpr: o.Expression; var debugContextExpr = this.view.createMethod.resetDebugInfoExpr(nodeIndex, ast); - if (nodeIndex === 0 && this.view.viewType === ViewType.HOST) { - createRenderNodeExpr = o.THIS_EXPR.callMethod( - 'selectOrCreateHostElement', [o.literal(ast.name), rootSelectorVar, debugContextExpr]); + var directives = ast.directives.map(directiveAst => directiveAst.directive); + var component = directives.find(directive => directive.isComponent); + if (ast.name === NG_CONTAINER_TAG) { + createRenderNodeExpr = ViewProperties.renderer.callMethod( + 'createTemplateAnchor', [this._getParentRenderNode(parent), debugContextExpr]); } else { - if (ast.name === NG_CONTAINER_TAG) { - createRenderNodeExpr = ViewProperties.renderer.callMethod( - 'createTemplateAnchor', [this._getParentRenderNode(parent), debugContextExpr]); + const htmlAttrs = _readHtmlAttrs(ast.attrs); + const attrNameAndValues = createFastArray( + _mergeHtmlAndDirectiveAttrs(htmlAttrs, directives).map(v => o.literal(v))); + if (nodeIndex === 0 && this.view.viewType === ViewType.HOST) { + createRenderNodeExpr = + o.importExpr(resolveIdentifier(Identifiers.selectOrCreateRenderHostElement)).callFn([ + ViewProperties.renderer, o.literal(ast.name), attrNameAndValues, rootSelectorVar, + debugContextExpr + ]); } else { - createRenderNodeExpr = ViewProperties.renderer.callMethod( - 'createElement', - [this._getParentRenderNode(parent), o.literal(ast.name), debugContextExpr]); + createRenderNodeExpr = + o.importExpr(resolveIdentifier(Identifiers.createRenderElement)).callFn([ + ViewProperties.renderer, this._getParentRenderNode(parent), o.literal(ast.name), + attrNameAndValues, debugContextExpr + ]); } } var fieldName = `_el_${nodeIndex}`; @@ -178,22 +188,6 @@ class ViewBuilderVisitor implements TemplateAstVisitor { var renderNode = o.THIS_EXPR.prop(fieldName); - var directives = ast.directives.map(directiveAst => directiveAst.directive); - var component = directives.find(directive => directive.isComponent); - var htmlAttrs = _readHtmlAttrs(ast.attrs); - var attrNameAndValues = _mergeHtmlAndDirectiveAttrs(htmlAttrs, directives); - for (var i = 0; i < attrNameAndValues.length; i++) { - const attrName = attrNameAndValues[i][0]; - if (ast.name !== NG_CONTAINER_TAG) { - // are not rendered in the DOM - const attrValue = attrNameAndValues[i][1]; - this.view.createMethod.addStmt( - ViewProperties.renderer - .callMethod( - 'setElementAttribute', [renderNode, o.literal(attrName), o.literal(attrValue)]) - .toStmt()); - } - } var compileElement = new CompileElement( parent, this.view, nodeIndex, renderNode, ast, component, directives, ast.providers, ast.hasViewContainer, false, ast.references, this.targetDependencies); @@ -328,18 +322,22 @@ function _isNgContainer(node: CompileNode, view: CompileView): boolean { function _mergeHtmlAndDirectiveAttrs( - declaredHtmlAttrs: {[key: string]: string}, - directives: CompileDirectiveMetadata[]): string[][] { - var result: {[key: string]: string} = {}; - Object.keys(declaredHtmlAttrs).forEach(key => { result[key] = declaredHtmlAttrs[key]; }); + declaredHtmlAttrs: {[key: string]: string}, directives: CompileDirectiveMetadata[]): string[] { + const mapResult: {[key: string]: string} = {}; + Object.keys(declaredHtmlAttrs).forEach(key => { mapResult[key] = declaredHtmlAttrs[key]; }); directives.forEach(directiveMeta => { Object.keys(directiveMeta.hostAttributes).forEach(name => { const value = directiveMeta.hostAttributes[name]; - var prevValue = result[name]; - result[name] = isPresent(prevValue) ? mergeAttributeValue(name, prevValue, value) : value; + const prevValue = mapResult[name]; + mapResult[name] = isPresent(prevValue) ? mergeAttributeValue(name, prevValue, value) : value; }); }); - return mapToKeyValueArray(result); + const arrResult: string[] = []; + // Note: We need to sort to get a defined output order + // for tests and for caching generated artifacts... + Object.keys(mapResult).sort().forEach( + (attrName) => { arrResult.push(attrName, mapResult[attrName]); }); + return arrResult; } function _readHtmlAttrs(attrs: AttrAst[]): {[key: string]: string} { @@ -356,14 +354,6 @@ function mergeAttributeValue(attrName: string, attrValue1: string, attrValue2: s } } -function mapToKeyValueArray(data: {[key: string]: string}): string[][] { - var entryArray: string[][] = []; - Object.keys(data).forEach(name => { entryArray.push([name, data[name]]); }); - // We need to sort to get a defined output order - // for tests and for caching generated artifacts... - return entryArray.sort(); -} - function createViewTopLevelStmts(view: CompileView, targetStatements: o.Statement[]) { var nodeDebugInfosVar: o.Expression = o.NULL_EXPR; if (view.genConfig.genDebugInfo) { diff --git a/modules/@angular/compiler/test/output/output_emitter_codegen_typed.ts b/modules/@angular/compiler/test/output/output_emitter_codegen_typed.ts index d614cc5160..99351a4ca3 100644 --- a/modules/@angular/compiler/test/output/output_emitter_codegen_typed.ts +++ b/modules/@angular/compiler/test/output/output_emitter_codegen_typed.ts @@ -11,7 +11,7 @@ import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter'; import {print} from '../../src/facade/lang'; -import {assetUrl} from '../../src/util'; +import {assetUrl} from '../../src/identifiers'; function unimplemented(): any { throw new Error('unimplemented'); diff --git a/modules/@angular/compiler/test/output/output_emitter_codegen_untyped.ts b/modules/@angular/compiler/test/output/output_emitter_codegen_untyped.ts index 2e36343b30..c6e8dead18 100644 --- a/modules/@angular/compiler/test/output/output_emitter_codegen_untyped.ts +++ b/modules/@angular/compiler/test/output/output_emitter_codegen_untyped.ts @@ -10,7 +10,7 @@ import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter'; import {print} from '../../src/facade/lang'; -import {assetUrl} from '../../src/util'; +import {assetUrl} from '../../src/identifiers'; import {SimpleJsImportGenerator, codegenExportsVars, codegenStmts} from './output_emitter_util'; diff --git a/modules/@angular/compiler/test/output/output_emitter_util.ts b/modules/@angular/compiler/test/output/output_emitter_util.ts index 7e8944abb6..f33b2e54f4 100644 --- a/modules/@angular/compiler/test/output/output_emitter_util.ts +++ b/modules/@angular/compiler/test/output/output_emitter_util.ts @@ -7,9 +7,9 @@ */ import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata'; +import {assetUrl} from '@angular/compiler/src/identifiers'; import * as o from '@angular/compiler/src/output/output_ast'; import {ImportGenerator} from '@angular/compiler/src/output/path_util'; -import {assetUrl} from '@angular/compiler/src/util'; import {EventEmitter} from '@angular/core'; import {BaseError} from '@angular/core/src/facade/errors'; import {ViewType} from '@angular/core/src/linker/view_type'; diff --git a/modules/@angular/core/src/linker/view.ts b/modules/@angular/core/src/linker/view.ts index b46b5cea1a..1ff412a50b 100644 --- a/modules/@angular/core/src/linker/view.ts +++ b/modules/@angular/core/src/linker/view.ts @@ -113,17 +113,6 @@ export abstract class AppView { } } - selectOrCreateHostElement( - elementName: string, rootSelectorOrNode: string|any, debugInfo: RenderDebugInfo): any { - var hostElement: any; - if (isPresent(rootSelectorOrNode)) { - hostElement = this.renderer.selectRootElement(rootSelectorOrNode, debugInfo); - } else { - hostElement = this.renderer.createElement(null, elementName, debugInfo); - } - return hostElement; - } - injectorGet(token: any, nodeIndex: number, notFoundResult: any): any { return this.injectorGetInternal(token, nodeIndex, notFoundResult); } diff --git a/modules/@angular/core/src/linker/view_utils.ts b/modules/@angular/core/src/linker/view_utils.ts index cfee424837..83e380461c 100644 --- a/modules/@angular/core/src/linker/view_utils.ts +++ b/modules/@angular/core/src/linker/view_utils.ts @@ -12,7 +12,7 @@ import {UNINITIALIZED} from '../change_detection/change_detection_util'; import {Inject, Injectable} from '../di'; import {isPresent, looseIdentical} from '../facade/lang'; import {ViewEncapsulation} from '../metadata/view'; -import {RenderComponentType, Renderer, RootRenderer} from '../render/api'; +import {RenderComponentType, RenderDebugInfo, Renderer, RootRenderer} from '../render/api'; import {Sanitizer} from '../security'; import {AppElement} from './element'; @@ -377,3 +377,153 @@ const CAMEL_CASE_REGEXP = /([A-Z])/g; function camelCaseToDashCase(input: string): string { return input.replace(CAMEL_CASE_REGEXP, (...m: any[]) => '-' + m[1].toLowerCase()); } + +export function createRenderElement( + renderer: Renderer, parentElement: any, name: string, attrs: FastArray, + debugInfo?: RenderDebugInfo): any { + const el = renderer.createElement(parentElement, name, debugInfo); + for (var i = 0; i < attrs.length; i += 2) { + renderer.setElementAttribute(el, attrs.get(i), attrs.get(i + 1)); + } + return el; +} + +export function selectOrCreateRenderHostElement( + renderer: Renderer, elementName: string, attrs: FastArray, + rootSelectorOrNode: string | any, debugInfo: RenderDebugInfo): any { + var hostElement: any; + if (isPresent(rootSelectorOrNode)) { + hostElement = renderer.selectRootElement(rootSelectorOrNode, debugInfo); + } else { + hostElement = createRenderElement(renderer, null, elementName, attrs, debugInfo); + } + return hostElement; +} + +export interface FastArray { + length: number; + get(index: number): T; +} + +class FastArray0 implements FastArray { + length = 0; + get(index: number): any { return undefined; } +} + +export class FastArray2 implements FastArray { + constructor(public length: number, private _v0: T, private _v1: T) {} + get(index: number) { + switch (index) { + case 0: + return this._v0; + case 1: + return this._v1; + default: + return undefined; + } + } +} + +export class FastArray4 implements FastArray { + constructor( + public length: number, private _v0: T, private _v1: T, private _v2: T, private _v3: T) {} + get(index: number) { + switch (index) { + case 0: + return this._v0; + case 1: + return this._v1; + case 2: + return this._v2; + case 3: + return this._v3; + default: + return undefined; + } + } +} + +export class FastArray8 implements FastArray { + constructor( + public length: number, private _v0: T, private _v1: T, private _v2: T, private _v3: T, + private _v4: T, private _v5: T, private _v6: T, private _v7: T) {} + get(index: number) { + switch (index) { + case 0: + return this._v0; + case 1: + return this._v1; + case 2: + return this._v2; + case 3: + return this._v3; + case 4: + return this._v4; + case 5: + return this._v5; + case 6: + return this._v6; + case 7: + return this._v7; + default: + return undefined; + } + } +} + +export class FastArray16 implements FastArray { + constructor( + public length: number, private _v0: T, private _v1: T, private _v2: T, private _v3: T, + private _v4: T, private _v5: T, private _v6: T, private _v7: T, private _v8: T, + private _v9: T, private _v10: T, private _v11: T, private _v12: T, private _v13: T, + private _v14: T, private _v15: T) {} + get(index: number) { + switch (index) { + case 0: + return this._v0; + case 1: + return this._v1; + case 2: + return this._v2; + case 3: + return this._v3; + case 4: + return this._v4; + case 5: + return this._v5; + case 6: + return this._v6; + case 7: + return this._v7; + case 8: + return this._v8; + case 9: + return this._v9; + case 10: + return this._v10; + case 11: + return this._v11; + case 12: + return this._v12; + case 13: + return this._v13; + case 14: + return this._v14; + case 15: + return this._v15; + default: + return undefined; + } + } +} + +export class FastArrayDynamic implements FastArray { + private _values: any[]; + // Note: We still take the length argument so this class can be created + // in the same ways as the other classes! + constructor(public length: number, ...values: any[]) { this._values = values; } + + get(index: number) { return this._values[index]; } +} + +export const EMPTY_FAST_ARRAY: FastArray = new FastArray0(); diff --git a/modules/benchmarks/src/tree/ng2_ftl/tree_host.ngfactory.ts b/modules/benchmarks/src/tree/ng2_ftl/tree_host.ngfactory.ts index 93545376f8..e7659ffb48 100644 --- a/modules/benchmarks/src/tree/ng2_ftl/tree_host.ngfactory.ts +++ b/modules/benchmarks/src/tree/ng2_ftl/tree_host.ngfactory.ts @@ -33,7 +33,8 @@ class _View_TreeComponent_Host0 extends import1.AppView { parentInjector, declarationEl, import7.ChangeDetectorStatus.CheckAlways); } createInternal(rootSelector: string): import2.AppElement { - this._el_0 = this.selectOrCreateHostElement('tree', rootSelector, (null as any)); + this._el_0 = import4.selectOrCreateRenderHostElement( + this.renderer, 'tree', import4.EMPTY_FAST_ARRAY, rootSelector, (null as any)); this._vc_0 = new import2.AppElement(0, (null as any), this, this._el_0); this._TreeComponent_0_4 = new _View_TreeComponent0(this._el_0); this._vc_0.initComponent(this._TreeComponent_0_4.context, [], this._TreeComponent_0_4); diff --git a/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts b/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts index 18d11c830c..1573bedda0 100644 --- a/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts +++ b/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts @@ -35,7 +35,8 @@ class _View_TreeRootComponent_Host0 extends import1.AppView { viewUtils, parentInjector, declarationEl, import7.ChangeDetectorStatus.CheckAlways); } createInternal(rootSelector: string): import2.AppElement { - this._el_0 = this.selectOrCreateHostElement('tree', rootSelector, (null as any)); + this._el_0 = import4.selectOrCreateRenderHostElement( + this.renderer, 'tree', import4.EMPTY_FAST_ARRAY, rootSelector, (null as any)); this._appEl_0 = new import2.AppElement(0, (null as any), this, this._el_0); var compView_0: any = viewFactory_TreeRootComponent0(this.viewUtils, this.injector(0), this._appEl_0);