Skip to content

Commit 2c08aff

Browse files
authored
Merge pull request #39264 from microsoft/migrateMapsAndSets
Migrate maps and sets
2 parents bcb4a49 + 1359dbd commit 2c08aff

File tree

109 files changed

+663
-660
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+663
-660
lines changed

src/compat/deprecations.ts

+20
Original file line numberDiff line numberDiff line change
@@ -1321,4 +1321,24 @@ namespace ts {
13211321
});
13221322

13231323
// #endregion Renamed node Tests
1324+
1325+
// DEPRECATION: Renamed `Map` and `ReadonlyMap` interfaces
1326+
// DEPRECATION PLAN:
1327+
// - soft: 4.0
1328+
// - remove: TBD (will remove for at least one release before replacing with `ESMap`/`ReadonlyESMap`)
1329+
// - replace: TBD (will eventually replace with `ESMap`/`ReadonlyESMap`)
1330+
// #region Renamed `Map` and `ReadonlyMap` interfaces
1331+
1332+
/**
1333+
* @deprecated Use `ts.ReadonlyESMap<K, V>` instead.
1334+
*/
1335+
export interface ReadonlyMap<T> extends ReadonlyESMap<string, T> {
1336+
}
1337+
1338+
/**
1339+
* @deprecated Use `ts.ESMap<K, V>` instead.
1340+
*/
1341+
export interface Map<T> extends ESMap<string, T> { }
1342+
1343+
// #endregion
13241344
}

