diff --git a/TypeScript b/TypeScript index 9ac13ab..d206046 160000 --- a/TypeScript +++ b/TypeScript @@ -1 +1 @@ -Subproject commit 9ac13abfd196f662ce606d8d99cb8791c2ad61fe +Subproject commit d2060466590a9cf3064da589cd321f405525f43f diff --git a/bin/ntypescript.d.ts b/bin/ntypescript.d.ts index ff01afe..b7040ac 100644 --- a/bin/ntypescript.d.ts +++ b/bin/ntypescript.d.ts @@ -2265,6 +2265,10 @@ declare namespace ts { function indexOf(array: T[], value: T): number; function indexOfAnyCharCode(text: string, charCodes: number[], start?: number): number; function countWhere(array: T[], predicate: (x: T) => boolean): number; + /** + * Filters an array by a predicate function. Returns the same array instance if the predicate is + * true for all elements, otherwise returns a new array instance containing the filtered subset. + */ function filter(array: T[], f: (x: T) => boolean): T[]; function filterMutate(array: T[], f: (x: T) => boolean): void; function map(array: T[], f: (x: T) => U): U[]; diff --git a/bin/ntypescript.js b/bin/ntypescript.js index 1f3c477..a34ce1f 100644 --- a/bin/ntypescript.js +++ b/bin/ntypescript.js @@ -1139,24 +1139,36 @@ var ts; return count; } ts.countWhere = countWhere; + /** + * Filters an array by a predicate function. Returns the same array instance if the predicate is + * true for all elements, otherwise returns a new array instance containing the filtered subset. + */ function filter(array, f) { - var result; if (array) { - result = []; - for (var _i = 0, array_3 = array; _i < array_3.length; _i++) { - var item = array_3[_i]; - if (f(item)) { - result.push(item); + var len = array.length; + var i = 0; + while (i < len && f(array[i])) + i++; + if (i < len) { + var result = array.slice(0, i); + i++; + while (i < len) { + var item = array[i]; + if (f(item)) { + result.push(item); + } + i++; } + return result; } } - return result; + return array; } ts.filter = filter; function filterMutate(array, f) { var outIndex = 0; - for (var _i = 0, array_4 = array; _i < array_4.length; _i++) { - var item = array_4[_i]; + for (var _i = 0, array_3 = array; _i < array_3.length; _i++) { + var item = array_3[_i]; if (f(item)) { array[outIndex] = item; outIndex++; @@ -1169,8 +1181,8 @@ var ts; var result; if (array) { result = []; - for (var _i = 0, array_5 = array; _i < array_5.length; _i++) { - var v = array_5[_i]; + for (var _i = 0, array_4 = array; _i < array_4.length; _i++) { + var v = array_4[_i]; result.push(f(v)); } } @@ -1189,8 +1201,8 @@ var ts; var result; if (array) { result = []; - loop: for (var _i = 0, array_6 = array; _i < array_6.length; _i++) { - var item = array_6[_i]; + loop: for (var _i = 0, array_5 = array; _i < array_5.length; _i++) { + var item = array_5[_i]; for (var _a = 0, result_1 = result; _a < result_1.length; _a++) { var res = result_1[_a]; if (areEqual ? areEqual(res, item) : res === item) { @@ -1205,8 +1217,8 @@ var ts; ts.deduplicate = deduplicate; function sum(array, prop) { var result = 0; - for (var _i = 0, array_7 = array; _i < array_7.length; _i++) { - var v = array_7[_i]; + for (var _i = 0, array_6 = array; _i < array_6.length; _i++) { + var v = array_6[_i]; result += v[prop]; } return result; @@ -13940,8 +13952,8 @@ var ts; array._children = undefined; array.pos += delta; array.end += delta; - for (var _i = 0, array_8 = array; _i < array_8.length; _i++) { - var node = array_8[_i]; + for (var _i = 0, array_7 = array; _i < array_7.length; _i++) { + var node = array_7[_i]; visitNode(node); } } @@ -14078,8 +14090,8 @@ var ts; array._children = undefined; // Adjust the pos or end (or both) of the intersecting array accordingly. adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - for (var _i = 0, array_9 = array; _i < array_9.length; _i++) { - var node = array_9[_i]; + for (var _i = 0, array_8 = array; _i < array_8.length; _i++) { + var node = array_8[_i]; visitNode(node); } return; @@ -16531,7 +16543,8 @@ var ts; TypeFacts[TypeFacts["NEUndefinedOrNull"] = 524288] = "NEUndefinedOrNull"; TypeFacts[TypeFacts["Truthy"] = 1048576] = "Truthy"; TypeFacts[TypeFacts["Falsy"] = 2097152] = "Falsy"; - TypeFacts[TypeFacts["All"] = 4194303] = "All"; + TypeFacts[TypeFacts["Discriminatable"] = 4194304] = "Discriminatable"; + TypeFacts[TypeFacts["All"] = 8388607] = "All"; // The following members encode facts about particular kinds of types for use in the getTypeFacts function. // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. @@ -16561,10 +16574,10 @@ var ts; TypeFacts[TypeFacts["TrueFacts"] = 4193668] = "TrueFacts"; TypeFacts[TypeFacts["SymbolStrictFacts"] = 1981320] = "SymbolStrictFacts"; TypeFacts[TypeFacts["SymbolFacts"] = 4193160] = "SymbolFacts"; - TypeFacts[TypeFacts["ObjectStrictFacts"] = 1972176] = "ObjectStrictFacts"; - TypeFacts[TypeFacts["ObjectFacts"] = 4184016] = "ObjectFacts"; - TypeFacts[TypeFacts["FunctionStrictFacts"] = 1970144] = "FunctionStrictFacts"; - TypeFacts[TypeFacts["FunctionFacts"] = 4181984] = "FunctionFacts"; + TypeFacts[TypeFacts["ObjectStrictFacts"] = 6166480] = "ObjectStrictFacts"; + TypeFacts[TypeFacts["ObjectFacts"] = 8378320] = "ObjectFacts"; + TypeFacts[TypeFacts["FunctionStrictFacts"] = 6164448] = "FunctionStrictFacts"; + TypeFacts[TypeFacts["FunctionFacts"] = 8376288] = "FunctionFacts"; TypeFacts[TypeFacts["UndefinedFacts"] = 2457472] = "UndefinedFacts"; TypeFacts[TypeFacts["NullFacts"] = 2340752] = "NullFacts"; })(TypeFacts || (TypeFacts = {})); @@ -21206,12 +21219,12 @@ var ts; } } } - // We deduplicate the constituent types based on object identity. If the subtypeReduction flag is - // specified we also reduce the constituent type set to only include types that aren't subtypes of - // other types. Subtype reduction is expensive for large union types and is possible only when union + // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction + // flag is specified we also reduce the constituent type set to only include types that aren't subtypes + // of other types. Subtype reduction is expensive for large union types and is possible only when union // types are known not to circularly reference themselves (as is the case with union types created by // expression constructs such as array literals and the || and ?: operators). Named types can - // circularly reference themselves and therefore cannot be deduplicated during their declaration. + // circularly reference themselves and therefore cannot be subtype reduced during their declaration. // For example, "type Item = string | (() => Item" is a named type that circularly references itself. function getUnionType(types, subtypeReduction, aliasSymbol, aliasTypeArguments) { if (types.length === 0) { @@ -21233,15 +21246,22 @@ var ts; typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType : neverType; } - else if (typeSet.length === 1) { - return typeSet[0]; + return getUnionTypeFromSortedList(typeSet, aliasSymbol, aliasTypeArguments); + } + // This function assumes the constituent type list is sorted and deduplicated. + function getUnionTypeFromSortedList(types, aliasSymbol, aliasTypeArguments) { + if (types.length === 0) { + return neverType; } - var id = getTypeListId(typeSet); + if (types.length === 1) { + return types[0]; + } + var id = getTypeListId(types); var type = unionTypes[id]; if (!type) { - var propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ 6144 /* Nullable */); + var propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ 6144 /* Nullable */); type = unionTypes[id] = createObjectType(524288 /* Union */ | propagatedFlags); - type.types = typeSet; + type.types = types; type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; } @@ -23514,17 +23534,24 @@ var ts; return undefined; } function isDiscriminantProperty(type, name) { - if (type) { - var nonNullType = getNonNullableType(type); - if (nonNullType.flags & 524288 /* Union */) { - var prop = getPropertyOfType(nonNullType, name); - if (prop && prop.flags & 268435456 /* SyntheticProperty */) { - if (prop.isDiscriminantProperty === undefined) { - prop.isDiscriminantProperty = !prop.hasCommonType && - isUnitUnionType(getTypeOfSymbol(prop)); - } - return prop.isDiscriminantProperty; + if (type && type.flags & 524288 /* Union */) { + var prop = getPropertyOfType(type, name); + if (!prop) { + // The type may be a union that includes nullable or primitive types. If filtering + // those out produces a different type, get the property from that type instead. + // Effectively, we're checking if this *could* be a discriminant property once nullable + // and primitive types are removed by other type guards. + var filteredType = getTypeWithFacts(type, 4194304 /* Discriminatable */); + if (filteredType !== type && filteredType.flags & 524288 /* Union */) { + prop = getPropertyOfType(filteredType, name); + } + } + if (prop && prop.flags & 268435456 /* SyntheticProperty */) { + if (prop.isDiscriminantProperty === undefined) { + prop.isDiscriminantProperty = !prop.hasCommonType && + isUnitUnionType(getTypeOfSymbol(prop)); } + return prop.isDiscriminantProperty; } } return false; @@ -23570,10 +23597,10 @@ var ts; // For example, when a variable of type number | string | boolean is assigned a value of type number | boolean, // we remove type string. function getAssignmentReducedType(declaredType, assignedType) { - if (declaredType !== assignedType && declaredType.flags & 524288 /* Union */) { - var reducedTypes = ts.filter(declaredType.types, function (t) { return typeMaybeAssignableTo(assignedType, t); }); - if (reducedTypes.length) { - return reducedTypes.length === 1 ? reducedTypes[0] : getUnionType(reducedTypes); + if (declaredType !== assignedType) { + var reducedType = filterType(declaredType, function (t) { return typeMaybeAssignableTo(assignedType, t); }); + if (reducedType !== neverType) { + return reducedType; } } return declaredType; @@ -23586,6 +23613,13 @@ var ts; } return result; } + function isFunctionObjectType(type) { + // We do a quick check for a "bind" property before performing the more expensive subtype + // check. This gives us a quicker out in the common case where an object type is not a function. + var resolved = resolveStructuredTypeMembers(type); + return !!(resolved.callSignatures.length || resolved.constructSignatures.length || + ts.hasProperty(resolved.members, "bind") && isTypeSubtypeOf(type, globalFunctionType)); + } function getTypeFacts(type) { var flags = type.flags; if (flags & 2 /* String */) { @@ -23614,10 +23648,9 @@ var ts; type === falseType ? 3145092 /* FalseFacts */ : 4193668 /* TrueFacts */; } if (flags & 2588672 /* ObjectType */) { - var resolved = resolveStructuredTypeMembers(type); - return resolved.callSignatures.length || resolved.constructSignatures.length || isTypeSubtypeOf(type, globalFunctionType) ? - strictNullChecks ? 1970144 /* FunctionStrictFacts */ : 4181984 /* FunctionFacts */ : - strictNullChecks ? 1972176 /* ObjectStrictFacts */ : 4184016 /* ObjectFacts */; + return isFunctionObjectType(type) ? + strictNullChecks ? 6164448 /* FunctionStrictFacts */ : 8376288 /* FunctionFacts */ : + strictNullChecks ? 6166480 /* ObjectStrictFacts */ : 8378320 /* ObjectFacts */; } if (flags & (1024 /* Void */ | 2048 /* Undefined */)) { return 2457472 /* UndefinedFacts */; @@ -23635,30 +23668,10 @@ var ts; if (flags & 1572864 /* UnionOrIntersection */) { return getTypeFactsOfTypes(type.types); } - return 4194303 /* All */; + return 8388607 /* All */; } function getTypeWithFacts(type, include) { - if (!(type.flags & 524288 /* Union */)) { - return getTypeFacts(type) & include ? type : neverType; - } - var firstType; - var types; - for (var _i = 0, _a = type.types; _i < _a.length; _i++) { - var t = _a[_i]; - if (getTypeFacts(t) & include) { - if (!firstType) { - firstType = t; - } - else { - if (!types) { - types = [firstType]; - } - types.push(t); - } - } - } - return types ? getUnionType(types) : - firstType ? firstType : neverType; + return filterType(type, function (t) { return (getTypeFacts(t) & include) !== 0; }); } function getTypeWithDefault(type, defaultExpression) { if (defaultExpression) { @@ -23813,9 +23826,12 @@ var ts; return containsType(target.types, source); } function filterType(type, f) { - return type.flags & 524288 /* Union */ ? - getUnionType(ts.filter(type.types, f)) : - f(type) ? type : neverType; + if (type.flags & 524288 /* Union */) { + var types = type.types; + var filtered = ts.filter(types, f); + return filtered === types ? type : getUnionTypeFromSortedList(filtered); + } + return f(type) ? type : neverType; } function isIncomplete(flowType) { return flowType.flags === 0; @@ -24139,7 +24155,7 @@ var ts; } if (assumeTrue && !(type.flags & 524288 /* Union */)) { // We narrow a non-union type to an exact primitive type if the non-union type - // is a supertype of that primtive type. For example, type 'any' can be narrowed + // is a supertype of that primitive type. For example, type 'any' can be narrowed // to one of the primitive types. var targetType = ts.getProperty(typeofTypesByName, literal.text); if (targetType && isTypeSubtypeOf(targetType, type)) { @@ -24220,9 +24236,9 @@ var ts; // If the current type is a union type, remove all constituents that couldn't be instances of // the candidate type. If one or more constituents remain, return a union of those. if (type.flags & 524288 /* Union */) { - var assignableConstituents = ts.filter(type.types, function (t) { return isTypeInstanceOf(t, candidate); }); - if (assignableConstituents.length) { - return getUnionType(assignableConstituents); + var assignableType = filterType(type, function (t) { return isTypeInstanceOf(t, candidate); }); + if (assignableType !== neverType) { + return assignableType; } } // If the candidate type is a subtype of the target type, narrow to the candidate type. @@ -44854,46 +44870,26 @@ var ts; return !(ts.isRootedDiskPath(moduleName) || ts.isExternalModuleNameRelative(moduleName)); } function tryReadTypesSection(packageJsonPath, baseDirectory, state) { - var jsonContent; - try { - var jsonText = state.host.readFile(packageJsonPath); - jsonContent = jsonText ? JSON.parse(jsonText) : {}; - } - catch (e) { - // gracefully handle if readFile fails or returns not JSON - jsonContent = {}; - } - var typesFile; - var fieldName; - // first try to read content of 'typings' section (backward compatibility) - if (jsonContent.typings) { - if (typeof jsonContent.typings === "string") { - fieldName = "typings"; - typesFile = jsonContent.typings; - } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "typings", typeof jsonContent.typings); + var jsonContent = readJson(packageJsonPath, state.host); + function tryReadFromField(fieldName) { + if (ts.hasProperty(jsonContent, fieldName)) { + var typesFile = jsonContent[fieldName]; + if (typeof typesFile === "string") { + var typesFilePath_1 = ts.normalizePath(ts.combinePaths(baseDirectory, typesFile)); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath_1); + } + return typesFilePath_1; } - } - } - // then read 'types' - if (!typesFile && jsonContent.types) { - if (typeof jsonContent.types === "string") { - fieldName = "types"; - typesFile = jsonContent.types; - } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "types", typeof jsonContent.types); + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile); + } } } } - if (typesFile) { - var typesFilePath = ts.normalizePath(ts.combinePaths(baseDirectory, typesFile)); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath); - } + var typesFilePath = tryReadFromField("typings") || tryReadFromField("types"); + if (typesFilePath) { return typesFilePath; } // Use the main module for inferring types if no types package specified and the allowJs is set @@ -44906,6 +44902,16 @@ var ts; } return undefined; } + function readJson(path, host) { + try { + var jsonText = host.readFile(path); + return jsonText ? JSON.parse(jsonText) : {}; + } + catch (e) { + // gracefully handle if readFile fails or returns not JSON + return {}; + } + } var typeReferenceExtensions = [".d.ts"]; function getEffectiveTypeRoots(options, host) { if (options.typeRoots) { @@ -45392,7 +45398,7 @@ var ts; } } function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, onlyRecordFailures, state) { - var packageJsonPath = ts.combinePaths(candidate, "package.json"); + var packageJsonPath = pathToPackageJson(candidate); var directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); if (directoryExists && state.host.fileExists(packageJsonPath)) { if (state.traceEnabled) { @@ -45420,6 +45426,9 @@ var ts; } return loadModuleFromFile(ts.combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); } + function pathToPackageJson(directory) { + return ts.combinePaths(directory, "package.json"); + } function loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state) { var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); var nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); @@ -45700,8 +45709,14 @@ var ts; if (host.directoryExists(root)) { for (var _a = 0, _b = host.getDirectories(root); _a < _b.length; _a++) { var typeDirectivePath = _b[_a]; - // Return just the type directive names - result = result.concat(ts.getBaseFileName(ts.normalizePath(typeDirectivePath))); + var normalized = ts.normalizePath(typeDirectivePath); + var packageJsonPath = pathToPackageJson(ts.combinePaths(root, normalized)); + // tslint:disable-next-line:no-null-keyword + var isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; + if (!isNotNeededPackage) { + // Return just the type directive names + result.push(ts.getBaseFileName(normalized)); + } } } } diff --git a/bin/typescript.d.ts b/bin/typescript.d.ts index 3df1dca..398be8e 100644 --- a/bin/typescript.d.ts +++ b/bin/typescript.d.ts @@ -2265,6 +2265,10 @@ declare namespace ts { function indexOf(array: T[], value: T): number; function indexOfAnyCharCode(text: string, charCodes: number[], start?: number): number; function countWhere(array: T[], predicate: (x: T) => boolean): number; + /** + * Filters an array by a predicate function. Returns the same array instance if the predicate is + * true for all elements, otherwise returns a new array instance containing the filtered subset. + */ function filter(array: T[], f: (x: T) => boolean): T[]; function filterMutate(array: T[], f: (x: T) => boolean): void; function map(array: T[], f: (x: T) => U): U[]; diff --git a/bin/typescript.js b/bin/typescript.js index de9262d..28cd893 100644 --- a/bin/typescript.js +++ b/bin/typescript.js @@ -1139,24 +1139,36 @@ var ts; return count; } ts.countWhere = countWhere; + /** + * Filters an array by a predicate function. Returns the same array instance if the predicate is + * true for all elements, otherwise returns a new array instance containing the filtered subset. + */ function filter(array, f) { - var result; if (array) { - result = []; - for (var _i = 0, array_3 = array; _i < array_3.length; _i++) { - var item = array_3[_i]; - if (f(item)) { - result.push(item); + var len = array.length; + var i = 0; + while (i < len && f(array[i])) + i++; + if (i < len) { + var result = array.slice(0, i); + i++; + while (i < len) { + var item = array[i]; + if (f(item)) { + result.push(item); + } + i++; } + return result; } } - return result; + return array; } ts.filter = filter; function filterMutate(array, f) { var outIndex = 0; - for (var _i = 0, array_4 = array; _i < array_4.length; _i++) { - var item = array_4[_i]; + for (var _i = 0, array_3 = array; _i < array_3.length; _i++) { + var item = array_3[_i]; if (f(item)) { array[outIndex] = item; outIndex++; @@ -1169,8 +1181,8 @@ var ts; var result; if (array) { result = []; - for (var _i = 0, array_5 = array; _i < array_5.length; _i++) { - var v = array_5[_i]; + for (var _i = 0, array_4 = array; _i < array_4.length; _i++) { + var v = array_4[_i]; result.push(f(v)); } } @@ -1189,8 +1201,8 @@ var ts; var result; if (array) { result = []; - loop: for (var _i = 0, array_6 = array; _i < array_6.length; _i++) { - var item = array_6[_i]; + loop: for (var _i = 0, array_5 = array; _i < array_5.length; _i++) { + var item = array_5[_i]; for (var _a = 0, result_1 = result; _a < result_1.length; _a++) { var res = result_1[_a]; if (areEqual ? areEqual(res, item) : res === item) { @@ -1205,8 +1217,8 @@ var ts; ts.deduplicate = deduplicate; function sum(array, prop) { var result = 0; - for (var _i = 0, array_7 = array; _i < array_7.length; _i++) { - var v = array_7[_i]; + for (var _i = 0, array_6 = array; _i < array_6.length; _i++) { + var v = array_6[_i]; result += v[prop]; } return result; @@ -13940,8 +13952,8 @@ var ts; array._children = undefined; array.pos += delta; array.end += delta; - for (var _i = 0, array_8 = array; _i < array_8.length; _i++) { - var node = array_8[_i]; + for (var _i = 0, array_7 = array; _i < array_7.length; _i++) { + var node = array_7[_i]; visitNode(node); } } @@ -14078,8 +14090,8 @@ var ts; array._children = undefined; // Adjust the pos or end (or both) of the intersecting array accordingly. adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - for (var _i = 0, array_9 = array; _i < array_9.length; _i++) { - var node = array_9[_i]; + for (var _i = 0, array_8 = array; _i < array_8.length; _i++) { + var node = array_8[_i]; visitNode(node); } return; @@ -16531,7 +16543,8 @@ var ts; TypeFacts[TypeFacts["NEUndefinedOrNull"] = 524288] = "NEUndefinedOrNull"; TypeFacts[TypeFacts["Truthy"] = 1048576] = "Truthy"; TypeFacts[TypeFacts["Falsy"] = 2097152] = "Falsy"; - TypeFacts[TypeFacts["All"] = 4194303] = "All"; + TypeFacts[TypeFacts["Discriminatable"] = 4194304] = "Discriminatable"; + TypeFacts[TypeFacts["All"] = 8388607] = "All"; // The following members encode facts about particular kinds of types for use in the getTypeFacts function. // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. @@ -16561,10 +16574,10 @@ var ts; TypeFacts[TypeFacts["TrueFacts"] = 4193668] = "TrueFacts"; TypeFacts[TypeFacts["SymbolStrictFacts"] = 1981320] = "SymbolStrictFacts"; TypeFacts[TypeFacts["SymbolFacts"] = 4193160] = "SymbolFacts"; - TypeFacts[TypeFacts["ObjectStrictFacts"] = 1972176] = "ObjectStrictFacts"; - TypeFacts[TypeFacts["ObjectFacts"] = 4184016] = "ObjectFacts"; - TypeFacts[TypeFacts["FunctionStrictFacts"] = 1970144] = "FunctionStrictFacts"; - TypeFacts[TypeFacts["FunctionFacts"] = 4181984] = "FunctionFacts"; + TypeFacts[TypeFacts["ObjectStrictFacts"] = 6166480] = "ObjectStrictFacts"; + TypeFacts[TypeFacts["ObjectFacts"] = 8378320] = "ObjectFacts"; + TypeFacts[TypeFacts["FunctionStrictFacts"] = 6164448] = "FunctionStrictFacts"; + TypeFacts[TypeFacts["FunctionFacts"] = 8376288] = "FunctionFacts"; TypeFacts[TypeFacts["UndefinedFacts"] = 2457472] = "UndefinedFacts"; TypeFacts[TypeFacts["NullFacts"] = 2340752] = "NullFacts"; })(TypeFacts || (TypeFacts = {})); @@ -21206,12 +21219,12 @@ var ts; } } } - // We deduplicate the constituent types based on object identity. If the subtypeReduction flag is - // specified we also reduce the constituent type set to only include types that aren't subtypes of - // other types. Subtype reduction is expensive for large union types and is possible only when union + // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction + // flag is specified we also reduce the constituent type set to only include types that aren't subtypes + // of other types. Subtype reduction is expensive for large union types and is possible only when union // types are known not to circularly reference themselves (as is the case with union types created by // expression constructs such as array literals and the || and ?: operators). Named types can - // circularly reference themselves and therefore cannot be deduplicated during their declaration. + // circularly reference themselves and therefore cannot be subtype reduced during their declaration. // For example, "type Item = string | (() => Item" is a named type that circularly references itself. function getUnionType(types, subtypeReduction, aliasSymbol, aliasTypeArguments) { if (types.length === 0) { @@ -21233,15 +21246,22 @@ var ts; typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType : neverType; } - else if (typeSet.length === 1) { - return typeSet[0]; + return getUnionTypeFromSortedList(typeSet, aliasSymbol, aliasTypeArguments); + } + // This function assumes the constituent type list is sorted and deduplicated. + function getUnionTypeFromSortedList(types, aliasSymbol, aliasTypeArguments) { + if (types.length === 0) { + return neverType; } - var id = getTypeListId(typeSet); + if (types.length === 1) { + return types[0]; + } + var id = getTypeListId(types); var type = unionTypes[id]; if (!type) { - var propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ 6144 /* Nullable */); + var propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ 6144 /* Nullable */); type = unionTypes[id] = createObjectType(524288 /* Union */ | propagatedFlags); - type.types = typeSet; + type.types = types; type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; } @@ -23514,17 +23534,24 @@ var ts; return undefined; } function isDiscriminantProperty(type, name) { - if (type) { - var nonNullType = getNonNullableType(type); - if (nonNullType.flags & 524288 /* Union */) { - var prop = getPropertyOfType(nonNullType, name); - if (prop && prop.flags & 268435456 /* SyntheticProperty */) { - if (prop.isDiscriminantProperty === undefined) { - prop.isDiscriminantProperty = !prop.hasCommonType && - isUnitUnionType(getTypeOfSymbol(prop)); - } - return prop.isDiscriminantProperty; + if (type && type.flags & 524288 /* Union */) { + var prop = getPropertyOfType(type, name); + if (!prop) { + // The type may be a union that includes nullable or primitive types. If filtering + // those out produces a different type, get the property from that type instead. + // Effectively, we're checking if this *could* be a discriminant property once nullable + // and primitive types are removed by other type guards. + var filteredType = getTypeWithFacts(type, 4194304 /* Discriminatable */); + if (filteredType !== type && filteredType.flags & 524288 /* Union */) { + prop = getPropertyOfType(filteredType, name); + } + } + if (prop && prop.flags & 268435456 /* SyntheticProperty */) { + if (prop.isDiscriminantProperty === undefined) { + prop.isDiscriminantProperty = !prop.hasCommonType && + isUnitUnionType(getTypeOfSymbol(prop)); } + return prop.isDiscriminantProperty; } } return false; @@ -23570,10 +23597,10 @@ var ts; // For example, when a variable of type number | string | boolean is assigned a value of type number | boolean, // we remove type string. function getAssignmentReducedType(declaredType, assignedType) { - if (declaredType !== assignedType && declaredType.flags & 524288 /* Union */) { - var reducedTypes = ts.filter(declaredType.types, function (t) { return typeMaybeAssignableTo(assignedType, t); }); - if (reducedTypes.length) { - return reducedTypes.length === 1 ? reducedTypes[0] : getUnionType(reducedTypes); + if (declaredType !== assignedType) { + var reducedType = filterType(declaredType, function (t) { return typeMaybeAssignableTo(assignedType, t); }); + if (reducedType !== neverType) { + return reducedType; } } return declaredType; @@ -23586,6 +23613,13 @@ var ts; } return result; } + function isFunctionObjectType(type) { + // We do a quick check for a "bind" property before performing the more expensive subtype + // check. This gives us a quicker out in the common case where an object type is not a function. + var resolved = resolveStructuredTypeMembers(type); + return !!(resolved.callSignatures.length || resolved.constructSignatures.length || + ts.hasProperty(resolved.members, "bind") && isTypeSubtypeOf(type, globalFunctionType)); + } function getTypeFacts(type) { var flags = type.flags; if (flags & 2 /* String */) { @@ -23614,10 +23648,9 @@ var ts; type === falseType ? 3145092 /* FalseFacts */ : 4193668 /* TrueFacts */; } if (flags & 2588672 /* ObjectType */) { - var resolved = resolveStructuredTypeMembers(type); - return resolved.callSignatures.length || resolved.constructSignatures.length || isTypeSubtypeOf(type, globalFunctionType) ? - strictNullChecks ? 1970144 /* FunctionStrictFacts */ : 4181984 /* FunctionFacts */ : - strictNullChecks ? 1972176 /* ObjectStrictFacts */ : 4184016 /* ObjectFacts */; + return isFunctionObjectType(type) ? + strictNullChecks ? 6164448 /* FunctionStrictFacts */ : 8376288 /* FunctionFacts */ : + strictNullChecks ? 6166480 /* ObjectStrictFacts */ : 8378320 /* ObjectFacts */; } if (flags & (1024 /* Void */ | 2048 /* Undefined */)) { return 2457472 /* UndefinedFacts */; @@ -23635,30 +23668,10 @@ var ts; if (flags & 1572864 /* UnionOrIntersection */) { return getTypeFactsOfTypes(type.types); } - return 4194303 /* All */; + return 8388607 /* All */; } function getTypeWithFacts(type, include) { - if (!(type.flags & 524288 /* Union */)) { - return getTypeFacts(type) & include ? type : neverType; - } - var firstType; - var types; - for (var _i = 0, _a = type.types; _i < _a.length; _i++) { - var t = _a[_i]; - if (getTypeFacts(t) & include) { - if (!firstType) { - firstType = t; - } - else { - if (!types) { - types = [firstType]; - } - types.push(t); - } - } - } - return types ? getUnionType(types) : - firstType ? firstType : neverType; + return filterType(type, function (t) { return (getTypeFacts(t) & include) !== 0; }); } function getTypeWithDefault(type, defaultExpression) { if (defaultExpression) { @@ -23813,9 +23826,12 @@ var ts; return containsType(target.types, source); } function filterType(type, f) { - return type.flags & 524288 /* Union */ ? - getUnionType(ts.filter(type.types, f)) : - f(type) ? type : neverType; + if (type.flags & 524288 /* Union */) { + var types = type.types; + var filtered = ts.filter(types, f); + return filtered === types ? type : getUnionTypeFromSortedList(filtered); + } + return f(type) ? type : neverType; } function isIncomplete(flowType) { return flowType.flags === 0; @@ -24139,7 +24155,7 @@ var ts; } if (assumeTrue && !(type.flags & 524288 /* Union */)) { // We narrow a non-union type to an exact primitive type if the non-union type - // is a supertype of that primtive type. For example, type 'any' can be narrowed + // is a supertype of that primitive type. For example, type 'any' can be narrowed // to one of the primitive types. var targetType = ts.getProperty(typeofTypesByName, literal.text); if (targetType && isTypeSubtypeOf(targetType, type)) { @@ -24220,9 +24236,9 @@ var ts; // If the current type is a union type, remove all constituents that couldn't be instances of // the candidate type. If one or more constituents remain, return a union of those. if (type.flags & 524288 /* Union */) { - var assignableConstituents = ts.filter(type.types, function (t) { return isTypeInstanceOf(t, candidate); }); - if (assignableConstituents.length) { - return getUnionType(assignableConstituents); + var assignableType = filterType(type, function (t) { return isTypeInstanceOf(t, candidate); }); + if (assignableType !== neverType) { + return assignableType; } } // If the candidate type is a subtype of the target type, narrow to the candidate type. @@ -44854,46 +44870,26 @@ var ts; return !(ts.isRootedDiskPath(moduleName) || ts.isExternalModuleNameRelative(moduleName)); } function tryReadTypesSection(packageJsonPath, baseDirectory, state) { - var jsonContent; - try { - var jsonText = state.host.readFile(packageJsonPath); - jsonContent = jsonText ? JSON.parse(jsonText) : {}; - } - catch (e) { - // gracefully handle if readFile fails or returns not JSON - jsonContent = {}; - } - var typesFile; - var fieldName; - // first try to read content of 'typings' section (backward compatibility) - if (jsonContent.typings) { - if (typeof jsonContent.typings === "string") { - fieldName = "typings"; - typesFile = jsonContent.typings; - } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "typings", typeof jsonContent.typings); + var jsonContent = readJson(packageJsonPath, state.host); + function tryReadFromField(fieldName) { + if (ts.hasProperty(jsonContent, fieldName)) { + var typesFile = jsonContent[fieldName]; + if (typeof typesFile === "string") { + var typesFilePath_1 = ts.normalizePath(ts.combinePaths(baseDirectory, typesFile)); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath_1); + } + return typesFilePath_1; } - } - } - // then read 'types' - if (!typesFile && jsonContent.types) { - if (typeof jsonContent.types === "string") { - fieldName = "types"; - typesFile = jsonContent.types; - } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "types", typeof jsonContent.types); + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile); + } } } } - if (typesFile) { - var typesFilePath = ts.normalizePath(ts.combinePaths(baseDirectory, typesFile)); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath); - } + var typesFilePath = tryReadFromField("typings") || tryReadFromField("types"); + if (typesFilePath) { return typesFilePath; } // Use the main module for inferring types if no types package specified and the allowJs is set @@ -44906,6 +44902,16 @@ var ts; } return undefined; } + function readJson(path, host) { + try { + var jsonText = host.readFile(path); + return jsonText ? JSON.parse(jsonText) : {}; + } + catch (e) { + // gracefully handle if readFile fails or returns not JSON + return {}; + } + } var typeReferenceExtensions = [".d.ts"]; function getEffectiveTypeRoots(options, host) { if (options.typeRoots) { @@ -45392,7 +45398,7 @@ var ts; } } function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, onlyRecordFailures, state) { - var packageJsonPath = ts.combinePaths(candidate, "package.json"); + var packageJsonPath = pathToPackageJson(candidate); var directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); if (directoryExists && state.host.fileExists(packageJsonPath)) { if (state.traceEnabled) { @@ -45420,6 +45426,9 @@ var ts; } return loadModuleFromFile(ts.combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); } + function pathToPackageJson(directory) { + return ts.combinePaths(directory, "package.json"); + } function loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state) { var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); var nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); @@ -45700,8 +45709,14 @@ var ts; if (host.directoryExists(root)) { for (var _a = 0, _b = host.getDirectories(root); _a < _b.length; _a++) { var typeDirectivePath = _b[_a]; - // Return just the type directive names - result = result.concat(ts.getBaseFileName(ts.normalizePath(typeDirectivePath))); + var normalized = ts.normalizePath(typeDirectivePath); + var packageJsonPath = pathToPackageJson(ts.combinePaths(root, normalized)); + // tslint:disable-next-line:no-null-keyword + var isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; + if (!isNotNeededPackage) { + // Return just the type directive names + result.push(ts.getBaseFileName(normalized)); + } } } } diff --git a/kicktravis b/kicktravis index 352dcc1..60470cc 100644 --- a/kicktravis +++ b/kicktravis @@ -1 +1 @@ -2016-08-12 [ci skip] Version: 1.201608120008.1+9ac13abfd196f662ce606d8d99cb8791c2ad61fe +2016-08-13 [ci skip] Version: 1.201608130005.1+d2060466590a9cf3064da589cd321f405525f43f diff --git a/package.json b/package.json index 3bacb43..e0cda14 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ntypescript", - "version": "1.201608120008.1+9ac13abfd196f662ce606d8d99cb8791c2ad61fe", + "version": "1.201608130005.1+d2060466590a9cf3064da589cd321f405525f43f", "description": "A nicer version of microsoft/typescript packaged and released for API developers", "main": "./bin/ntypescript.js", "bin": { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 43ec22d..4e04c5f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -245,7 +245,8 @@ namespace ts { NEUndefinedOrNull = 1 << 19, // x != undefined / x != null Truthy = 1 << 20, // x Falsy = 1 << 21, // !x - All = (1 << 22) - 1, + Discriminatable = 1 << 22, // May have discriminant property + All = (1 << 23) - 1, // The following members encode facts about particular kinds of types for use in the getTypeFacts function. // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. @@ -275,9 +276,9 @@ namespace ts { TrueFacts = BaseBooleanFacts | Truthy, SymbolStrictFacts = TypeofEQSymbol | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, SymbolFacts = SymbolStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, - ObjectStrictFacts = TypeofEQObject | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | NEUndefined | NENull | NEUndefinedOrNull | Truthy, + ObjectStrictFacts = TypeofEQObject | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | NEUndefined | NENull | NEUndefinedOrNull | Truthy | Discriminatable, ObjectFacts = ObjectStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, - FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, + FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy | Discriminatable, FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy, NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy, @@ -5351,12 +5352,12 @@ namespace ts { } } - // We deduplicate the constituent types based on object identity. If the subtypeReduction flag is - // specified we also reduce the constituent type set to only include types that aren't subtypes of - // other types. Subtype reduction is expensive for large union types and is possible only when union + // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction + // flag is specified we also reduce the constituent type set to only include types that aren't subtypes + // of other types. Subtype reduction is expensive for large union types and is possible only when union // types are known not to circularly reference themselves (as is the case with union types created by // expression constructs such as array literals and the || and ?: operators). Named types can - // circularly reference themselves and therefore cannot be deduplicated during their declaration. + // circularly reference themselves and therefore cannot be subtype reduced during their declaration. // For example, "type Item = string | (() => Item" is a named type that circularly references itself. function getUnionType(types: Type[], subtypeReduction?: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type { if (types.length === 0) { @@ -5378,15 +5379,23 @@ namespace ts { typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType : neverType; } - else if (typeSet.length === 1) { - return typeSet[0]; + return getUnionTypeFromSortedList(typeSet, aliasSymbol, aliasTypeArguments); + } + + // This function assumes the constituent type list is sorted and deduplicated. + function getUnionTypeFromSortedList(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type { + if (types.length === 0) { + return neverType; } - const id = getTypeListId(typeSet); + if (types.length === 1) { + return types[0]; + } + const id = getTypeListId(types); let type = unionTypes[id]; if (!type) { - const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable); + const propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); type = unionTypes[id] = createObjectType(TypeFlags.Union | propagatedFlags); - type.types = typeSet; + type.types = types; type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; } @@ -7848,17 +7857,24 @@ namespace ts { } function isDiscriminantProperty(type: Type, name: string) { - if (type) { - const nonNullType = getNonNullableType(type); - if (nonNullType.flags & TypeFlags.Union) { - const prop = getPropertyOfType(nonNullType, name); - if (prop && prop.flags & SymbolFlags.SyntheticProperty) { - if ((prop).isDiscriminantProperty === undefined) { - (prop).isDiscriminantProperty = !(prop).hasCommonType && - isUnitUnionType(getTypeOfSymbol(prop)); - } - return (prop).isDiscriminantProperty; + if (type && type.flags & TypeFlags.Union) { + let prop = getPropertyOfType(type, name); + if (!prop) { + // The type may be a union that includes nullable or primitive types. If filtering + // those out produces a different type, get the property from that type instead. + // Effectively, we're checking if this *could* be a discriminant property once nullable + // and primitive types are removed by other type guards. + const filteredType = getTypeWithFacts(type, TypeFacts.Discriminatable); + if (filteredType !== type && filteredType.flags & TypeFlags.Union) { + prop = getPropertyOfType(filteredType, name); + } + } + if (prop && prop.flags & SymbolFlags.SyntheticProperty) { + if ((prop).isDiscriminantProperty === undefined) { + (prop).isDiscriminantProperty = !(prop).hasCommonType && + isUnitUnionType(getTypeOfSymbol(prop)); } + return (prop).isDiscriminantProperty; } } return false; @@ -7907,10 +7923,10 @@ namespace ts { // For example, when a variable of type number | string | boolean is assigned a value of type number | boolean, // we remove type string. function getAssignmentReducedType(declaredType: UnionType, assignedType: Type) { - if (declaredType !== assignedType && declaredType.flags & TypeFlags.Union) { - const reducedTypes = filter(declaredType.types, t => typeMaybeAssignableTo(assignedType, t)); - if (reducedTypes.length) { - return reducedTypes.length === 1 ? reducedTypes[0] : getUnionType(reducedTypes); + if (declaredType !== assignedType) { + const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t)); + if (reducedType !== neverType) { + return reducedType; } } return declaredType; @@ -7924,6 +7940,14 @@ namespace ts { return result; } + function isFunctionObjectType(type: ObjectType): boolean { + // We do a quick check for a "bind" property before performing the more expensive subtype + // 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)); + } + function getTypeFacts(type: Type): TypeFacts { const flags = type.flags; if (flags & TypeFlags.String) { @@ -7952,8 +7976,7 @@ namespace ts { type === falseType ? TypeFacts.FalseFacts : TypeFacts.TrueFacts; } if (flags & TypeFlags.ObjectType) { - const resolved = resolveStructuredTypeMembers(type); - return resolved.callSignatures.length || resolved.constructSignatures.length || isTypeSubtypeOf(type, globalFunctionType) ? + return isFunctionObjectType(type) ? strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts : strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; } @@ -7977,26 +8000,7 @@ namespace ts { } function getTypeWithFacts(type: Type, include: TypeFacts) { - if (!(type.flags & TypeFlags.Union)) { - return getTypeFacts(type) & include ? type : neverType; - } - let firstType: Type; - let types: Type[]; - for (const t of (type as UnionType).types) { - if (getTypeFacts(t) & include) { - if (!firstType) { - firstType = t; - } - else { - if (!types) { - types = [firstType]; - } - types.push(t); - } - } - } - return types ? getUnionType(types) : - firstType ? firstType : neverType; + return filterType(type, t => (getTypeFacts(t) & include) !== 0); } function getTypeWithDefault(type: Type, defaultExpression: Expression) { @@ -8172,9 +8176,12 @@ namespace ts { } function filterType(type: Type, f: (t: Type) => boolean): Type { - return type.flags & TypeFlags.Union ? - getUnionType(filter((type).types, f)) : - f(type) ? type : neverType; + if (type.flags & TypeFlags.Union) { + const types = (type).types; + const filtered = filter(types, f); + return filtered === types ? type : getUnionTypeFromSortedList(filtered); + } + return f(type) ? type : neverType; } function isIncomplete(flowType: FlowType) { @@ -8512,7 +8519,7 @@ namespace ts { } if (assumeTrue && !(type.flags & TypeFlags.Union)) { // We narrow a non-union type to an exact primitive type if the non-union type - // is a supertype of that primtive type. For example, type 'any' can be narrowed + // is a supertype of that primitive type. For example, type 'any' can be narrowed // to one of the primitive types. const targetType = getProperty(typeofTypesByName, literal.text); if (targetType && isTypeSubtypeOf(targetType, type)) { @@ -8601,9 +8608,9 @@ namespace ts { // If the current type is a union type, remove all constituents that couldn't be instances of // the candidate type. If one or more constituents remain, return a union of those. if (type.flags & TypeFlags.Union) { - const assignableConstituents = filter((type).types, t => isTypeInstanceOf(t, candidate)); - if (assignableConstituents.length) { - return getUnionType(assignableConstituents); + const assignableType = filterType(type, t => isTypeInstanceOf(t, candidate)); + if (assignableType !== neverType) { + return assignableType; } } // If the candidate type is a subtype of the target type, narrow to the candidate type. diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5494101..1d89d00 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -147,17 +147,29 @@ namespace ts { return count; } + /** + * Filters an array by a predicate function. Returns the same array instance if the predicate is + * true for all elements, otherwise returns a new array instance containing the filtered subset. + */ export function filter(array: T[], f: (x: T) => boolean): T[] { - let result: T[]; if (array) { - result = []; - for (const item of array) { - if (f(item)) { - result.push(item); + const len = array.length; + let i = 0; + while (i < len && f(array[i])) i++; + if (i < len) { + const result = array.slice(0, i); + i++; + while (i < len) { + const item = array[i]; + if (f(item)) { + result.push(item); + } + i++; } + return result; } } - return result; + return array; } export function filterMutate(array: T[], f: (x: T) => boolean): void { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7d40b2f..67a9360 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -119,49 +119,31 @@ namespace ts { } function tryReadTypesSection(packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string { - let jsonContent: { typings?: string, types?: string, main?: string }; - try { - const jsonText = state.host.readFile(packageJsonPath); - jsonContent = jsonText ? <{ typings?: string, types?: string, main?: string }>JSON.parse(jsonText) : {}; - } - catch (e) { - // gracefully handle if readFile fails or returns not JSON - jsonContent = {}; - } - - let typesFile: string; - let fieldName: string; - // first try to read content of 'typings' section (backward compatibility) - if (jsonContent.typings) { - if (typeof jsonContent.typings === "string") { - fieldName = "typings"; - typesFile = jsonContent.typings; - } - else { - if (state.traceEnabled) { - trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "typings", typeof jsonContent.typings); + const jsonContent = readJson(packageJsonPath, state.host); + + function tryReadFromField(fieldName: string) { + if (hasProperty(jsonContent, fieldName)) { + const typesFile = (jsonContent)[fieldName]; + if (typeof typesFile === "string") { + const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile)); + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath); + } + return typesFilePath; } - } - } - // then read 'types' - if (!typesFile && jsonContent.types) { - if (typeof jsonContent.types === "string") { - fieldName = "types"; - typesFile = jsonContent.types; - } - else { - if (state.traceEnabled) { - trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "types", typeof jsonContent.types); + else { + if (state.traceEnabled) { + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile); + } } } } - if (typesFile) { - const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile)); - if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath); - } + + const typesFilePath = tryReadFromField("typings") || tryReadFromField("types"); + if (typesFilePath) { return typesFilePath; } + // Use the main module for inferring types if no types package specified and the allowJs is set if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") { if (state.traceEnabled) { @@ -173,6 +155,17 @@ namespace ts { return undefined; } + function readJson(path: string, host: ModuleResolutionHost): { typings?: string, types?: string, main?: string } { + try { + const jsonText = host.readFile(path); + return jsonText ? JSON.parse(jsonText) : {}; + } + catch (e) { + // gracefully handle if readFile fails or returns not JSON + return {}; + } + } + const typeReferenceExtensions = [".d.ts"]; function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) { @@ -717,7 +710,7 @@ namespace ts { } function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string { - const packageJsonPath = combinePaths(candidate, "package.json"); + const packageJsonPath = pathToPackageJson(candidate); const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); if (directoryExists && state.host.fileExists(packageJsonPath)) { if (state.traceEnabled) { @@ -747,6 +740,10 @@ namespace ts { return loadModuleFromFile(combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); } + function pathToPackageJson(directory: string): string { + return combinePaths(directory, "package.json"); + } + function loadModuleFromNodeModulesFolder(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string { const nodeModulesFolder = combinePaths(directory, "node_modules"); const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); @@ -1070,15 +1067,21 @@ namespace ts { } // Walk the primary type lookup locations - let result: string[] = []; + const result: string[] = []; if (host.directoryExists && host.getDirectories) { const typeRoots = getEffectiveTypeRoots(options, host); if (typeRoots) { for (const root of typeRoots) { if (host.directoryExists(root)) { for (const typeDirectivePath of host.getDirectories(root)) { - // Return just the type directive names - result = result.concat(getBaseFileName(normalizePath(typeDirectivePath))); + const normalized = normalizePath(typeDirectivePath); + const packageJsonPath = pathToPackageJson(combinePaths(root, normalized)); + // tslint:disable-next-line:no-null-keyword + const isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; + if (!isNotNeededPackage) { + // Return just the type directive names + result.push(getBaseFileName(normalized)); + } } } }