Skip to content

Commit 0e7fa4f

Browse files
author
Andy Hanson
committed
WIP
1 parent 2326785 commit 0e7fa4f

File tree

9 files changed

+130
-59
lines changed

9 files changed

+130
-59
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19901,16 +19901,16 @@ namespace ts {
1990119901
}
1990219902

1990319903
function checkGrammarJsxElement(node: JsxOpeningLikeElement) {
19904-
const seen = createMap<boolean>();
19904+
const seen = createSet();
1990519905
for (const attr of node.attributes) {
1990619906
if (attr.kind === SyntaxKind.JsxSpreadAttribute) {
1990719907
continue;
1990819908
}
1990919909

1991019910
const jsxAttr = (<JsxAttribute>attr);
1991119911
const name = jsxAttr.name;
19912-
if (!_g(seen, name.text)) {
19913-
_s(seen, name.text, true);
19912+
if (!_setHas(seen, name.text)) {
19913+
_add(seen, name.text);
1991419914
}
1991519915
else {
1991619916
return grammarErrorOnNode(name, Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name);

src/compiler/dataStructures.ts

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ namespace ts {
3939
/* @internal */
4040
//map implementation
4141
namespace ts {
42-
interface Iterator<T> {
42+
export interface Iterator<T> {
4343
next(): { value: T, done: boolean }; //TODO: LKG updated, so use { value: T, done: false } | { value: never, done: true }
4444
}
4545

@@ -53,19 +53,14 @@ namespace ts {
5353
keys(): Iterator<string>;
5454
values(): Iterator<T>;
5555
entries(): Iterator<[string, T]>;
56+
57+
//kill?
58+
forEach(f: (value: T, key: string) => void): void;
5659
}
5760

5861
declare const Map: { new<T>(): NativeMap<T> } | undefined;
5962
const realMaps = typeof Map !== "undefined"; //false;
6063

61-
//function asNative<T>(map: Map<T>): NativeMap<T> {
62-
// //Debug.assert(map instanceof Map);
63-
// return map as NativeMap<T>;
64-
//}
65-
function asObj<T>(map: Map<T>): MapLike<T> {
66-
return map as any as MapLike<T>;
67-
}
68-
6964
const createObject = Object.create;
7065
const hasOwnProperty = Object.prototype.hasOwnProperty;
7166

@@ -84,7 +79,8 @@ namespace ts {
8479
return map;
8580
}
8681

87-
function createDictionaryModeObject(): any {
82+
//TODO: don't export
83+
export function createDictionaryModeObject(): any {
8884
const map = createObject(null); // tslint:disable-line:no-null-keyword
8985

9086
// Using 'delete' on an object causes V8 to put the object in dictionary mode.
@@ -124,15 +120,16 @@ namespace ts {
124120

125121
export const _each: <T>(map: Map<T>, f: (key: string, value: T) => void) => void = realMaps
126122
? <T>(map: NativeMap<T>, f: (key: string, value: T) => void) => {
127-
const iter = map.entries();
123+
/*const iter = map.entries();
128124
while (true) {
129125
const { value: pair, done } = iter.next();
130126
if (done) {
131127
return;
132128
}
133129
const [key, value] = pair;
134130
f(key, value);
135-
}
131+
}*/
132+
map.forEach((value, key) => { f(key, value) }); // No idea whether this is better or worse...
136133
}
137134
: <T>(map: MapLike<T>, f: (key: string, value: T) => void): void => {
138135
for (const key in map) {
@@ -142,6 +139,7 @@ namespace ts {
142139

143140
export const _find: <T, U>(map: Map<T>, f: (key: string, value: T) => U | undefined) => U | undefined = realMaps
144141
? <T, U>(map: NativeMap<T>, f: (key: string, value: T) => U | undefined) => {
142+
//use forEach?
145143
const iter = map.entries();
146144
while (true) {
147145
const { value: pair, done } = iter.next();
@@ -242,6 +240,7 @@ namespace ts {
242240
}
243241
f(key);
244242
}
243+
//map.forEach((value, key) => f(key)); //does this do unnecessary lookup?
245244
}
246245
: (map: MapLike<any>, f: (key: string) => void) => {
247246
for (const key in map) {
@@ -281,6 +280,7 @@ namespace ts {
281280
}
282281
f(value);
283282
}
283+
//map.forEach(f);
284284
}
285285
: <T>(map: MapLike<T>, f: (value: T) => void) => {
286286
for (const key in map) {
@@ -474,6 +474,77 @@ namespace ts {
474474
}
475475
}
476476

477+
478+
/* @internal */
479+
namespace ts {
480+
export interface Set {
481+
__setBrand: any;
482+
}
483+
484+
interface NativeSet extends Set {
485+
readonly size: number;
486+
add(value: string): this;
487+
has(value: string): boolean;
488+
delete(value: string): void;
489+
values(): Iterator<string>;
490+
forEach(f: (value: string) => void): void;
491+
}
492+
493+
interface SetLike extends Set {
494+
[value: string]: boolean; //TODO: `: true`
495+
}
496+
497+
declare const Set: { new(): NativeSet } | undefined;
498+
const realSets = typeof Set !== "undefined";
499+
500+
export const createSet: () => Set = realSets
501+
? () => new Set()
502+
: () => createDictionaryModeObject();
503+
504+
export const _add: (set: Set, value: string) => void = realSets
505+
? (set: NativeSet, value: string) => {
506+
set.add(value);
507+
}
508+
: (set: SetLike, value: string) => {
509+
set[value] = true;
510+
}
511+
512+
export const _setHas: (set: Set, value: string) => boolean = realSets
513+
? (set: NativeSet, value: string) => set.has(value)
514+
: (set: SetLike, value: string) => value in set
515+
516+
export const _deleteFromSet: (set: Set, value: string) => void = realSets
517+
? (set: NativeSet, value: string) => {
518+
set.delete(value)
519+
}
520+
: (set: SetLike, value: string) => {
521+
delete set[value];
522+
}
523+
524+
export const _setIsEmpty: (set: Set) => boolean = realSets
525+
? (set: NativeSet) => set.size === 0
526+
: (set: SetLike) => {
527+
for (const value in set)
528+
return false;
529+
return true;
530+
}
531+
532+
export const _eachInSet: (set: Set, f: (value: string) => void) => void = realSets
533+
? (set: NativeSet, f: (value: string) => void) => {
534+
set.forEach(f);
535+
}
536+
: (set: SetLike, f: (value: string) => void) => {
537+
for (const value in set)
538+
f(value);
539+
}
540+
541+
//todo: more iteration helpers
542+
}
543+
544+
545+
546+
547+
477548
//MAPLIKE CRAP
478549
/* @internal */
479550
namespace ts {

src/compiler/transformers/generators.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ namespace ts {
243243
context.onSubstituteNode = onSubstituteNode;
244244

245245
let currentSourceFile: SourceFile;
246-
let renamedCatchVariables: Map<boolean>;
246+
let renamedCatchVariables: Set;
247247
let renamedCatchVariableDeclarations: Map<Identifier>;
248248

249249
let inGeneratorFunctionBody: boolean;
@@ -1903,7 +1903,7 @@ namespace ts {
19031903
}
19041904

19051905
function substituteExpressionIdentifier(node: Identifier) {
1906-
if (renamedCatchVariables && _has(renamedCatchVariables, node.text)) {
1906+
if (renamedCatchVariables && _setHas(renamedCatchVariables, node.text)) {
19071907
const original = getOriginalNode(node);
19081908
if (isIdentifier(original) && original.parent) {
19091909
const declaration = resolver.getReferencedValueDeclaration(original);
@@ -2073,12 +2073,12 @@ namespace ts {
20732073
const name = declareLocal(text);
20742074

20752075
if (!renamedCatchVariables) {
2076-
renamedCatchVariables = createMap<boolean>();
2076+
renamedCatchVariables = createSet();
20772077
renamedCatchVariableDeclarations = createMap<Identifier>();
20782078
context.enableSubstitution(SyntaxKind.Identifier);
20792079
}
20802080

2081-
_s(renamedCatchVariables, text, true);
2081+
_add(renamedCatchVariables, text);
20822082
_setWakka(renamedCatchVariableDeclarations, getOriginalNodeId(variable), name);
20832083

20842084
const exception = <ExceptionBlock>peekBlock();

src/harness/fourslash.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ namespace FourSlash {
9999

100100
export import IndentStyle = ts.IndentStyle;
101101

102-
const entityMap = ts.createMap({
102+
const entityMap = ts.createMapFromMapLike({
103103
"&": "&amp;",
104104
"\"": "&quot;",
105105
"'": "&#39;",
@@ -966,7 +966,7 @@ namespace FourSlash {
966966

967967
public verifyQuickInfos(namesAndTexts: { [name: string]: string | [string, string] }) {
968968
//TODO: don't bother creating a map
969-
ts._each(ts.createMap(namesAndTexts), (name, text) => {
969+
ts._each(ts.createMapFromMapLike(namesAndTexts), (name, text) => {
970970
if (text instanceof Array) {
971971
assert(text.length === 2);
972972
const [expectedText, expectedDocumentation] = text;
@@ -2069,7 +2069,7 @@ namespace FourSlash {
20692069

20702070
public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) {
20712071

2072-
const openBraceMap = ts.createMap<ts.CharacterCodes>({
2072+
const openBraceMap = ts.createMapFromMapLike<ts.CharacterCodes>({
20732073
"(": ts.CharacterCodes.openParen,
20742074
"{": ts.CharacterCodes.openBrace,
20752075
"[": ts.CharacterCodes.openBracket,

src/harness/harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ namespace Harness {
925925
export const defaultLibFileName = "lib.d.ts";
926926
export const es2015DefaultLibFileName = "lib.es2015.d.ts";
927927

928-
const libFileNameSourceFileMap= ts.createMap<ts.SourceFile>({
928+
const libFileNameSourceFileMap= ts.createMapFromMapLike<ts.SourceFile>({
929929
[defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest)
930930
});
931931

src/harness/unittests/cachingInServerLSHost.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ namespace ts {
77
}
88

99
function createDefaultServerHost(fileMap: Map<File>): server.ServerHost {
10-
const existingDirectories = createMap<boolean>();
10+
const existingDirectories = createSet();
1111
_eachKey(fileMap, name => {
1212
let dir = getDirectoryPath(name);
1313
let previous: string;
1414
do {
15-
_s(existingDirectories, dir, true);
15+
_add(existingDirectories, dir);
1616
previous = dir;
1717
dir = getDirectoryPath(dir);
1818
} while (dir !== previous);
@@ -36,7 +36,7 @@ namespace ts {
3636
return _has(fileMap, path);
3737
},
3838
directoryExists: (path: string): boolean => {
39-
return _g(existingDirectories, path) || false;
39+
return _setHas(existingDirectories, path);
4040
},
4141
createDirectory: (path: string) => {
4242
},
@@ -102,7 +102,7 @@ namespace ts {
102102
content: `foo()`
103103
};
104104

105-
const serverHost = createDefaultServerHost(createMap({ [root.name]: root, [imported.name]: imported }));
105+
const serverHost = createDefaultServerHost(createMapFromMapLike({ [root.name]: root, [imported.name]: imported }));
106106
const { project, rootScriptInfo } = createProject(root.name, serverHost);
107107

108108
// ensure that imported file was found
@@ -194,7 +194,7 @@ namespace ts {
194194
content: `export var y = 1`
195195
};
196196

197-
const fileMap = createMap({ [root.name]: root });
197+
const fileMap = createMapFromMapLike({ [root.name]: root });
198198
const serverHost = createDefaultServerHost(fileMap);
199199
const originalFileExists = serverHost.fileExists;
200200

src/harness/unittests/moduleResolution.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ namespace ts {
318318
}
319319

320320
it("should find all modules", () => {
321-
const files = createMap({
321+
const files = createMapFromMapLike({
322322
"/a/b/c/first/shared.ts": `
323323
class A {}
324324
export = A`,
@@ -337,15 +337,15 @@ export = C;
337337
});
338338

339339
it("should find modules in node_modules", () => {
340-
const files = createMap({
340+
const files = createMapFromMapLike({
341341
"/parent/node_modules/mod/index.d.ts": "export var x",
342342
"/parent/app/myapp.ts": `import {x} from "mod"`
343343
});
344344
test(files, "/parent/app", ["myapp.ts"], 2, []);
345345
});
346346

347347
it("should find file referenced via absolute and relative names", () => {
348-
const files = createMap({
348+
const files = createMapFromMapLike({
349349
"/a/b/c.ts": `/// <reference path="b.ts"/>`,
350350
"/a/b/b.ts": "var x"
351351
});
@@ -392,39 +392,39 @@ export = C;
392392
}
393393

394394
it("should succeed when the same file is referenced using absolute and relative names", () => {
395-
const files = createMap({
395+
const files = createMapFromMapLike({
396396
"/a/b/c.ts": `/// <reference path="d.ts"/>`,
397397
"/a/b/d.ts": "var x"
398398
});
399399
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "/a/b/d.ts"], []);
400400
});
401401

402402
it("should fail when two files used in program differ only in casing (tripleslash references)", () => {
403-
const files = createMap({
403+
const files = createMapFromMapLike({
404404
"/a/b/c.ts": `/// <reference path="D.ts"/>`,
405405
"/a/b/d.ts": "var x"
406406
});
407407
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
408408
});
409409

410410
it("should fail when two files used in program differ only in casing (imports)", () => {
411-
const files = createMap({
411+
const files = createMapFromMapLike({
412412
"/a/b/c.ts": `import {x} from "D"`,
413413
"/a/b/d.ts": "export var x"
414414
});
415415
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], [1149]);
416416
});
417417

418418
it("should fail when two files used in program differ only in casing (imports, relative module names)", () => {
419-
const files = createMap({
419+
const files = createMapFromMapLike({
420420
"moduleA.ts": `import {x} from "./ModuleB"`,
421421
"moduleB.ts": "export var x"
422422
});
423423
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts"], [1149]);
424424
});
425425

426426
it("should fail when two files exist on disk that differs only in casing", () => {
427-
const files = createMap({
427+
const files = createMapFromMapLike({
428428
"/a/b/c.ts": `import {x} from "D"`,
429429
"/a/b/D.ts": "export var x",
430430
"/a/b/d.ts": "export var y"
@@ -433,7 +433,7 @@ export = C;
433433
});
434434

435435
it("should fail when module name in 'require' calls has inconsistent casing", () => {
436-
const files = createMap({
436+
const files = createMapFromMapLike({
437437
"moduleA.ts": `import a = require("./ModuleC")`,
438438
"moduleB.ts": `import a = require("./moduleC")`,
439439
"moduleC.ts": "export var x"
@@ -442,7 +442,7 @@ export = C;
442442
});
443443

444444
it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => {
445-
const files = createMap({
445+
const files = createMapFromMapLike({
446446
"/a/B/c/moduleA.ts": `import a = require("./ModuleC")`,
447447
"/a/B/c/moduleB.ts": `import a = require("./moduleC")`,
448448
"/a/B/c/moduleC.ts": "export var x",
@@ -454,7 +454,7 @@ import b = require("./moduleB");
454454
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]);
455455
});
456456
it("should not fail when module names in 'require' calls has consistent casing and current directory has uppercase chars", () => {
457-
const files = createMap({
457+
const files = createMapFromMapLike({
458458
"/a/B/c/moduleA.ts": `import a = require("./moduleC")`,
459459
"/a/B/c/moduleB.ts": `import a = require("./moduleC")`,
460460
"/a/B/c/moduleC.ts": "export var x",

0 commit comments

Comments
 (0)