Skip to content

Commit 7ea134b

Browse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint
2 parents 9efb31c + 72bb4c2 commit 7ea134b

36 files changed

+1079
-44
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@
123123
"fs": false,
124124
"os": false,
125125
"path": false,
126-
"@microsoft/typescript-etw": false
126+
"crypto": false,
127+
"buffer": false,
128+
"@microsoft/typescript-etw": false,
129+
"source-map-support": false
127130
},
128131
"dependencies": {}
129132
}

src/compiler/binder.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,23 @@ namespace ts {
18271827
bindPotentiallyMissingNamespaces(file.symbol, declName.parent, isTopLevel,
18281828
!!findAncestor(declName, d => isPropertyAccessExpression(d) && d.name.escapedText === "prototype"), /*containerIsClass*/ false);
18291829
const oldContainer = container;
1830-
container = isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name : declName.parent.expression;
1830+
switch (getAssignmentDeclarationPropertyAccessKind(declName.parent)) {
1831+
case AssignmentDeclarationKind.ExportsProperty:
1832+
case AssignmentDeclarationKind.ModuleExports:
1833+
container = file;
1834+
break;
1835+
case AssignmentDeclarationKind.ThisProperty:
1836+
container = declName.parent.expression;
1837+
break;
1838+
case AssignmentDeclarationKind.PrototypeProperty:
1839+
container = (declName.parent.expression as PropertyAccessExpression).name;
1840+
break;
1841+
case AssignmentDeclarationKind.Property:
1842+
container = isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name : declName.parent.expression;
1843+
break;
1844+
case AssignmentDeclarationKind.None:
1845+
return Debug.fail("Shouldn't have detected typedef or enum on non-assignment declaration");
1846+
}
18311847
declareModuleMember(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
18321848
container = oldContainer;
18331849
}

src/compiler/checker.ts

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12882,7 +12882,7 @@ namespace ts {
1288212882
// and we need to handle "each" relations before "some" relations for the same kind of type.
1288312883
if (source.flags & TypeFlags.Union) {
1288412884
result = relation === comparableRelation ?
12885-
someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive)) :
12885+
someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), isIntersectionConstituent) :
1288612886
eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive));
1288712887
}
1288812888
else {
@@ -12920,7 +12920,7 @@ namespace ts {
1292012920
//
1292112921
// - For a primitive type or type parameter (such as 'number = A & B') there is no point in
1292212922
// breaking the intersection apart.
12923-
result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false);
12923+
result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false, /*isIntersectionConstituent*/ true);
1292412924
}
1292512925
if (!result && (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable)) {
1292612926
if (result = recursiveTypeRelatedTo(source, target, reportErrors, isIntersectionConstituent)) {
@@ -13199,14 +13199,14 @@ namespace ts {
1319913199
return result;
1320013200
}
1320113201

13202-
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
13202+
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, isIntersectionConstituent: boolean): Ternary {
1320313203
const sourceTypes = source.types;
1320413204
if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) {
1320513205
return Ternary.True;
1320613206
}
1320713207
const len = sourceTypes.length;
1320813208
for (let i = 0; i < len; i++) {
13209-
const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1);
13209+
const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1, /*headMessage*/ undefined, isIntersectionConstituent);
1321013210
if (related) {
1321113211
return related;
1321213212
}
@@ -14546,6 +14546,9 @@ namespace ts {
1454614546
// though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely
1454714547
// expanding. Effectively, we will generate a false positive when two types are structurally equal to at least 5
1454814548
// levels, but unequal at some level beyond that.
14549+
// In addition, this will also detect when an indexed access has been chained off of 5 or more times (which is essentially
14550+
// the dual of the structural comparison), and likewise mark the type as deeply nested, potentially adding false positives
14551+
// for finite but deeply expanding indexed accesses (eg, for `Q[P1][P2][P3][P4][P5]`).
1454914552
function isDeeplyNestedType(type: Type, stack: Type[], depth: number): boolean {
1455014553
// We track all object types that have an associated symbol (representing the origin of the type)
1455114554
if (depth >= 5 && type.flags & TypeFlags.Object) {
@@ -14561,9 +14564,31 @@ namespace ts {
1456114564
}
1456214565
}
1456314566
}
14567+
if (depth >= 5 && type.flags & TypeFlags.IndexedAccess) {
14568+
const root = getRootObjectTypeFromIndexedAccessChain(type);
14569+
let count = 0;
14570+
for (let i = 0; i < depth; i++) {
14571+
const t = stack[i];
14572+
if (getRootObjectTypeFromIndexedAccessChain(t) === root) {
14573+
count++;
14574+
if (count >= 5) return true;
14575+
}
14576+
}
14577+
}
1456414578
return false;
1456514579
}
1456614580

