Migrated more MapLikes to Maps

This commit is contained in:
Ron Buckton
2016-08-15 12:03:39 -07:00
parent 4e04b75d4b
commit 7f0a02ff02
23 changed files with 319 additions and 252 deletions

View File

@@ -403,8 +403,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 = cloneSymbolTable(symbol.members);
if (symbol.exports) result.exports = cloneSymbolTable(symbol.exports);
if (symbol.members) result.members = cloneMap(symbol.members);
if (symbol.exports) result.exports = cloneMap(symbol.exports);
recordMergedSymbol(result, symbol);
return result;
}
@@ -447,14 +447,6 @@ namespace ts {
}
}
function cloneSymbolTable(symbolTable: SymbolTable): SymbolTable {
const result = createMap<Symbol>();
for (const id in symbolTable) {
result[id] = symbolTable[id];
}
return result;
}
function mergeSymbolTable(target: SymbolTable, source: SymbolTable) {
for (const id in source) {
let targetSymbol = target[id];
@@ -1450,7 +1442,7 @@ namespace ts {
return;
}
visitedSymbols.push(symbol);
const symbols = cloneSymbolTable(symbol.exports);
const symbols = cloneMap(symbol.exports);
// All export * declarations are collected in an __export symbol by the binder
const exportStars = symbol.exports["__export"];
if (exportStars) {
@@ -1655,12 +1647,12 @@ namespace ts {
}
// If symbol is directly available by its name in the symbol table
if (isAccessible(lookUp(symbols, symbol.name))) {
if (isAccessible(symbols[symbol.name])) {
return [symbol];
}
// Check if symbol is any of the alias
return forEachValue(symbols, symbolFromSymbolTable => {
return forEachProperty(symbols, symbolFromSymbolTable => {
if (symbolFromSymbolTable.flags & SymbolFlags.Alias
&& symbolFromSymbolTable.name !== "export="
&& !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) {
@@ -6622,7 +6614,7 @@ namespace ts {
const maybeCache = maybeStack[depth];
// If result is definitely true, copy assumptions to global cache, else copy to next level up
const destinationCache = (result === Ternary.True || depth === 0) ? relation : maybeStack[depth - 1];
copyMap(maybeCache, destinationCache);
copyProperties(maybeCache, destinationCache);
}
else {
// A false result goes straight into global cache (when something is false under assumptions it
@@ -7934,7 +7926,7 @@ namespace ts {
// check. This gives us a quicker out in the common case where an object type is not a function.
const resolved = resolveStructuredTypeMembers(type);
return !!(resolved.callSignatures.length || resolved.constructSignatures.length ||
hasProperty(resolved.members, "bind") && isTypeSubtypeOf(type, globalFunctionType));
resolved.members["bind"] && isTypeSubtypeOf(type, globalFunctionType));
}
function getTypeFacts(type: Type): TypeFacts {
@@ -18192,7 +18184,7 @@ namespace ts {
// otherwise - check if at least one export is value
symbolLinks.exportsSomeValue = hasExportAssignment
? !!(moduleSymbol.flags & SymbolFlags.Value)
: forEachValue(getExportsOfModule(moduleSymbol), isValue);
: forEachProperty(getExportsOfModule(moduleSymbol), isValue);
}
return symbolLinks.exportsSomeValue;

View File

@@ -486,10 +486,11 @@ namespace ts {
/* @internal */
export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
const namesOfType: string[] = [];
forEachKey(opt.type, key => {
namesOfType.push(` '${key}'`);
});
for (const key in opt.type) {
if (hasProperty(opt.type, key)) {
namesOfType.push(` '${key}'`);
}
}
return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
}
@@ -551,11 +552,11 @@ namespace ts {
s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
// Try to translate short option names to their full equivalents.
if (hasProperty(shortOptionNames, s)) {
if (s in shortOptionNames) {
s = shortOptionNames[s];
}
if (hasProperty(optionNameMap, s)) {
if (s in optionNameMap) {
const opt = optionNameMap[s];
if (opt.isTSConfigOnly) {
@@ -811,7 +812,7 @@ namespace ts {
const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
for (const id in jsonOptions) {
if (hasProperty(optionNameMap, id)) {
if (id in optionNameMap) {
const opt = optionNameMap[id];
defaultOptions[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors);
}
@@ -1011,14 +1012,14 @@ namespace ts {
removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper);
const key = keyMapper(file);
if (!hasProperty(literalFileMap, key) && !hasProperty(wildcardFileMap, key)) {
if (!(key in literalFileMap) && !(key in wildcardFileMap)) {
wildcardFileMap[key] = file;
}
}
}
const literalFiles = reduceProperties(literalFileMap, addFileToOutput, []);
const wildcardFiles = reduceProperties(wildcardFileMap, addFileToOutput, []);
const literalFiles = reduceOwnProperties(literalFileMap, addFileToOutput, []);
const wildcardFiles = reduceOwnProperties(wildcardFileMap, addFileToOutput, []);
wildcardFiles.sort(host.useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive);
return {
fileNames: literalFiles.concat(wildcardFiles),
@@ -1076,7 +1077,7 @@ namespace ts {
if (match) {
const key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase();
const flags = watchRecursivePattern.test(name) ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None;
const existingFlags = getProperty(wildcardDirectories, key);
const existingFlags = wildcardDirectories[key];
if (existingFlags === undefined || existingFlags < flags) {
wildcardDirectories[key] = flags;
if (flags === WatchDirectoryFlags.Recursive) {
@@ -1088,11 +1089,9 @@ namespace ts {
// Remove any subpaths under an existing recursively watched directory.
for (const key in wildcardDirectories) {
if (hasProperty(wildcardDirectories, key)) {
for (const recursiveKey of recursiveKeys) {
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
delete wildcardDirectories[key];
}
for (const recursiveKey of recursiveKeys) {
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
delete wildcardDirectories[key];
}
}
}
@@ -1115,7 +1114,7 @@ namespace ts {
for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) {
const higherPriorityExtension = extensions[i];
const higherPriorityPath = keyMapper(changeExtension(file, higherPriorityExtension));
if (hasProperty(literalFiles, higherPriorityPath) || hasProperty(wildcardFiles, higherPriorityPath)) {
if (higherPriorityPath in literalFiles || higherPriorityPath in wildcardFiles) {
return true;
}
}

View File

@@ -21,10 +21,8 @@ namespace ts {
const createObject = Object.create;
export function createMap<T>(): Map<T> {
/* tslint:disable:no-null-keyword */
const map: Map<T> = createObject(null);
/* tslint:enable:no-null-keyword */
export function createMap<T>(template?: MapLike<T>): Map<T> {
const map: Map<T> = createObject(null); // tslint:disable-line:no-null-keyword
// Using 'delete' on an object causes V8 to put the object in dictionary mode.
// This disables creation of hidden classes, which are expensive when an object is
@@ -32,6 +30,10 @@ namespace ts {
map["__"] = undefined;
delete map["__"];
if (template) {
copyOwnProperties(template, map);
}
return map;
}
@@ -62,7 +64,7 @@ namespace ts {
}
function contains(path: Path) {
return hasProperty(files, toKey(path));
return toKey(path) in files;
}
function remove(path: Path) {
@@ -350,82 +352,192 @@ namespace ts {
const hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Indicates whether a map-like contains an own property with the specified key.
*
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
* the 'in' operator.
*
* @param map A map-like.
* @param key A property key.
*/
export function hasProperty<T>(map: MapLike<T>, key: string): boolean {
return hasOwnProperty.call(map, key);
}
export function getKeys<T>(map: MapLike<T>): string[] {
/**
* Gets the value of an owned property in a map-like.
*
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
* an indexer.
*
* @param map A map-like.
* @param key A property key.
*/
export function getProperty<T>(map: MapLike<T>, key: string): T | undefined {
return hasOwnProperty.call(map, key) ? map[key] : undefined;
}
/**
* Gets the owned, enumerable property keys of a map-like.
*
* @param map A map-like.
*/
export function getOwnKeys<T>(map: MapLike<T>): string[] {
const keys: string[] = [];
for (const key in map) {
for (const key in map) if (hasOwnProperty.call(map, key)) {
keys.push(key);
}
return keys;
}
export function getProperty<T>(map: MapLike<T>, key: string): T | undefined {
return hasProperty(map, key) ? map[key] : undefined;
/**
* Enumerates the properties of a Map<T>, invoking a callback and returning the first truthy result.
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* forEachOwnProperties instead as it offers better runtime safety.
*
* @param map A map for which properties should be enumerated.
* @param callback A callback to invoke for each property.
*/
export function forEachProperty<T, U>(map: Map<T>, callback: (value: T, key: string) => U): U {
let result: U;
for (const key in map) {
if (result = callback(map[key], key)) break;
}
return result;
}
export function getOrUpdateProperty<T>(map: MapLike<T>, key: string, makeValue: () => T): T {
return hasProperty(map, key) ? map[key] : map[key] = makeValue();
/**
* Enumerates the owned properties of a MapLike<T>, invoking a callback and returning the first truthy result.
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* forEachProperty instead as it offers better performance.
*
* @param map A map for which properties should be enumerated.
* @param callback A callback to invoke for each property.
*/
export function forEachOwnProperty<T, U>(map: MapLike<T>, callback: (value: T, key: string) => U): U {
let result: U;
for (const key in map) if (hasOwnProperty.call(map, key)) {
if (result = callback(map[key], key)) break;
}
return result;
}
export function isEmpty<T>(map: MapLike<T>) {
for (const id in map) {
if (hasProperty(map, id)) {
return false;
/**
* Returns true if a Map<T> has some matching property.
*
* @param map A map whose properties should be tested.
* @param predicate An optional callback used to test each property.
*/
export function someProperties<T>(map: Map<T>, predicate?: (value: T, key: string) => boolean) {
for (const key in map) {
if (!predicate || predicate(map[key], key)) return true;
}
return false;
}
/**
* Performs a shallow copy of the properties from a source Map<T> to a target MapLike<T>
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* copyOwnProperties instead as it offers better runtime safety.
*
* @param source A map from which properties should be copied.
* @param target A map to which properties should be copied.
*/
export function copyProperties<T>(source: Map<T>, target: MapLike<T>): void {
for (const key in source) {
target[key] = source[key];
}
}
/**
* Performs a shallow copy of the owned properties from a source map to a target map-like.
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* copyProperties instead as it offers better performance.
*
* @param source A map-like from which properties should be copied.
* @param target A map-like to which properties should be copied.
*/
export function copyOwnProperties<T>(source: MapLike<T>, target: MapLike<T>): void {
for (const key in source) if (hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
/**
* Reduce the properties of a map.
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* reduceOwnProperties instead as it offers better runtime safety.
*
* @param map The map to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
for (const key in map) {
result = callback(result, map[key], String(key));
}
return result;
}
/**
* Reduce the properties defined on a map-like (but not from its prototype chain).
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* reduceProperties instead as it offers better performance.
*
* @param map The map-like to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceOwnProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
for (const key in map) if (hasOwnProperty.call(map, key)) {
result = callback(result, map[key], String(key));
}
return result;
}
/**
* Counts the owned properties of a map-like.
*
* @param map A map-like whose properties should be counted.
* @param predicate An optional callback used to limit which properties should be counted.
*/
export function countOwnProperties<T>(map: MapLike<T>, predicate?: (value: T, key: string) => boolean) {
let count = 0;
for (const key in map) if (hasOwnProperty.call(map, key)) {
if (!predicate || predicate(map[key], key)) {
count++;
}
}
return count;
}
/**
* Performs a shallow equality comparison of the contents of two map-likes.
*
* @param left A map whose properties should be compared.
* @param right A map whose properties should be compared.
*/
export function equalOwnProperties<T>(left: MapLike<T>, right: MapLike<T>) {
if (left === right) return true;
if (!left || !right) return false;
for (const key in left) if (hasOwnProperty.call(left, key)) {
if (!hasOwnProperty.call(right, key) === undefined || left[key] !== right[key]) return false;
}
for (const key in right) if (hasOwnProperty.call(right, key)) {
if (!hasOwnProperty.call(left, key)) return false;
}
return true;
}
export function clone<T>(object: T): T {
const result: any = {};
for (const id in object) {
result[id] = (<any>object)[id];
}
return <T>result;
}
export function extend<T1 extends MapLike<{}>, T2 extends MapLike<{}>>(first: T1 , second: T2): T1 & T2 {
const result: T1 & T2 = <any>{};
for (const id in first) {
(result as any)[id] = first[id];
}
for (const id in second) {
if (!hasProperty(result, id)) {
(result as any)[id] = second[id];
}
}
return result;
}
export function forEachValue<T, U>(map: MapLike<T>, callback: (value: T) => U): U {
let result: U;
for (const id in map) {
if (result = callback(map[id])) break;
}
return result;
}
export function forEachKey<T, U>(map: MapLike<T>, callback: (key: string) => U): U {
let result: U;
for (const id in map) {
if (result = callback(id)) break;
}
return result;
}
export function lookUp<T>(map: MapLike<T>, key: string): T {
return hasProperty(map, key) ? map[key] : undefined;
}
export function copyMap<T>(source: MapLike<T>, target: MapLike<T>): void {
for (const p in source) {
target[p] = source[p];
}
}
/**
* Creates a map from the elements of an array.
*
@@ -436,33 +548,42 @@ namespace ts {
* the same key with the given 'makeKey' function, then the element with the higher
* index in the array will be the one associated with the produced key.
*/
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
const result = createMap<T>();
forEach(array, value => {
result[makeKey(value)] = value;
});
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T>;
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue: (value: T) => U): Map<U>;
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue?: (value: T) => U): Map<T | U> {
const result = createMap<T | U>();
for (const value of array) {
result[makeKey(value)] = makeValue ? makeValue(value) : value;
}
return result;
}
/**
* Reduce the properties of a map.
*
* @param map The map to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
if (map) {
for (const key in map) {
if (hasProperty(map, key)) {
result = callback(result, map[key], String(key));
}
export function cloneMap<T>(map: Map<T>) {
const clone = createMap<T>();
copyProperties(map, clone);
return clone;
}
export function clone<T>(object: T): T {
const result: any = {};
for (const id in object) {
if (hasOwnProperty.call(object, id)) {
result[id] = (<any>object)[id];
}
}
return result;
}
export function extend<T1 extends MapLike<{}>, T2 extends MapLike<{}>>(first: T1 , second: T2): T1 & T2 {
const result: T1 & T2 = <any>{};
for (const id in first) {
(result as any)[id] = first[id];
}
for (const id in second) {
if (!hasProperty(result, id)) {
(result as any)[id] = second[id];
}
}
return result;
}

View File

@@ -157,9 +157,7 @@ namespace ts {
if (usedTypeDirectiveReferences) {
for (const directive in usedTypeDirectiveReferences) {
if (hasProperty(usedTypeDirectiveReferences, directive)) {
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
}
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
}
}
@@ -272,7 +270,7 @@ namespace ts {
usedTypeDirectiveReferences = createMap<string>();
}
for (const directive of typeReferenceDirectives) {
if (!hasProperty(usedTypeDirectiveReferences, directive)) {
if (!(directive in usedTypeDirectiveReferences)) {
usedTypeDirectiveReferences[directive] = directive;
}
}
@@ -537,14 +535,14 @@ namespace ts {
// do not need to keep track of created temp names.
function getExportDefaultTempVariableName(): string {
const baseName = "_default";
if (!hasProperty(currentIdentifiers, baseName)) {
if (!(baseName in currentIdentifiers)) {
return baseName;
}
let count = 0;
while (true) {
count++;
const name = baseName + "_" + count;
if (!hasProperty(currentIdentifiers, name)) {
if (!(name in currentIdentifiers)) {
return name;
}
}

View File

@@ -407,7 +407,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function isUniqueLocalName(name: string, container: Node): boolean {
for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
if (node.locals && hasProperty(node.locals, name)) {
if (node.locals && name in node.locals) {
// We conservatively include alias symbols to cover cases where they're emitted as locals
if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
return false;
@@ -669,8 +669,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function isUniqueName(name: string): boolean {
return !resolver.hasGlobalName(name) &&
!hasProperty(currentFileIdentifiers, name) &&
!hasProperty(generatedNameSet, name);
!(name in currentFileIdentifiers) &&
!(name in generatedNameSet);
}
// Return the next available name in the pattern _a ... _z, _0, _1, ...
@@ -2646,7 +2646,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return false;
}
return !exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, (<Identifier>node).text);
return !exportEquals && exportSpecifiers && (<Identifier>node).text in exportSpecifiers;
}
function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
@@ -3263,7 +3263,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
write(", ");
}
if (!hasProperty(seen, id.text)) {
if (!(id.text in seen)) {
emit(id);
seen[id.text] = id.text;
}
@@ -3970,7 +3970,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return;
}
if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
if (!exportEquals && exportSpecifiers && name.text in exportSpecifiers) {
for (const specifier of exportSpecifiers[name.text]) {
writeLine();
emitStart(specifier.name);
@@ -6842,7 +6842,7 @@ const _super = (function (geti, seti) {
// export { x, y }
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
const name = (specifier.propertyName || specifier.name).text;
getOrUpdateProperty(exportSpecifiers, name, () => []).push(specifier);
(exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
}
}
break;
@@ -6941,7 +6941,7 @@ const _super = (function (geti, seti) {
}
// local names set should only be added if we have anything exported
if (!exportedDeclarations && isEmpty(exportSpecifiers)) {
if (!exportedDeclarations && !someProperties(exportSpecifiers)) {
// no exported declarations (export var ...) or export specifiers (export {x})
// check if we have any non star export declarations.
let hasExportDeclarationWithExportClause = false;
@@ -7091,7 +7091,7 @@ const _super = (function (geti, seti) {
if (name) {
// do not emit duplicate entries (in case of declaration merging) in the list of hoisted variables
const text = unescapeIdentifier(name.text);
if (hasProperty(seen, text)) {
if (text in seen) {
continue;
}
else {
@@ -7460,7 +7460,7 @@ const _super = (function (geti, seti) {
// for deduplication purposes in key remove leading and trailing quotes so 'a' and "a" will be considered the same
const key = text.substr(1, text.length - 2);
if (hasProperty(groupIndices, key)) {
if (key in groupIndices) {
// deduplicate/group entries in dependency list by the dependency name
const groupIndex = groupIndices[key];
dependencyGroups[groupIndex].push(externalImports[i]);

View File

@@ -501,7 +501,7 @@ namespace ts {
if (state.traceEnabled) {
trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName);
}
matchedPattern = matchPatternOrExact(getKeys(state.compilerOptions.paths), moduleName);
matchedPattern = matchPatternOrExact(getOwnKeys(state.compilerOptions.paths), moduleName);
}
if (matchedPattern) {
@@ -875,7 +875,7 @@ namespace ts {
}
function directoryExists(directoryPath: string): boolean {
if (hasProperty(existingDirectories, directoryPath)) {
if (directoryPath in existingDirectories) {
return true;
}
if (sys.directoryExists(directoryPath)) {
@@ -903,7 +903,7 @@ namespace ts {
const hash = sys.createHash(data);
const mtimeBefore = sys.getModifiedTime(fileName);
if (mtimeBefore && hasProperty(outputFingerprints, fileName)) {
if (mtimeBefore && fileName in outputFingerprints) {
const fingerprint = outputFingerprints[fileName];
// If output has not been changed, and the file has no external modification
@@ -1041,14 +1041,9 @@ namespace ts {
const resolutions: T[] = [];
const cache = createMap<T>();
for (const name of names) {
let result: T;
if (hasProperty(cache, name)) {
result = cache[name];
}
else {
result = loader(name, containingFile);
cache[name] = result;
}
const result = name in cache
? cache[name]
: cache[name] = loader(name, containingFile);
resolutions.push(result);
}
return resolutions;
@@ -1249,7 +1244,7 @@ namespace ts {
classifiableNames = createMap<string>();
for (const sourceFile of files) {
copyMap(sourceFile.classifiableNames, classifiableNames);
copyProperties(sourceFile.classifiableNames, classifiableNames);
}
}
@@ -1277,7 +1272,7 @@ namespace ts {
(oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) ||
!arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) ||
!arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) ||
!mapIsEqualTo(oldOptions.paths, options.paths)) {
!equalOwnProperties(oldOptions.paths, options.paths)) {
return false;
}
@@ -1399,7 +1394,7 @@ namespace ts {
getSourceFile: program.getSourceFile,
getSourceFileByPath: program.getSourceFileByPath,
getSourceFiles: program.getSourceFiles,
isSourceFileFromExternalLibrary: (file: SourceFile) => !!lookUp(sourceFilesFoundSearchingNodeModules, file.path),
isSourceFileFromExternalLibrary: (file: SourceFile) => !!sourceFilesFoundSearchingNodeModules[file.path],
writeFile: writeFileCallback || (
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
isEmitBlocked,
@@ -1937,7 +1932,7 @@ namespace ts {
// If the file was previously found via a node_modules search, but is now being processed as a root file,
// then everything it sucks in may also be marked incorrectly, and needs to be checked again.
if (file && lookUp(sourceFilesFoundSearchingNodeModules, file.path) && currentNodeModulesDepth == 0) {
if (file && sourceFilesFoundSearchingNodeModules[file.path] && currentNodeModulesDepth == 0) {
sourceFilesFoundSearchingNodeModules[file.path] = false;
if (!options.noResolve) {
processReferencedFiles(file, getDirectoryPath(fileName), isDefaultLib);
@@ -1948,7 +1943,7 @@ namespace ts {
processImportedModules(file, getDirectoryPath(fileName));
}
// See if we need to reprocess the imports due to prior skipped imports
else if (file && lookUp(modulesWithElidedImports, file.path)) {
else if (file && modulesWithElidedImports[file.path]) {
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
modulesWithElidedImports[file.path] = false;
processImportedModules(file, getDirectoryPath(fileName));

View File

@@ -445,10 +445,9 @@ namespace ts {
}
function cachedFileExists(fileName: string): boolean {
if (hasProperty(cachedExistingFiles, fileName)) {
return cachedExistingFiles[fileName];
}
return cachedExistingFiles[fileName] = hostFileExists(fileName);
return fileName in cachedExistingFiles
? cachedExistingFiles[fileName]
: cachedExistingFiles[fileName] = hostFileExists(fileName);
}
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
@@ -704,9 +703,12 @@ namespace ts {
description = getDiagnosticText(option.description);
const options: string[] = [];
const element = (<CommandLineOptionOfListType>option).element;
forEachKey(<Map<number | string>>element.type, key => {
options.push(`'${key}'`);
});
const typeMap = <MapLike<number | string>>element.type;
for (const key in typeMap) {
if (hasProperty(typeMap, key)) {
options.push(`'${key}'`);
}
}
optionsDescriptionMap[description] = options;
}
else {

View File

@@ -87,25 +87,6 @@ namespace ts {
return node.end - node.pos;
}
export function mapIsEqualTo<T>(map1: MapLike<T>, map2: MapLike<T>): boolean {
if (!map1 || !map2) {
return map1 === map2;
}
return containsAll(map1, map2) && containsAll(map2, map1);
}
function containsAll<T>(map: MapLike<T>, other: MapLike<T>): boolean {
for (const key in map) {
if (!hasProperty(map, key)) {
continue;
}
if (!hasProperty(other, key) || map[key] !== other[key]) {
return false;
}
}
return true;
}
export function arrayIsEqualTo<T>(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean {
if (!array1 || !array2) {
return array1 === array2;
@@ -2792,7 +2773,7 @@ namespace ts {
}
function stringifyObject(value: any) {
return `{${reduceProperties(value, stringifyProperty, "")}}`;
return `{${reduceOwnProperties(value, stringifyProperty, "")}}`;
}
function stringifyProperty(memo: string, value: any, key: string) {