From 64770571b2a02cf6614672468e23c7dc8196fb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=A1ko=20Hevery?= Date: Thu, 15 Aug 2019 13:42:17 -0700 Subject: [PATCH] perf: don't create holey arrays (#32155) Don't use `Array` constructor with the size value (ex. `new Array(5)`) - this will create a `HOLEY_ELEMENTS` array (even if this array is filled in later on!); https://v8.dev/blog/elements-kinds https://stackoverflow.com/questions/32054170/how-to-resize-an-array PR Close #32155 --- .../src/largetable/baseline/table.ts | 4 +- .../src/old/compiler/compiler_benchmark.ts | 2 +- modules/benchmarks/src/old/costs/index.ts | 2 +- modules/benchmarks/src/tree/baseline/tree.ts | 4 +- modules/benchmarks/src/tree/util.ts | 10 +++++ packages/bazel/src/ng_package/packager.ts | 12 +++++- packages/compiler/src/aot/compiler.ts | 5 +-- .../compiler/src/expression_parser/ast.ts | 4 +- packages/compiler/src/i18n/digest.ts | 9 +++-- .../src/template_parser/template_parser.ts | 4 +- packages/compiler/src/util.ts | 10 +++++ packages/compiler/test/aot/test_util.ts | 3 +- .../compiler/test/output/js_emitter_spec.ts | 3 +- .../compiler/test/output/output_jit_spec.ts | 5 ++- .../compiler/test/output/ts_emitter_spec.ts | 4 +- .../template_parser/template_parser_spec.ts | 4 +- packages/core/src/di/r3_injector.ts | 5 +-- packages/core/src/di/reflective_injector.ts | 8 ++-- .../src/reflection/reflection_capabilities.ts | 8 ++-- .../src/render3/instructions/projection.ts | 3 +- packages/core/src/render3/query.ts | 11 +++--- packages/core/src/util/array_utils.ts | 10 +++++ packages/core/src/view/element.ts | 4 +- packages/core/src/view/ng_module.ts | 7 ++-- packages/core/src/view/provider.ts | 8 ++-- packages/core/src/view/pure_expression.ts | 38 ++++++++++--------- packages/core/src/view/text.ts | 2 +- .../injection/bundle.golden_symbols.json | 3 ++ .../src/browser/browser_adapter.ts | 2 +- .../shared/service_message_broker.ts | 2 +- packages/service-worker/cli/sha1.ts | 12 +++--- packages/service-worker/worker/src/sha1.ts | 12 +++--- 32 files changed, 137 insertions(+), 83 deletions(-) diff --git a/modules/benchmarks/src/largetable/baseline/table.ts b/modules/benchmarks/src/largetable/baseline/table.ts index 4950e5b2d7..8dc74f21c2 100644 --- a/modules/benchmarks/src/largetable/baseline/table.ts +++ b/modules/benchmarks/src/largetable/baseline/table.ts @@ -50,12 +50,12 @@ export class TableComponent { this._rootEl.appendChild(table); const tbody = document.createElement('tbody'); table.appendChild(tbody); - this._renderCells = new Array(data.length); + this._renderCells = []; for (let r = 0; r < data.length; r++) { const dataRow = data[r]; const tr = document.createElement('tr'); tbody.appendChild(tr); - const renderRow = new Array(dataRow.length); + const renderRow = []; this._renderCells[r] = renderRow; for (let c = 0; c < dataRow.length; c++) { const dataCell = dataRow[c]; diff --git a/modules/benchmarks/src/old/compiler/compiler_benchmark.ts b/modules/benchmarks/src/old/compiler/compiler_benchmark.ts index ce86f687fd..51cf1d0ffa 100644 --- a/modules/benchmarks/src/old/compiler/compiler_benchmark.ts +++ b/modules/benchmarks/src/old/compiler/compiler_benchmark.ts @@ -75,7 +75,7 @@ class MultiplyDirectiveResolver extends DirectiveResolver { private _fillCache(component: Type) { const view = super.resolve(component); - const multipliedTemplates = new Array(this._multiplyBy); + const multipliedTemplates = []; for (let i = 0; i < this._multiplyBy; ++i) { multipliedTemplates[i] = view.template; } diff --git a/modules/benchmarks/src/old/costs/index.ts b/modules/benchmarks/src/old/costs/index.ts index f36e457278..74023d5610 100644 --- a/modules/benchmarks/src/old/costs/index.ts +++ b/modules/benchmarks/src/old/costs/index.ts @@ -18,7 +18,7 @@ let testList = null; export function main() { const size = getIntParameter('size'); - testList = new Array(size); + testList = []; platformBrowserDynamic().bootstrapModule(AppModule).then((ref) => { const injector = ref.injector; diff --git a/modules/benchmarks/src/tree/baseline/tree.ts b/modules/benchmarks/src/tree/baseline/tree.ts index adf283b66c..8350018a60 100644 --- a/modules/benchmarks/src/tree/baseline/tree.ts +++ b/modules/benchmarks/src/tree/baseline/tree.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {TreeNode} from '../util'; +import {TreeNode, newArray} from '../util'; export class TreeComponent { private _renderNodes: any[]; @@ -25,7 +25,7 @@ export class TreeComponent { private _create(parentNode: any, dataNode: TreeNode, index: number) { if (!this._renderNodes) { - this._renderNodes = new Array(dataNode.transitiveChildCount); + this._renderNodes = newArray(dataNode.transitiveChildCount); } const span = document.createElement('span'); diff --git a/modules/benchmarks/src/tree/util.ts b/modules/benchmarks/src/tree/util.ts index 6f8f596258..90d475ad05 100644 --- a/modules/benchmarks/src/tree/util.ts +++ b/modules/benchmarks/src/tree/util.ts @@ -68,3 +68,13 @@ export function flattenTree(node: TreeNode, target: TreeNode[] = []): TreeNode[] } return target; } + +export function newArray(size: number): T[]; +export function newArray(size: number, value: T): T[]; +export function newArray(size: number, value?: T): T[] { + const list: T[] = []; + for (let i = 0; i < size; i++) { + list.push(value !); + } + return list; +} \ No newline at end of file diff --git a/packages/bazel/src/ng_package/packager.ts b/packages/bazel/src/ng_package/packager.ts index 41cc9842a8..db7e85b233 100644 --- a/packages/bazel/src/ng_package/packager.ts +++ b/packages/bazel/src/ng_package/packager.ts @@ -335,7 +335,7 @@ function main(args: string[]): number { const parts = packageName.split('/'); // Remove the scoped package part, like @angular if present const nameParts = packageName.startsWith('@') ? parts.splice(1) : parts; - const relativePath = Array(nameParts.length - 1).fill('..').join('/') || '.'; + const relativePath = newArray(nameParts.length - 1, '..').join('/') || '.'; let basename: string; if (dir === 'bundles') { basename = nameParts.join('-') + '.umd'; @@ -435,3 +435,13 @@ export * from '${srcDirRelative(inputPath, typingsFile.replace(/\.d\.tsx?$/, '') if (require.main === module) { process.exitCode = main(process.argv.slice(2)); } + +export function newArray(size: number): T[]; +export function newArray(size: number, value: T): T[]; +export function newArray(size: number, value?: T): T[] { + const list: T[] = []; + for (let i = 0; i < size; i++) { + list.push(value !); + } + return list; +} \ No newline at end of file diff --git a/packages/compiler/src/aot/compiler.ts b/packages/compiler/src/aot/compiler.ts index 5a3f0c3278..255d2c0581 100644 --- a/packages/compiler/src/aot/compiler.ts +++ b/packages/compiler/src/aot/compiler.ts @@ -14,7 +14,6 @@ import {MessageBundle} from '../i18n/message_bundle'; import {Identifiers, createTokenForExternalReference} from '../identifiers'; import {InjectableCompiler} from '../injectable_compiler'; import {CompileMetadataResolver} from '../metadata_resolver'; -import * as html from '../ml_parser/ast'; import {HtmlParser} from '../ml_parser/html_parser'; import {removeWhitespaces} from '../ml_parser/html_whitespaces'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../ml_parser/interpolation_config'; @@ -32,7 +31,7 @@ import {SummaryResolver} from '../summary_resolver'; import {BindingParser} from '../template_parser/binding_parser'; import {TemplateAst} from '../template_parser/template_ast'; import {TemplateParser} from '../template_parser/template_parser'; -import {OutputContext, ValueVisitor, error, syntaxError, visitValue} from '../util'; +import {OutputContext, ValueVisitor, error, newArray, syntaxError, visitValue} from '../util'; import {TypeCheckCompiler} from '../view_compiler/type_check_compiler'; import {ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler'; @@ -690,7 +689,7 @@ export class AotCompiler { const suppliedTypeParams = typeParams || []; const missingTypeParamsCount = arity - suppliedTypeParams.length; const allTypeParams = - suppliedTypeParams.concat(new Array(missingTypeParamsCount).fill(o.DYNAMIC_TYPE)); + suppliedTypeParams.concat(newArray(missingTypeParamsCount, o.DYNAMIC_TYPE)); return members.reduce( (expr, memberName) => expr.prop(memberName), o.importExpr( diff --git a/packages/compiler/src/expression_parser/ast.ts b/packages/compiler/src/expression_parser/ast.ts index 084de03945..0ae7cc4e8f 100644 --- a/packages/compiler/src/expression_parser/ast.ts +++ b/packages/compiler/src/expression_parser/ast.ts @@ -436,7 +436,7 @@ export class AstTransformer implements AstVisitor { } visitAll(asts: any[]): any[] { - const res = new Array(asts.length); + const res = []; for (let i = 0; i < asts.length; ++i) { res[i] = asts[i].visit(this); } @@ -598,7 +598,7 @@ export class AstMemoryEfficientTransformer implements AstVisitor { } visitAll(asts: any[]): any[] { - const res = new Array(asts.length); + const res = []; let modified = false; for (let i = 0; i < asts.length; ++i) { const original = asts[i]; diff --git a/packages/compiler/src/i18n/digest.ts b/packages/compiler/src/i18n/digest.ts index c60b853fb2..459461715d 100644 --- a/packages/compiler/src/i18n/digest.ts +++ b/packages/compiler/src/i18n/digest.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {utf8Encode} from '../util'; +import {newArray, utf8Encode} from '../util'; import * as i18n from './i18n_ast'; @@ -93,7 +93,7 @@ export function sha1(str: string): string { const words32 = stringToWords32(utf8, Endian.Big); const len = utf8.length * 8; - const w = new Array(80); + const w = newArray(80); let [a, b, c, d, e]: number[] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; words32[len >> 5] |= 0x80 << (24 - len % 32); @@ -247,9 +247,10 @@ function rol64([hi, lo]: [number, number], count: number): [number, number] { } function stringToWords32(str: string, endian: Endian): number[] { - const words32 = Array((str.length + 3) >>> 2); + const size = (str.length + 3) >>> 2; + const words32 = []; - for (let i = 0; i < words32.length; i++) { + for (let i = 0; i < size; i++) { words32[i] = wordAt(str, i * 4, endian); } diff --git a/packages/compiler/src/template_parser/template_parser.ts b/packages/compiler/src/template_parser/template_parser.ts index 29bf328be5..e17cf35ea6 100644 --- a/packages/compiler/src/template_parser/template_parser.ts +++ b/packages/compiler/src/template_parser/template_parser.ts @@ -24,7 +24,7 @@ import {ProviderElementContext, ProviderViewContext} from '../provider_analyzer' import {ElementSchemaRegistry} from '../schema/element_schema_registry'; import {CssSelector, SelectorMatcher} from '../selector'; import {isStyleUrlResolvable} from '../style_url_resolver'; -import {Console, syntaxError} from '../util'; +import {Console, newArray, syntaxError} from '../util'; import {BindingParser} from './binding_parser'; import * as t from './template_ast'; @@ -528,7 +528,7 @@ class TemplateParseVisitor implements html.Visitor { // Need to sort the directives so that we get consistent results throughout, // as selectorMatcher uses Maps inside. // Also deduplicate directives as they might match more than one time! - const directives = new Array(this.directivesIndex.size); + const directives = newArray(this.directivesIndex.size); // Whether any directive selector matches on the element name let matchElement = false; diff --git a/packages/compiler/src/util.ts b/packages/compiler/src/util.ts index d6bba8ca32..e0e5c1d11a 100644 --- a/packages/compiler/src/util.ts +++ b/packages/compiler/src/util.ts @@ -253,3 +253,13 @@ const __global = typeof global !== 'undefined' && global; // should be __global in that case. const _global: {[name: string]: any} = __global || __window || __self; export {_global as global}; + +export function newArray(size: number): T[]; +export function newArray(size: number, value: T): T[]; +export function newArray(size: number, value?: T): T[] { + const list: T[] = []; + for (let i = 0; i < size; i++) { + list.push(value !); + } + return list; +} \ No newline at end of file diff --git a/packages/compiler/test/aot/test_util.ts b/packages/compiler/test/aot/test_util.ts index 788ed4184e..f516d6f300 100644 --- a/packages/compiler/test/aot/test_util.ts +++ b/packages/compiler/test/aot/test_util.ts @@ -10,6 +10,7 @@ import {AotCompilerHost, AotCompilerOptions, GeneratedFile, createAotCompiler, t import {MetadataBundlerHost} from '@angular/compiler-cli/src/metadata/bundler'; import {MetadataCollector} from '@angular/compiler-cli/src/metadata/collector'; import {ModuleMetadata} from '@angular/compiler-cli/src/metadata/index'; +import {newArray} from '@angular/compiler/src/util'; import * as fs from 'fs'; import * as path from 'path'; import * as ts from 'typescript'; @@ -686,7 +687,7 @@ export function expectNoDiagnostics(program: ts.Program) { return ''; } - function chars(len: number, ch: string): string { return new Array(len).fill(ch).join(''); } + function chars(len: number, ch: string): string { return newArray(len, ch).join(''); } function lineNoOf(offset: number, text: string): number { let result = 1; diff --git a/packages/compiler/test/output/js_emitter_spec.ts b/packages/compiler/test/output/js_emitter_spec.ts index 184cb615e9..e38e310ba5 100644 --- a/packages/compiler/test/output/js_emitter_spec.ts +++ b/packages/compiler/test/output/js_emitter_spec.ts @@ -9,6 +9,7 @@ import {StaticSymbol} from '@angular/compiler/src/aot/static_symbol'; import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter'; import * as o from '@angular/compiler/src/output/output_ast'; +import {newArray} from '@angular/compiler/src/util'; import {stripSourceMapAndNewLine} from './abstract_emitter_spec'; @@ -108,7 +109,7 @@ const externalModuleIdentifier = new o.ExternalReference(anotherModuleUrl, 'some }); it('should break expressions into multiple lines if they are too long', () => { - const values: o.Expression[] = new Array(100); + const values: o.Expression[] = newArray(100); values.fill(o.literal(1)); values.splice(50, 0, o.fn([], [new o.ReturnStatement(o.literal(1))])); expect(emitStmt(o.variable('fn').callFn(values).toStmt())).toEqual([ diff --git a/packages/compiler/test/output/output_jit_spec.ts b/packages/compiler/test/output/output_jit_spec.ts index 5ec18c3eb5..eadc9292c5 100644 --- a/packages/compiler/test/output/output_jit_spec.ts +++ b/packages/compiler/test/output/output_jit_spec.ts @@ -10,6 +10,7 @@ import {EmitterVisitorContext} from '@angular/compiler/src/output/abstract_emitt import * as o from '@angular/compiler/src/output/output_ast'; import {JitEmitterVisitor, JitEvaluator} from '@angular/compiler/src/output/output_jit'; import {R3JitReflector} from '@angular/compiler/src/render3/r3_jit'; +import {newArray} from '@angular/compiler/src/util'; import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_reflector'; const anotherModuleUrl = 'somePackage/someOtherPath'; @@ -18,10 +19,10 @@ const anotherModuleUrl = 'somePackage/someOtherPath'; describe('Output JIT', () => { describe('regression', () => { it('should generate unique argument names', () => { - const externalIds = new Array(10).fill(1).map( + const externalIds = newArray(10, 1).map( (_, index) => new o.ExternalReference(anotherModuleUrl, `id_${index}_`, {name: `id_${index}_`})); - const externalIds1 = new Array(10).fill(1).map( + const externalIds1 = newArray(10, 1).map( (_, index) => new o.ExternalReference( anotherModuleUrl, `id_${index}_1`, {name: `id_${index}_1`})); const ctx = EmitterVisitorContext.createRoot(); diff --git a/packages/compiler/test/output/ts_emitter_spec.ts b/packages/compiler/test/output/ts_emitter_spec.ts index e9f3c41a49..aa4b7ab649 100644 --- a/packages/compiler/test/output/ts_emitter_spec.ts +++ b/packages/compiler/test/output/ts_emitter_spec.ts @@ -10,6 +10,8 @@ import {StaticSymbol} from '@angular/compiler/src/aot/static_symbol'; import * as o from '@angular/compiler/src/output/output_ast'; import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter'; import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '@angular/compiler/src/parse_util'; +import {newArray} from '@angular/compiler/src/util'; + import {stripSourceMapAndNewLine} from './abstract_emitter_spec'; const someGenFilePath = 'somePackage/someGenFile'; @@ -160,7 +162,7 @@ const externalModuleIdentifier = new o.ExternalReference(anotherModuleUrl, 'some }); it('should break expressions into multiple lines if they are too long', () => { - const values: o.Expression[] = new Array(100); + const values: o.Expression[] = newArray(100); values.fill(o.literal(1)); values.splice(50, 0, o.fn([], [new o.ReturnStatement(o.literal(1))])); expect(emitStmt(o.variable('fn').callFn(values).toStmt())).toEqual([ diff --git a/packages/compiler/test/template_parser/template_parser_spec.ts b/packages/compiler/test/template_parser/template_parser_spec.ts index eca9eeac33..0d805187ec 100644 --- a/packages/compiler/test/template_parser/template_parser_spec.ts +++ b/packages/compiler/test/template_parser/template_parser_spec.ts @@ -19,7 +19,7 @@ import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_refle import {CompileEntryComponentMetadata, CompileStylesheetMetadata} from '../../src/compile_metadata'; import {Identifiers, createTokenForExternalReference, createTokenForReference} from '../../src/identifiers'; import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../src/ml_parser/interpolation_config'; -import {noUndefined} from '../../src/util'; +import {newArray, noUndefined} from '../../src/util'; import {MockSchemaRegistry} from '../../testing'; import {unparse} from '../expression_parser/utils/unparser'; import {TEST_COMPILER_PROVIDERS} from '../test_bindings'; @@ -481,7 +481,7 @@ class ArrayConsole implements Console { new BoundDirectivePropertyAst('foo', 'bar', null !, null !) ]; const result = templateVisitAll(visitor, nodes, null); - expect(result).toEqual(new Array(nodes.length).fill(true)); + expect(result).toEqual(newArray(nodes.length).fill(true)); }); }); diff --git a/packages/core/src/di/r3_injector.ts b/packages/core/src/di/r3_injector.ts index f3ed6489d5..f3271c2b98 100644 --- a/packages/core/src/di/r3_injector.ts +++ b/packages/core/src/di/r3_injector.ts @@ -11,9 +11,8 @@ import '../util/ng_dev_mode'; import {OnDestroy} from '../interface/lifecycle_hooks'; import {Type} from '../interface/type'; import {throwCyclicDependencyError, throwInvalidProviderError, throwMixedMultiProviderError} from '../render3/errors'; -import {deepForEach} from '../util/array_utils'; +import {deepForEach, newArray} from '../util/array_utils'; import {stringify} from '../util/stringify'; - import {resolveForwardRef} from './forward_ref'; import {InjectionToken} from './injection_token'; import {Injector} from './injector'; @@ -428,7 +427,7 @@ function getUndecoratedInjectableFactory(token: Function) { // If the token has parameters then it has dependencies that we cannot resolve implicitly. const paramLength = token.length; if (paramLength > 0) { - const args: string[] = new Array(paramLength).fill('?'); + const args: string[] = newArray(paramLength, '?'); throw new Error(`Can't resolve all parameters for ${stringify(token)}: (${args.join(', ')}).`); } diff --git a/packages/core/src/di/reflective_injector.ts b/packages/core/src/di/reflective_injector.ts index 20ba0c39cf..ee7aaab217 100644 --- a/packages/core/src/di/reflective_injector.ts +++ b/packages/core/src/di/reflective_injector.ts @@ -288,8 +288,8 @@ export class ReflectiveInjector_ implements ReflectiveInjector { const len = _providers.length; - this.keyIds = new Array(len); - this.objs = new Array(len); + this.keyIds = []; + this.objs = []; for (let i = 0; i < len; i++) { this.keyIds[i] = _providers[i].key.id; @@ -339,7 +339,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector { private _instantiateProvider(provider: ResolvedReflectiveProvider): any { if (provider.multiProvider) { - const res = new Array(provider.resolvedFactories.length); + const res = []; for (let i = 0; i < provider.resolvedFactories.length; ++i) { res[i] = this._instantiate(provider, provider.resolvedFactories[i]); } @@ -455,7 +455,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector { } function _mapProviders(injector: ReflectiveInjector_, fn: Function): any[] { - const res: any[] = new Array(injector._providers.length); + const res: any[] = []; for (let i = 0; i < injector._providers.length; ++i) { res[i] = fn(injector.getProviderAtIndex(i)); } diff --git a/packages/core/src/reflection/reflection_capabilities.ts b/packages/core/src/reflection/reflection_capabilities.ts index baadf9a404..0aac8ca00c 100644 --- a/packages/core/src/reflection/reflection_capabilities.ts +++ b/packages/core/src/reflection/reflection_capabilities.ts @@ -7,10 +7,10 @@ */ import {Type, isType} from '../interface/type'; +import {newArray} from '../util/array_utils'; import {ANNOTATIONS, PARAMETERS, PROP_METADATA} from '../util/decorators'; import {global} from '../util/global'; import {stringify} from '../util/stringify'; - import {PlatformReflectionCapabilities} from './platform_reflection_capabilities'; import {GetterFn, MethodFn, SetterFn} from './types'; @@ -53,9 +53,9 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities { let result: any[][]; if (typeof paramTypes === 'undefined') { - result = new Array(paramAnnotations.length); + result = newArray(paramAnnotations.length); } else { - result = new Array(paramTypes.length); + result = newArray(paramTypes.length); } for (let i = 0; i < result.length; i++) { @@ -120,7 +120,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities { // based on function.length. // Note: We know that this is a real constructor as we checked // the content of the constructor above. - return new Array((type.length)).fill(undefined); + return newArray(type.length); } parameters(type: Type): any[][] { diff --git a/packages/core/src/render3/instructions/projection.ts b/packages/core/src/render3/instructions/projection.ts index cbbd897602..291ca01ce1 100644 --- a/packages/core/src/render3/instructions/projection.ts +++ b/packages/core/src/render3/instructions/projection.ts @@ -5,6 +5,7 @@ * 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 {newArray} from '../../util/array_utils'; import {TAttributes, TElementNode, TNode, TNodeType} from '../interfaces/node'; import {ProjectionSlots} from '../interfaces/projection'; import {TVIEW, T_HOST} from '../interfaces/view'; @@ -81,7 +82,7 @@ export function ɵɵprojectionDef(projectionSlots?: ProjectionSlots): void { // projection slot with the wildcard selector. const numProjectionSlots = projectionSlots ? projectionSlots.length : 1; const projectionHeads: (TNode | null)[] = componentNode.projection = - new Array(numProjectionSlots).fill(null); + newArray(numProjectionSlots, null !as TNode); const tails: (TNode | null)[] = projectionHeads.slice(); let componentChild: TNode|null = componentNode.child; diff --git a/packages/core/src/render3/query.ts b/packages/core/src/render3/query.ts index 3f7a0ed0b9..ceb6701c7d 100644 --- a/packages/core/src/render3/query.ts +++ b/packages/core/src/render3/query.ts @@ -48,7 +48,7 @@ class LQueries_ implements LQueries { if (tQueries !== null) { const noOfInheritedQueries = tView.contentQueries !== null ? tView.contentQueries[0] : tQueries.length; - const viewLQueries: LQuery[] = new Array(noOfInheritedQueries); + const viewLQueries: LQuery[] = []; // An embedded view has queries propagated from a declaration view at the beginning of the // TQueries collection and up until a first content query declared in the embedded view. Only @@ -57,7 +57,7 @@ class LQueries_ implements LQueries { for (let i = 0; i < noOfInheritedQueries; i++) { const tQuery = tQueries.getByIndex(i); const parentLQuery = this.queries[tQuery.indexInDeclarationView]; - viewLQueries[i] = parentLQuery.clone(); + viewLQueries.push(parentLQuery.clone()); } return new LQueries_(viewLQueries); @@ -313,19 +313,18 @@ function materializeViewResults(lView: LView, tQuery: TQuery, queryIndex: num if (lQuery.matches === null) { const tViewData = lView[TVIEW].data; const tQueryMatches = tQuery.matches !; - const result: T|null[] = new Array(tQueryMatches.length / 2); + const result: T|null[] = []; for (let i = 0; i < tQueryMatches.length; i += 2) { const matchedNodeIdx = tQueryMatches[i]; if (matchedNodeIdx < 0) { // we at the marker which might have results in views created based on this // - those results will be in separate views though, so here we just leave // null as a placeholder - result[i / 2] = null; + result.push(null); } else { ngDevMode && assertDataInRange(tViewData, matchedNodeIdx); const tNode = tViewData[matchedNodeIdx] as TNode; - result[i / 2] = - createResultForNode(lView, tNode, tQueryMatches[i + 1], tQuery.metadata.read); + result.push(createResultForNode(lView, tNode, tQueryMatches[i + 1], tQuery.metadata.read)); } } lQuery.matches = result; diff --git a/packages/core/src/util/array_utils.ts b/packages/core/src/util/array_utils.ts index e7acac22b3..9587ae1dbf 100644 --- a/packages/core/src/util/array_utils.ts +++ b/packages/core/src/util/array_utils.ts @@ -60,4 +60,14 @@ export function removeFromArray(arr: any[], index: number): any { } else { return arr.splice(index, 1)[0]; } +} + +export function newArray(size: number): T[]; +export function newArray(size: number, value: T): T[]; +export function newArray(size: number, value?: T): T[] { + const list: T[] = []; + for (let i = 0; i < size; i++) { + list.push(value !); + } + return list; } \ No newline at end of file diff --git a/packages/core/src/view/element.ts b/packages/core/src/view/element.ts index 1cc299557c..ed4b9f71c0 100644 --- a/packages/core/src/view/element.ts +++ b/packages/core/src/view/element.ts @@ -73,7 +73,7 @@ export function elementDef( [ns, name] = splitNamespace(namespaceAndName); } bindings = bindings || []; - const bindingDefs: BindingDef[] = new Array(bindings.length); + const bindingDefs: BindingDef[] = []; for (let i = 0; i < bindings.length; i++) { const [bindingFlags, namespaceAndName, suffixOrSecurityContext] = bindings[i]; @@ -93,7 +93,7 @@ export function elementDef( {flags: bindingFlags, ns, name, nonMinifiedName: name, securityContext, suffix}; } outputs = outputs || []; - const outputDefs: OutputDef[] = new Array(outputs.length); + const outputDefs: OutputDef[] = []; for (let i = 0; i < outputs.length; i++) { const [target, eventName] = outputs[i]; outputDefs[i] = { diff --git a/packages/core/src/view/ng_module.ts b/packages/core/src/view/ng_module.ts index 6d064e91af..1c5626ce81 100644 --- a/packages/core/src/view/ng_module.ts +++ b/packages/core/src/view/ng_module.ts @@ -12,6 +12,7 @@ import {INJECTOR, setCurrentInjector} from '../di/injector_compatibility'; import {getInjectableDef, ɵɵInjectableDef} from '../di/interface/defs'; import {APP_ROOT} from '../di/scope'; import {NgModuleRef} from '../linker/ng_module_factory'; +import {newArray} from '../util/array_utils'; import {stringify} from '../util/stringify'; import {DepDef, DepFlags, NgModuleData, NgModuleDefinition, NgModuleProviderDef, NodeFlags} from './types'; @@ -65,7 +66,7 @@ export function moduleDef(providers: NgModuleProviderDef[]): NgModuleDefinition export function initNgModule(data: NgModuleData) { const def = data._def; - const providers = data._providers = new Array(def.providers.length); + const providers = data._providers = newArray(def.providers.length); for (let i = 0; i < def.providers.length; i++) { const provDef = def.providers[i]; if (!(provDef.flags & NodeFlags.LazyProvider)) { @@ -179,7 +180,7 @@ function _createClass(ngModule: NgModuleData, ctor: any, deps: DepDef[]): any { resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]), resolveNgModuleDep(ngModule, deps[2])); default: - const depValues = new Array(len); + const depValues = []; for (let i = 0; i < len; i++) { depValues[i] = resolveNgModuleDep(ngModule, deps[i]); } @@ -201,7 +202,7 @@ function _callFactory(ngModule: NgModuleData, factory: any, deps: DepDef[]): any resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]), resolveNgModuleDep(ngModule, deps[2])); default: - const depValues = Array(len); + const depValues = []; for (let i = 0; i < len; i++) { depValues[i] = resolveNgModuleDep(ngModule, deps[i]); } diff --git a/packages/core/src/view/provider.ts b/packages/core/src/view/provider.ts index 0774765dca..13cf82633c 100644 --- a/packages/core/src/view/provider.ts +++ b/packages/core/src/view/provider.ts @@ -278,9 +278,9 @@ function createClass( resolveDep(view, elDef, allowPrivateServices, deps[1]), resolveDep(view, elDef, allowPrivateServices, deps[2])); default: - const depValues = new Array(len); + const depValues = []; for (let i = 0; i < len; i++) { - depValues[i] = resolveDep(view, elDef, allowPrivateServices, deps[i]); + depValues.push(resolveDep(view, elDef, allowPrivateServices, deps[i])); } return new ctor(...depValues); } @@ -305,9 +305,9 @@ function callFactory( resolveDep(view, elDef, allowPrivateServices, deps[1]), resolveDep(view, elDef, allowPrivateServices, deps[2])); default: - const depValues = Array(len); + const depValues = []; for (let i = 0; i < len; i++) { - depValues[i] = resolveDep(view, elDef, allowPrivateServices, deps[i]); + depValues.push(resolveDep(view, elDef, allowPrivateServices, deps[i])); } return factory(...depValues); } diff --git a/packages/core/src/view/pure_expression.ts b/packages/core/src/view/pure_expression.ts index 8eb27f05b1..1cbcae3558 100644 --- a/packages/core/src/view/pure_expression.ts +++ b/packages/core/src/view/pure_expression.ts @@ -6,26 +6,28 @@ * found in the LICENSE file at https://angular.io/license */ +import {newArray} from '../util/array_utils'; + import {BindingDef, BindingFlags, NodeDef, NodeFlags, PureExpressionData, ViewData, asPureExpressionData} from './types'; import {calcBindingFlags, checkAndUpdateBinding} from './util'; export function purePipeDef(checkIndex: number, argCount: number): NodeDef { // argCount + 1 to include the pipe as first arg - return _pureExpressionDef(NodeFlags.TypePurePipe, checkIndex, new Array(argCount + 1)); + return _pureExpressionDef(NodeFlags.TypePurePipe, checkIndex, newArray(argCount + 1)); } export function pureArrayDef(checkIndex: number, argCount: number): NodeDef { - return _pureExpressionDef(NodeFlags.TypePureArray, checkIndex, new Array(argCount)); + return _pureExpressionDef(NodeFlags.TypePureArray, checkIndex, newArray(argCount)); } export function pureObjectDef(checkIndex: number, propToIndex: {[p: string]: number}): NodeDef { const keys = Object.keys(propToIndex); const nbKeys = keys.length; - const propertyNames = new Array(nbKeys); + const propertyNames = []; for (let i = 0; i < nbKeys; i++) { const key = keys[i]; const index = propToIndex[key]; - propertyNames[index] = key; + propertyNames.push(key); } return _pureExpressionDef(NodeFlags.TypePureObject, checkIndex, propertyNames); @@ -33,17 +35,17 @@ export function pureObjectDef(checkIndex: number, propToIndex: {[p: string]: num function _pureExpressionDef( flags: NodeFlags, checkIndex: number, propertyNames: string[]): NodeDef { - const bindings: BindingDef[] = new Array(propertyNames.length); + const bindings: BindingDef[] = []; for (let i = 0; i < propertyNames.length; i++) { const prop = propertyNames[i]; - bindings[i] = { + bindings.push({ flags: BindingFlags.TypeProperty, name: prop, ns: null, nonMinifiedName: prop, securityContext: null, suffix: null - }; + }); } return { // will bet set by the view definition @@ -99,17 +101,17 @@ export function checkAndUpdatePureExpressionInline( let value: any; switch (def.flags & NodeFlags.Types) { case NodeFlags.TypePureArray: - value = new Array(bindings.length); - if (bindLen > 0) value[0] = v0; - if (bindLen > 1) value[1] = v1; - if (bindLen > 2) value[2] = v2; - if (bindLen > 3) value[3] = v3; - if (bindLen > 4) value[4] = v4; - if (bindLen > 5) value[5] = v5; - if (bindLen > 6) value[6] = v6; - if (bindLen > 7) value[7] = v7; - if (bindLen > 8) value[8] = v8; - if (bindLen > 9) value[9] = v9; + value = []; + if (bindLen > 0) value.push(v0); + if (bindLen > 1) value.push(v1); + if (bindLen > 2) value.push(v2); + if (bindLen > 3) value.push(v3); + if (bindLen > 4) value.push(v4); + if (bindLen > 5) value.push(v5); + if (bindLen > 6) value.push(v6); + if (bindLen > 7) value.push(v7); + if (bindLen > 8) value.push(v8); + if (bindLen > 9) value.push(v9); break; case NodeFlags.TypePureObject: value = {}; diff --git a/packages/core/src/view/text.ts b/packages/core/src/view/text.ts index e5abed2a22..7067d7fe43 100644 --- a/packages/core/src/view/text.ts +++ b/packages/core/src/view/text.ts @@ -11,7 +11,7 @@ import {checkAndUpdateBinding, getParentRenderElement} from './util'; export function textDef( checkIndex: number, ngContentIndex: number | null, staticText: string[]): NodeDef { - const bindings: BindingDef[] = new Array(staticText.length - 1); + const bindings: BindingDef[] = []; for (let i = 1; i < staticText.length; i++) { bindings[i - 1] = { flags: BindingFlags.TypeProperty, diff --git a/packages/core/test/bundling/injection/bundle.golden_symbols.json b/packages/core/test/bundling/injection/bundle.golden_symbols.json index 55b71159e8..b76b2d0f03 100644 --- a/packages/core/test/bundling/injection/bundle.golden_symbols.json +++ b/packages/core/test/bundling/injection/bundle.golden_symbols.json @@ -173,6 +173,9 @@ { "name": "makeRecord" }, + { + "name": "newArray" + }, { "name": "providerToFactory" }, diff --git a/packages/platform-browser/src/browser/browser_adapter.ts b/packages/platform-browser/src/browser/browser_adapter.ts index 5747047fbb..6974c9383d 100644 --- a/packages/platform-browser/src/browser/browser_adapter.ts +++ b/packages/platform-browser/src/browser/browser_adapter.ts @@ -168,7 +168,7 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { childNodes(el: any): Node[] { return el.childNodes; } childNodesAsList(el: Node): any[] { const childNodes = el.childNodes; - const res = new Array(childNodes.length); + const res = []; for (let i = 0; i < childNodes.length; i++) { res[i] = childNodes[i]; } diff --git a/packages/platform-webworker/src/web_workers/shared/service_message_broker.ts b/packages/platform-webworker/src/web_workers/shared/service_message_broker.ts index f18d7feaa6..10045e163f 100644 --- a/packages/platform-webworker/src/web_workers/shared/service_message_broker.ts +++ b/packages/platform-webworker/src/web_workers/shared/service_message_broker.ts @@ -60,7 +60,7 @@ export class ServiceMessageBroker { this._methods.set(methodName, (message: ReceivedMessage) => { const serializedArgs = message.args; const numArgs = signature ? signature.length : 0; - const deserializedArgs = new Array(numArgs); + const deserializedArgs = []; for (let i = 0; i < numArgs; i++) { const serializedArg = serializedArgs[i]; deserializedArgs[i] = this._serializer.deserialize(serializedArg, signature ![i]); diff --git a/packages/service-worker/cli/sha1.ts b/packages/service-worker/cli/sha1.ts index a01f0e744e..770287d55d 100644 --- a/packages/service-worker/cli/sha1.ts +++ b/packages/service-worker/cli/sha1.ts @@ -29,7 +29,7 @@ export function sha1Binary(buffer: ArrayBuffer): string { } function _sha1(words32: number[], len: number): string { - const w = new Array(80); + const w: number[] = []; let [a, b, c, d, e]: number[] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; words32[len >> 5] |= 0x80 << (24 - len % 32); @@ -113,9 +113,10 @@ function fk(index: number, b: number, c: number, d: number): [number, number] { function stringToWords32(str: string, endian: Endian): number[] { - const words32 = Array((str.length + 3) >>> 2); + const size = (str.length + 3) >>> 2; + const words32 = []; - for (let i = 0; i < words32.length; i++) { + for (let i = 0; i < size; i++) { words32[i] = wordAt(str, i * 4, endian); } @@ -123,9 +124,10 @@ function stringToWords32(str: string, endian: Endian): number[] { } function arrayBufferToWords32(buffer: ArrayBuffer, endian: Endian): number[] { - const words32 = Array((buffer.byteLength + 3) >>> 2); + const size = (buffer.byteLength + 3) >>> 2; + const words32: number[] = []; const view = new Uint8Array(buffer); - for (let i = 0; i < words32.length; i++) { + for (let i = 0; i < size; i++) { words32[i] = wordAt(view, i * 4, endian); } return words32; diff --git a/packages/service-worker/worker/src/sha1.ts b/packages/service-worker/worker/src/sha1.ts index a01f0e744e..770287d55d 100644 --- a/packages/service-worker/worker/src/sha1.ts +++ b/packages/service-worker/worker/src/sha1.ts @@ -29,7 +29,7 @@ export function sha1Binary(buffer: ArrayBuffer): string { } function _sha1(words32: number[], len: number): string { - const w = new Array(80); + const w: number[] = []; let [a, b, c, d, e]: number[] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; words32[len >> 5] |= 0x80 << (24 - len % 32); @@ -113,9 +113,10 @@ function fk(index: number, b: number, c: number, d: number): [number, number] { function stringToWords32(str: string, endian: Endian): number[] { - const words32 = Array((str.length + 3) >>> 2); + const size = (str.length + 3) >>> 2; + const words32 = []; - for (let i = 0; i < words32.length; i++) { + for (let i = 0; i < size; i++) { words32[i] = wordAt(str, i * 4, endian); } @@ -123,9 +124,10 @@ function stringToWords32(str: string, endian: Endian): number[] { } function arrayBufferToWords32(buffer: ArrayBuffer, endian: Endian): number[] { - const words32 = Array((buffer.byteLength + 3) >>> 2); + const size = (buffer.byteLength + 3) >>> 2; + const words32: number[] = []; const view = new Uint8Array(buffer); - for (let i = 0; i < words32.length; i++) { + for (let i = 0; i < size; i++) { words32[i] = wordAt(view, i * 4, endian); } return words32;