src/compiler/binder.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ namespace ts {
218218
let symbolCount = 0;
219219

220220
let Symbol: new (flags: SymbolFlags, name: __String) => Symbol;
221-
let classifiableNames: UnderscoreEscapedMap<true>;
221+
let classifiableNames: Set<__String>;
222222

223223
const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
224224
const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable };
@@ -237,7 +237,7 @@ namespace ts {
237237
options = opts;
238238
languageVersion = getEmitScriptTarget(options);
239239
inStrictMode = bindInStrictMode(file, opts);
240-
classifiableNames = createUnderscoreEscapedMap<true>();
240+
classifiableNames = new Set();
241241
symbolCount = 0;
242242

243243
Symbol = objectAllocator.getSymbolConstructor();
@@ -445,7 +445,7 @@ namespace ts {
445445
symbol = symbolTable.get(name);
446446

447447
if (includes & SymbolFlags.Classifiable) {
448-
classifiableNames.set(name, true);
448+
classifiableNames.add(name);
449449
}
450450

451451
if (!symbol) {
@@ -1965,7 +1965,7 @@ namespace ts {
19651965
}
19661966

19671967
if (inStrictMode && !isAssignmentTarget(node)) {
1968-
const seen = createUnderscoreEscapedMap<ElementKind>();
1968+
const seen = new Map<__String, ElementKind>();
19691969

19701970
for (const prop of node.properties) {
19711971
if (prop.kind === SyntaxKind.SpreadAssignment || prop.name.kind !== SyntaxKind.Identifier) {
@@ -3146,7 +3146,7 @@ namespace ts {
31463146
bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName);
31473147
// Add name of class expression into the map for semantic classifier
31483148
if (node.name) {
3149-
classifiableNames.set(node.name.escapedText, true);
3149+
classifiableNames.add(node.name.escapedText);
31503150
}
31513151
}
31523152

src/compiler/checker.ts

+116-114
Large diffs are not rendered by default.

src/compiler/commandLineParser.ts

+24-24
Original file line numberDiff line numberDiff line change
@@ -83,33 +83,33 @@ namespace ts {
8383
export const optionsForWatch: CommandLineOption[] = [
8484
{
8585
name: "watchFile",
86-
type: createMapFromTemplate({
86+
type: new Map(getEntries({
8787
fixedpollinginterval: WatchFileKind.FixedPollingInterval,
8888
prioritypollinginterval: WatchFileKind.PriorityPollingInterval,
8989
dynamicprioritypolling: WatchFileKind.DynamicPriorityPolling,
9090
usefsevents: WatchFileKind.UseFsEvents,
9191
usefseventsonparentdirectory: WatchFileKind.UseFsEventsOnParentDirectory,
92-
}),
92+
})),
9393
category: Diagnostics.Advanced_Options,
9494
description: Diagnostics.Specify_strategy_for_watching_file_Colon_FixedPollingInterval_default_PriorityPollingInterval_DynamicPriorityPolling_UseFsEvents_UseFsEventsOnParentDirectory,
9595
},
9696
{
9797
name: "watchDirectory",
98-
type: createMapFromTemplate({
98+
type: new Map(getEntries({
9999
usefsevents: WatchDirectoryKind.UseFsEvents,
100100
fixedpollinginterval: WatchDirectoryKind.FixedPollingInterval,
101101
dynamicprioritypolling: WatchDirectoryKind.DynamicPriorityPolling,
102-
}),
102+
})),
103103
category: Diagnostics.Advanced_Options,
104104
description: Diagnostics.Specify_strategy_for_watching_directory_on_platforms_that_don_t_support_recursive_watching_natively_Colon_UseFsEvents_default_FixedPollingInterval_DynamicPriorityPolling,
105105
},
106106
{
107107
name: "fallbackPolling",
108-
type: createMapFromTemplate({
108+
type: new Map(getEntries({
109109
fixedinterval: PollingWatchKind.FixedInterval,
110110
priorityinterval: PollingWatchKind.PriorityInterval,
111111
dynamicpriority: PollingWatchKind.DynamicPriority,
112-
}),
112+
})),
113113
category: Diagnostics.Advanced_Options,
114114
description: Diagnostics.Specify_strategy_for_creating_a_polling_watch_when_it_fails_to_create_using_file_system_events_Colon_FixedInterval_default_PriorityInterval_DynamicPriority,
115115
},
@@ -286,7 +286,7 @@ namespace ts {
286286
{
287287
name: "target",
288288
shortName: "t",
289-
type: createMapFromTemplate({
289+
type: new Map(getEntries({
290290
es3: ScriptTarget.ES3,
291291
es5: ScriptTarget.ES5,
292292
es6: ScriptTarget.ES2015,
@@ -297,7 +297,7 @@ namespace ts {
297297
es2019: ScriptTarget.ES2019,
298298
es2020: ScriptTarget.ES2020,
299299
esnext: ScriptTarget.ESNext,
300-
}),
300+
})),
301301
affectsSourceFile: true,
302302
affectsModuleResolution: true,
303303
affectsEmit: true,
@@ -309,7 +309,7 @@ namespace ts {
309309
{
310310
name: "module",
311311
shortName: "m",
312-
type: createMapFromTemplate({
312+
type: new Map(getEntries({
313313
none: ModuleKind.None,
314314
commonjs: ModuleKind.CommonJS,
315315
amd: ModuleKind.AMD,
@@ -319,7 +319,7 @@ namespace ts {
319319
es2015: ModuleKind.ES2015,
320320
es2020: ModuleKind.ES2020,
321321
esnext: ModuleKind.ESNext
322-
}),
322+
})),
323323
affectsModuleResolution: true,
324324
affectsEmit: true,
325325
paramType: Diagnostics.KIND,
@@ -356,11 +356,11 @@ namespace ts {
356356
},
357357
{
358358
name: "jsx",
359-
type: createMapFromTemplate({
359+
type: new Map(getEntries({
360360
"preserve": JsxEmit.Preserve,
361361
"react-native": JsxEmit.ReactNative,
362362
"react": JsxEmit.React
363-
}),
363+
})),
364364
affectsSourceFile: true,
365365
paramType: Diagnostics.KIND,
366366
showInSimplifiedHelpView: true,
@@ -476,11 +476,11 @@ namespace ts {
476476
},
477477
{
478478
name: "importsNotUsedAsValues",
479-
type: createMapFromTemplate({
479+
type: new Map(getEntries({
480480
remove: ImportsNotUsedAsValues.Remove,
481481
preserve: ImportsNotUsedAsValues.Preserve,
482482
error: ImportsNotUsedAsValues.Error
483-
}),
483+
})),
484484
affectsEmit: true,
485485
affectsSemanticDiagnostics: true,
486486
category: Diagnostics.Advanced_Options,
@@ -610,10 +610,10 @@ namespace ts {
610610
// Module Resolution
611611
{
612612
name: "moduleResolution",
613-
type: createMapFromTemplate({
613+
type: new Map(getEntries({
614614
node: ModuleResolutionKind.NodeJs,
615615
classic: ModuleResolutionKind.Classic,
616-
}),
616+
})),
617617
affectsModuleResolution: true,
618618
paramType: Diagnostics.STRATEGY,
619619
category: Diagnostics.Module_Resolution_Options,
@@ -818,10 +818,10 @@ namespace ts {
818818
},
819819
{
820820
name: "newLine",
821-
type: createMapFromTemplate({
821+
type: new Map(getEntries({
822822
crlf: NewLineKind.CarriageReturnLineFeed,
823823
lf: NewLineKind.LineFeed
824-
}),
824+
})),
825825
affectsEmit: true,
826826
paramType: Diagnostics.NEWLINE,
827827
category: Diagnostics.Advanced_Options,
@@ -1096,8 +1096,8 @@ namespace ts {
10961096

10971097
/*@internal*/
10981098
export function createOptionNameMap(optionDeclarations: readonly CommandLineOption[]): OptionsNameMap {
1099-
const optionsNameMap = createMap<CommandLineOption>();
1100-
const shortOptionNames = createMap<string>();
1099+
const optionsNameMap = new Map<string, CommandLineOption>();
1100+
const shortOptionNames = new Map<string, string>();
11011101
forEach(optionDeclarations, option => {
11021102
optionsNameMap.set(option.name.toLowerCase(), option);
11031103
if (option.shortName) {
@@ -2032,7 +2032,7 @@ namespace ts {
20322032
{ optionsNameMap }: OptionsNameMap,
20332033
pathOptions?: { configFilePath: string, useCaseSensitiveFileNames: boolean }
20342034
): ESMap<string, CompilerOptionsValue> {
2035-
const result = createMap<CompilerOptionsValue>();
2035+
const result = new Map<string, CompilerOptionsValue>();
20362036
const getCanonicalFileName = pathOptions && createGetCanonicalFileName(pathOptions.useCaseSensitiveFileNames);
20372037

20382038
for (const name in options) {
@@ -2962,17 +2962,17 @@ namespace ts {
29622962
// Literal file names (provided via the "files" array in tsconfig.json) are stored in a
29632963
// file map with a possibly case insensitive key. We use this map later when when including
29642964
// wildcard paths.
2965-
const literalFileMap = createMap<string>();
2965+
const literalFileMap = new Map<string, string>();
29662966

29672967
// Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a
29682968
// file map with a possibly case insensitive key. We use this map to store paths matched
29692969
// via wildcard, and to handle extension priority.
2970-
const wildcardFileMap = createMap<string>();
2970+
const wildcardFileMap = new Map<string, string>();
29712971

29722972
// Wildcard paths of json files (provided via the "includes" array in tsconfig.json) are stored in a
29732973
// file map with a possibly case insensitive key. We use this map to store paths matched
29742974
// via wildcard of *.json kind
2975-
const wildCardJsonFileMap = createMap<string>();
2975+
const wildCardJsonFileMap = new Map<string, string>();
29762976
const { filesSpecs, validatedIncludeSpecs, validatedExcludeSpecs, wildcardDirectories } = spec;
29772977

29782978
// Rather than requery this for each file and filespec, we query the supported extensions

src/compiler/core.ts

+36-4
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,23 @@ namespace ts {
4040
}
4141

4242
export const emptyArray: never[] = [] as never[];
43+
export const emptyMap: ReadonlyESMap<never, never> = new Map<never, never>();
44+
export const emptySet: ReadonlySet<never> = new Set<never>();
4345

44-
/** Create a new map. */
46+
/**
47+
* Create a new map.
48+
* @deprecated Use `new Map()` instead.
49+
*/
4550
export function createMap<K, V>(): ESMap<K, V>;
4651
export function createMap<T>(): ESMap<string, T>;
4752
export function createMap<K, V>(): ESMap<K, V> {
4853
return new Map<K, V>();
4954
}
5055

51-
/** Create a new map from a template object is provided, the map will copy entries from it. */
56+
/**
57+
* Create a new map from a template object is provided, the map will copy entries from it.
58+
* @deprecated Use `new Map(getEntries(template))` instead.
59+
*/
5260
export function createMapFromTemplate<T>(template: MapLike<T>): ESMap<string, T> {
5361
const map: ESMap<string, T> = new Map<string, T>();
5462

@@ -590,6 +598,15 @@ namespace ts {
590598
}
591599
}
592600

601+
export function getOrUpdate<K, V>(map: ESMap<K, V>, key: K, callback: () => V) {
602+
if (map.has(key)) {
603+
return map.get(key)!;
604+
}
605+
const value = callback();
606+
map.set(key, value);
607+
return value;
608+
}
609+
593610
export function tryAddToSet<T>(set: Set<T>, value: T) {
594611
if (!set.has(value)) {
595612
set.add(value);
@@ -1287,6 +1304,19 @@ namespace ts {
12871304
return values;
12881305
}
12891306

1307+
const _entries = Object.entries ? Object.entries : <T>(obj: MapLike<T>) => {
1308+
const keys = getOwnKeys(obj);
1309+
const result: [string, T][] = Array(keys.length);
1310+
for (const key of keys) {
1311+
result.push([key, obj[key]]);
1312+
}
1313+
return result;
1314+
};
1315+
1316+
export function getEntries<T>(obj: MapLike<T>): [string, T][] {
1317+
return obj ? _entries(obj) : [];
1318+
}
1319+
12901320
export function arrayOf<T>(count: number, f: (index: number) => T): T[] {
12911321
const result = new Array(count);
12921322
for (let i = 0; i < count; i++) {
@@ -1387,9 +1417,11 @@ namespace ts {
13871417
return result;
13881418
}
13891419

1420+
export function group<T, K>(values: readonly T[], getGroupId: (value: T) => K): readonly (readonly T[])[];
1421+
export function group<T, K, R>(values: readonly T[], getGroupId: (value: T) => K, resultSelector: (values: readonly T[]) => R): R[];
13901422
export function group<T>(values: readonly T[], getGroupId: (value: T) => string): readonly (readonly T[])[];
13911423
export function group<T, R>(values: readonly T[], getGroupId: (value: T) => string, resultSelector: (values: readonly T[]) => R): R[];
1392-
export function group<T>(values: readonly T[], getGroupId: (value: T) => string, resultSelector: (values: readonly T[]) => readonly T[] = identity): readonly (readonly T[])[] {
1424+
export function group<T, K>(values: readonly T[], getGroupId: (value: T) => K, resultSelector: (values: readonly T[]) => readonly T[] = identity): readonly (readonly T[])[] {
13931425
return arrayFrom(arrayToMultiMap(values, getGroupId).values(), resultSelector);
13941426
}
13951427

@@ -1608,7 +1640,7 @@ namespace ts {
16081640

16091641
/** A version of `memoize` that supports a single primitive argument */
16101642
export function memoizeOne<A extends string | number | boolean | undefined, T>(callback: (arg: A) => T): (arg: A) => T {
1611-
const map = createMap<T>();
1643+
const map = new Map<string, T>();
16121644
return (arg: A) => {
16131645
const key = `${typeof arg}:${arg}`;
16141646
let value = map.get(key);

src/compiler/corePublic.ts

-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ namespace ts {
4545

4646
/**
4747
* ES6 Map interface, only read methods included.
48-
* @deprecated Use `ts.ReadonlyESMap<K, V>` instead.
4948
*/
5049
export interface ReadonlyMap<T> extends ReadonlyESMap<string, T> {
5150
}
@@ -57,7 +56,6 @@ namespace ts {
5756

5857
/**
5958
* ES6 Map interface.
60-
* @deprecated Use `ts.ESMap<K, V>` instead.
6159
*/
6260
export interface Map<T> extends ESMap<string, T> {
6361
}

src/compiler/emitter.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -682,9 +682,9 @@ namespace ts {
682682

683683
function createSourceFilesFromBundleBuildInfo(bundle: BundleBuildInfo, buildInfoDirectory: string, host: EmitUsingBuildInfoHost): readonly SourceFile[] {
684684
const jsBundle = Debug.checkDefined(bundle.js);
685-
const prologueMap = jsBundle.sources?.prologues && arrayToMap(jsBundle.sources.prologues, prologueInfo => "" + prologueInfo.file);
685+
const prologueMap = jsBundle.sources?.prologues && arrayToMap(jsBundle.sources.prologues, prologueInfo => prologueInfo.file);
686686
return bundle.sourceFiles.map((fileName, index) => {
687-
const prologueInfo = prologueMap?.get("" + index);
687+
const prologueInfo = prologueMap?.get(index);
688688
const statements = prologueInfo?.directives.map(directive => {
689689
const literal = setTextRange(factory.createStringLiteral(directive.expression.text), directive.expression);
690690
const statement = setTextRange(factory.createExpressionStatement(literal), directive);
@@ -834,7 +834,7 @@ namespace ts {
834834
const extendedDiagnostics = !!printerOptions.extendedDiagnostics;
835835
const newLine = getNewLineCharacter(printerOptions);
836836
const moduleKind = getEmitModuleKind(printerOptions);
837-
const bundledHelpers = createMap<boolean>();
837+
const bundledHelpers = new Map<string, boolean>();
838838

839839
let currentSourceFile: SourceFile | undefined;
840840
let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes.
@@ -1682,7 +1682,7 @@ namespace ts {
16821682
if (moduleKind === ModuleKind.None || printerOptions.noEmitHelpers) {
16831683
return undefined;
16841684
}
1685-
const bundledHelpers = createMap<boolean>();
1685+
const bundledHelpers = new Map<string, boolean>();
16861686
for (const sourceFile of bundle.sourceFiles) {
16871687
const shouldSkip = getExternalHelpersModuleName(sourceFile) !== undefined;
16881688
const helpers = getSortedEmitHelpers(sourceFile);

src/compiler/factory/nodeFactory.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5654,7 +5654,7 @@ namespace ts {
56545654
left.splice(0, 0, ...declarations.slice(0, rightStandardPrologueEnd));
56555655
}
56565656
else {
5657-
const leftPrologues = createMap<boolean>();
5657+
const leftPrologues = new Map<string, boolean>();
56585658
for (let i = 0; i < leftStandardPrologueEnd; i++) {
56595659
const leftPrologue = statements[i] as PrologueDirective;
56605660
leftPrologues.set(leftPrologue.expression.text, true);
@@ -6159,7 +6159,7 @@ namespace ts {
61596159
): InputFiles {
61606160
const node = parseNodeFactory.createInputFiles();
61616161
if (!isString(javascriptTextOrReadFileText)) {
6162-
const cache = createMap<string | false>();
6162+
const cache = new Map<string, string | false>();
61636163
const textGetter = (path: string | undefined) => {
61646164
if (path === undefined) return undefined;
61656165
let value = cache.get(path);

0 commit comments

Comments
 (0)