14581+
/**
14582+
* Gets the leftmost object type in a chain of indexed accesses, eg, in A[P][Q], returns A
14583+
*/
14584+
function getRootObjectTypeFromIndexedAccessChain(type: Type) {
14585+
let t = type;
14586+
while (t.flags & TypeFlags.IndexedAccess) {
14587+
t = (t as IndexedAccessType).objectType;
14588+
}
14589+
return t;
14590+
}
14591+
1456714592
function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
1456814593
return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False;
1456914594
}
@@ -15584,11 +15609,14 @@ namespace ts {
1558415609
if (inferFromMatchingType(source, (<UnionType>target).types, isTypeCloselyMatchedBy)) return;
1558515610
}
1558615611
}
15587-
else if (target.flags & TypeFlags.Intersection && some((<IntersectionType>target).types, t => !!getInferenceInfoForType(t))) {
15612+
else if (target.flags & TypeFlags.Intersection && some((<IntersectionType>target).types,
15613+
t => !!getInferenceInfoForType(t) || (isGenericMappedType(t) && !!getInferenceInfoForType(getHomomorphicTypeVariable(t) || neverType)))) {
1558815614
// We reduce intersection types only when they contain naked type parameters. For example, when
1558915615
// inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and
1559015616
// infer { extra: any } for T. But when inferring to 'string[] & Iterable<T>' we want to keep the
1559115617
// string[] on the source side and infer string for T.
15618+
// Likewise, we consider a homomorphic mapped type constrainted to the target type parameter as similar to a "naked type variable"
15619+
// in such scenarios.
1559215620
if (source.flags & TypeFlags.Intersection) {
1559315621
// Infer between identically matching source and target constituents and remove the matching types.
1559415622
const [sources, targets] = inferFromMatchingTypes((<IntersectionType>source).types, (<IntersectionType>target).types, isTypeIdenticalTo);
@@ -21574,13 +21602,13 @@ namespace ts {
2157421602
checkMode: CheckMode,
2157521603
reportErrors: boolean,
2157621604
containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
21577-
) {
21605+
): ReadonlyArray<Diagnostic> | undefined {
2157821606

2157921607
const errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } = { errors: undefined, skipLogging: true };
2158021608
if (isJsxOpeningLikeElement(node)) {
2158121609
if (!checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors, containingMessageChain, errorOutputContainer)) {
2158221610
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors");
21583-
return errorOutputContainer.errors || [];
21611+
return errorOutputContainer.errors || emptyArray;
2158421612
}
2158521613
return undefined;
2158621614
}
@@ -21595,7 +21623,7 @@ namespace ts {
2159521623
const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1;
2159621624
if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer)) {
2159721625
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "this parameter should have errors when reporting errors");
21598-
return errorOutputContainer.errors || [];
21626+
return errorOutputContainer.errors || emptyArray;
2159921627
}
2160021628
}
2160121629
const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
@@ -21613,7 +21641,7 @@ namespace ts {
2161321641
if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containingMessageChain, errorOutputContainer)) {
2161421642
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors");
2161521643
maybeAddMissingAwaitInfo(arg, checkArgType, paramType);
21616-
return errorOutputContainer.errors || [];
21644+
return errorOutputContainer.errors || emptyArray;
2161721645
}
2161821646
}
2161921647
}
@@ -21623,7 +21651,7 @@ namespace ts {
2162321651
if (!checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) {
2162421652
Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors");
2162521653
maybeAddMissingAwaitInfo(errorNode, spreadType, restType);
21626-
return errorOutputContainer.errors || [];
21654+
return errorOutputContainer.errors || emptyArray;
2162721655
}
2162821656
}
2162921657
return undefined;
@@ -22014,7 +22042,7 @@ namespace ts {
2201422042
}
2201522043
}
2201622044
else {
22017-
const allDiagnostics: DiagnosticRelatedInformation[][] = [];
22045+
const allDiagnostics: (readonly DiagnosticRelatedInformation[])[] = [];
2201822046
let max = 0;
2201922047
let min = Number.MAX_VALUE;
2202022048
let minIndex = 0;

src/compiler/perfLogger.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ namespace ts {
3636
etwModule = undefined;
3737
}
3838

39-
/** Performance logger that will generate ETW events if possible */
40-
export const perfLogger: PerfLogger = etwModule ? etwModule : nullLogger;
41-
42-
perfLogger.logInfoEvent(`Starting TypeScript v${versionMajorMinor} with command line: ${JSON.stringify(process.argv)}`);
39+
/** Performance logger that will generate ETW events if possible - check for `logEvent` member, as `etwModule` will be `{}` when browserified */
40+
export const perfLogger: PerfLogger = etwModule && etwModule.logEvent ? etwModule : nullLogger;
41+
const args = typeof process === "undefined" ? [] : process.argv;
42+
perfLogger.logInfoEvent(`Starting TypeScript v${versionMajorMinor} with command line: ${JSON.stringify(args)}`);
4343
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts]
2+
type PartialDeep<T> = {[K in keyof T]?: PartialDeep<T[K]>};
3+
type Many<T> = T | readonly T[];
4+
5+
interface Collection<T> {
6+
sortBy(...iteratees: Many<PartialDeep<T>>[]): Collection<T>;
7+
}
8+
9+
const x: Collection<{x: number}> = (null as any as Collection<{x: number, y: number}>);
10+
11+
export {};
12+
13+
14+
//// [comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.js]
15+
"use strict";
16+
exports.__esModule = true;
17+
var x = null;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
=== tests/cases/compiler/comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts ===
2+
type PartialDeep<T> = {[K in keyof T]?: PartialDeep<T[K]>};
3+
>PartialDeep : Symbol(PartialDeep, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 0))
4+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 17))
5+
>K : Symbol(K, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 24))
6+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 17))
7+
>PartialDeep : Symbol(PartialDeep, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 0))
8+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 17))
9+
>K : Symbol(K, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 24))
10+
11+
type Many<T> = T | readonly T[];
12+
>Many : Symbol(Many, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 59))
13+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 1, 10))
14+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 1, 10))
15+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 1, 10))
16+
17+
interface Collection<T> {
18+
>Collection : Symbol(Collection, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 1, 32))
19+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 3, 21))
20+
21+
sortBy(...iteratees: Many<PartialDeep<T>>[]): Collection<T>;
22+
>sortBy : Symbol(Collection.sortBy, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 3, 25))
23+
>iteratees : Symbol(iteratees, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 4, 11))
24+
>Many : Symbol(Many, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 59))
25+
>PartialDeep : Symbol(PartialDeep, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 0, 0))
26+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 3, 21))
27+
>Collection : Symbol(Collection, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 1, 32))
28+
>T : Symbol(T, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 3, 21))
29+
}
30+
31+
const x: Collection<{x: number}> = (null as any as Collection<{x: number, y: number}>);
32+
>x : Symbol(x, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 7, 5))
33+
>Collection : Symbol(Collection, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 1, 32))
34+
>x : Symbol(x, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 7, 21))
35+
>Collection : Symbol(Collection, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 1, 32))
36+
>x : Symbol(x, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 7, 63))
37+
>y : Symbol(y, Decl(comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts, 7, 73))
38+
39+
export {};
40+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
=== tests/cases/compiler/comparisonOfPartialDeepAndIndexedAccessTerminatesWithoutError.ts ===
2+
type PartialDeep<T> = {[K in keyof T]?: PartialDeep<T[K]>};
3+
>PartialDeep : PartialDeep<T>
4+
5+
type Many<T> = T | readonly T[];
6+
>Many : Many<T>
7+
8+
interface Collection<T> {
9+
sortBy(...iteratees: Many<PartialDeep<T>>[]): Collection<T>;
10+
>sortBy : (...iteratees: Many<PartialDeep<T>>[]) => Collection<T>
11+
>iteratees : Many<PartialDeep<T>>[]
12+
}
13+
14+
const x: Collection<{x: number}> = (null as any as Collection<{x: number, y: number}>);
15+
>x : Collection<{ x: number; }>
16+
>x : number
17+
>(null as any as Collection<{x: number, y: number}>) : Collection<{ x: number; y: number; }>
18+
>null as any as Collection<{x: number, y: number}> : Collection<{ x: number; y: number; }>
19+
>null as any : any
20+
>null : null
21+
>x : number
22+
>y : number
23+
24+
export {};
25+

0 commit comments

Comments
 (0)