diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 2b578cecfc..ed58ab7f3a 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -751,7 +751,7 @@ namespace ts { value : { version: value.version, signature, affectsGlobalScope: value.affectsGlobalScope } : { version: value.version, signature: false, affectsGlobalScope: value.affectsGlobalScope }; - }); + }, state.fileInfos.size()); let referencedMap: ProgramBuildInfoReferencedMap | undefined; if (state.referencedMap) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51c5001204..dc28cf0c9c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1211,8 +1211,8 @@ namespace ts { result.parent = symbol.parent; if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration; if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true; - if (symbol.members) result.members = new Map(symbol.members); - if (symbol.exports) result.exports = new Map(symbol.exports); + if (symbol.members) result.members = new Map(symbol.members, symbol.members.size()); + if (symbol.exports) result.exports = new Map(symbol.exports, symbol.exports.size()); recordMergedSymbol(result, symbol); return result; } @@ -2756,8 +2756,8 @@ namespace ts { result.declarations = deduplicate(concatenate(valueSymbol.declarations, typeSymbol.declarations), equateValues); result.parent = valueSymbol.parent || typeSymbol.parent; if (valueSymbol.valueDeclaration) result.valueDeclaration = valueSymbol.valueDeclaration; - if (typeSymbol.members) result.members = new Map(typeSymbol.members); - if (valueSymbol.exports) result.exports = new Map(valueSymbol.exports); + if (typeSymbol.members) result.members = new Map(typeSymbol.members, typeSymbol.members.size()); + if (valueSymbol.exports) result.exports = new Map(valueSymbol.exports, valueSymbol.exports.size()); return result; } @@ -6148,7 +6148,7 @@ namespace ts { // export const x: (x: T) => T // export const y: (x: T_1) => T_1 if (initial.typeParameterNames) { - initial.typeParameterNames = new Map(initial.typeParameterNames); + initial.typeParameterNames = new Map(initial.typeParameterNames, initial.typeParameterNames.size); } if (initial.typeParameterNamesByText) { initial.typeParameterNamesByText = new Set(initial.typeParameterNamesByText); @@ -9123,8 +9123,8 @@ namespace ts { result.parent = symbol; result.target = fileSymbol; if (fileSymbol.valueDeclaration) result.valueDeclaration = fileSymbol.valueDeclaration; - if (fileSymbol.members) result.members = new Map(fileSymbol.members); - if (fileSymbol.exports) result.exports = new Map(fileSymbol.exports); + if (fileSymbol.members) result.members = new Map(fileSymbol.members, fileSymbol.members.size); + if (fileSymbol.exports) result.exports = new Map(fileSymbol.exports, fileSymbol.exports.size); const members = createSymbolTable(); members.set("exports" as __String, result); return createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray); @@ -13722,7 +13722,7 @@ namespace ts { const properties: Symbol[] = []; let combinedFlags: ElementFlags = 0; if (arity) { - typeParameters = new Array(arity); + typeParameters = presizedArray(arity); for (let i = 0; i < arity; i++) { const typeParameter = typeParameters[i] = createTypeParameter(); const flags = elementFlags[i]; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index eb07a11cba..9daf2f7d02 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -358,7 +358,7 @@ namespace ts { export function map(array: readonly T[] | undefined, f: (x: T, i: number) => U): U[] | undefined { let result: U[] | undefined; if (array) { - result = []; + result = presizedArray(array.length); for (let i = 0; i < array.length; i++) { result.push(f(array[i], i)); } @@ -684,7 +684,7 @@ namespace ts { return undefined; } - const result = new Map(); + const result = new Map(undefined, map.size); map.forEach((value, key) => { const [newKey, newValue] = f(key, value); result.set(newKey, newValue); @@ -784,8 +784,8 @@ namespace ts { export function deduplicate(array: readonly T[], equalityComparer: EqualityComparer, comparer?: Comparer): T[] { return array.length === 0 ? [] : array.length === 1 ? array.slice() : - comparer ? deduplicateRelational(array, equalityComparer, comparer) : - deduplicateEquality(array, equalityComparer); + comparer ? deduplicateRelational(array, equalityComparer, comparer) : + deduplicateEquality(array, equalityComparer); } /** @@ -1065,7 +1065,7 @@ namespace ts { else { i++; return { value: array[i - 1], done: false }; - } + } }}; } @@ -1318,15 +1318,19 @@ namespace ts { } export function arrayOf(count: number, f: (index: number) => T): T[] { - const result = new Array(count); + const result = presizedArray(count); for (let i = 0; i < count; i++) { result[i] = f(i); } return result; } + export function presizedArray(length?: number): T[] { + return Array.from({ length } as any); + } + /** Shims `Array.from`. */ - export function arrayFrom(iterator: Iterator | IterableIterator, map: (t: T) => U): U[]; + export function arrayFrom(iterator: Iterator | IterableIterator, map: (t: T) => U, count?: number): U[]; export function arrayFrom(iterator: Iterator | IterableIterator): T[]; export function arrayFrom(iterator: Iterator | IterableIterator, map?: (t: T) => U): (T | U)[] { const result: (T | U)[] = []; @@ -1389,7 +1393,7 @@ namespace ts { export function arrayToMap(array: readonly T[], makeKey: (value: T) => string | undefined): ESMap; export function arrayToMap(array: readonly T[], makeKey: (value: T) => string | undefined, makeValue: (value: T) => U): ESMap; export function arrayToMap(array: readonly V1[], makeKey: (value: V1) => K | undefined, makeValue: (value: V1) => V1 | V2 = identity): ESMap { - const result = new Map(); + const result = new Map(undefined, array.length); for (const value of array) { const key = makeKey(value); if (key !== undefined) result.set(key, makeValue(value)); @@ -1422,7 +1426,8 @@ namespace ts { export function group(values: readonly T[], getGroupId: (value: T) => string): readonly (readonly T[])[]; export function group(values: readonly T[], getGroupId: (value: T) => string, resultSelector: (values: readonly T[]) => R): R[]; export function group(values: readonly T[], getGroupId: (value: T) => K, resultSelector: (values: readonly T[]) => readonly T[] = identity): readonly (readonly T[])[] { - return arrayFrom(arrayToMultiMap(values, getGroupId).values(), resultSelector); + const multiMap = arrayToMultiMap(values, getGroupId); + return arrayFrom(multiMap.values(), resultSelector, multiMap.size); } export function clone(object: T): T { @@ -1743,9 +1748,9 @@ namespace ts { function compareComparableValues(a: string | number | undefined, b: string | number | undefined) { return a === b ? Comparison.EqualTo : a === undefined ? Comparison.LessThan : - b === undefined ? Comparison.GreaterThan : - a < b ? Comparison.LessThan : - Comparison.GreaterThan; + b === undefined ? Comparison.GreaterThan : + a < b ? Comparison.LessThan : + Comparison.GreaterThan; } /** @@ -1926,8 +1931,8 @@ namespace ts { export function compareProperties(a: T | undefined, b: T | undefined, key: K, comparer: Comparer): Comparison { return a === b ? Comparison.EqualTo : a === undefined ? Comparison.LessThan : - b === undefined ? Comparison.GreaterThan : - comparer(a[key], b[key]); + b === undefined ? Comparison.GreaterThan : + comparer(a[key], b[key]); } /** True is greater than false. */ @@ -1977,8 +1982,8 @@ namespace ts { } function levenshteinWithMax(s1: string, s2: string, max: number): number | undefined { - let previous = new Array(s2.length + 1); - let current = new Array(s2.length + 1); + let previous = presizedArray(s2.length + 1); + let current = presizedArray(s2.length + 1); /** Represents any value > max. We don't care about the particular value. */ const big = max + 0.01; @@ -1998,7 +2003,7 @@ namespace ts { } for (let j = minJ; j <= maxJ; j++) { // case difference should be significantly cheaper than other differences - const substitutionDistance = s1[i - 1].toLowerCase() === s2[j-1].toLowerCase() + const substitutionDistance = s1[i - 1].toLowerCase() === s2[j - 1].toLowerCase() ? (previous[j - 1] + 0.1) : (previous[j - 1] + 2); const dist = c1 === s2.charCodeAt(j - 1) diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index 58d53aec45..455c050019 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -65,7 +65,7 @@ namespace ts { /* @internal */ export interface MapConstructor { // eslint-disable-next-line @typescript-eslint/prefer-function-type - new (iterable?: readonly (readonly [K, V])[] | ReadonlyESMap): ESMap; + new (iterable?: readonly (readonly [K, V])[] | ReadonlyESMap, count?: number): ESMap; } /** ES6 Set interface, only read methods included. */ diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 9dd6db3779..e8d8653ac6 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1300,7 +1300,7 @@ namespace ts { oldResolvedModule.packageId && packageIdToString(oldResolvedModule.packageId) ); } - (result || (result = new Array(moduleNames.length)))[i] = oldResolvedModule; + (result || (result = presizedArray(moduleNames.length)))[i] = oldResolvedModule; (reusedNames || (reusedNames = [])).push(moduleName); continue; } @@ -1321,7 +1321,7 @@ namespace ts { } if (resolvesToAmbientModuleInNonModifiedFile) { - (result || (result = new Array(moduleNames.length)))[i] = predictedToResolveToAmbientModuleMarker; + (result || (result = presizedArray(moduleNames.length)))[i] = predictedToResolveToAmbientModuleMarker; } else { // Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result. diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index ed75cf081d..a7a66d679b 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -638,7 +638,7 @@ namespace ts { const generatedAbsoluteFilePath = getNormalizedAbsolutePath(map.file, mapDirectory); const generatedFile = host.getSourceFileLike(generatedAbsoluteFilePath); const sourceFileAbsolutePaths = map.sources.map(source => getNormalizedAbsolutePath(source, sourceRoot)); - const sourceToSourceIndexMap = new Map(sourceFileAbsolutePaths.map((source, i) => [host.getCanonicalFileName(source), i])); + const sourceToSourceIndexMap = new Map(sourceFileAbsolutePaths.map((source, i) => [host.getCanonicalFileName(source), i]), sourceFileAbsolutePaths.length); let decodedMappings: readonly MappedPosition[] | undefined; let generatedMappings: SortedReadonlyArray | undefined; let sourceMappings: readonly SortedReadonlyArray[] | undefined; diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 012be39dad..44538b1170 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -976,7 +976,7 @@ namespace ts { const parameter = parameters[i + firstParameterOffset]; if (decorators || parameter.decorators) { if (!decorators) { - decorators = new Array(numParameters); + decorators = presizedArray(numParameters); } decorators[i] = parameter.decorators; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 8ac91f86f9..5d496ca156 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -36,7 +36,7 @@ namespace ts { } export function createSymbolTable(symbols?: readonly Symbol[]): SymbolTable { - const result = new Map<__String, Symbol>(); + const result = new Map<__String, Symbol>(undefined, symbols?.length); if (symbols) { for (const symbol of symbols) { result.set(symbol.escapedName, symbol); diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 3f63422a7f..a41ea2d9e3 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -19,7 +19,7 @@ namespace ts { return diagnostic => system.write(formatDiagnostic(diagnostic, host)); } - const diagnostics: Diagnostic[] = new Array(1); + const diagnostics: Diagnostic[] = presizedArray(1); return diagnostic => { diagnostics[0] = diagnostic; system.write(formatDiagnosticsWithColorAndContext(diagnostics, host) + host.getNewLine());