Skip to content

Commit e752861

Browse files
committed
Merge branch 'master' into 5378-equality-fix
2 parents 98e9fea + 4cba1b2 commit e752861

29 files changed

+1204
-495
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
language: node_js
22

33
node_js:
4+
- 'stable'
45
- '4'
56
- '0.10'
67

src/compiler/checker.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2990,7 +2990,7 @@ namespace ts {
29902990
(<GenericType>type).typeArguments = type.typeParameters;
29912991
type.thisType = <TypeParameter>createType(TypeFlags.TypeParameter | TypeFlags.ThisType);
29922992
type.thisType.symbol = symbol;
2993-
type.thisType.constraint = getTypeWithThisArgument(type);
2993+
type.thisType.constraint = type;
29942994
}
29952995
}
29962996
return <InterfaceType>links.declaredType;
@@ -3533,19 +3533,29 @@ namespace ts {
35333533
return type.flags & TypeFlags.UnionOrIntersection ? getPropertiesOfUnionOrIntersectionType(<UnionType>type) : getPropertiesOfObjectType(type);
35343534
}
35353535

3536+
/**
3537+
* The apparent type of a type parameter is the base constraint instantiated with the type parameter
3538+
* as the type argument for the 'this' type.
3539+
*/
3540+
function getApparentTypeOfTypeParameter(type: TypeParameter) {
3541+
if (!type.resolvedApparentType) {
3542+
let constraintType = getConstraintOfTypeParameter(type);
3543+
while (constraintType && constraintType.flags & TypeFlags.TypeParameter) {
3544+
constraintType = getConstraintOfTypeParameter(<TypeParameter>constraintType);
3545+
}
3546+
type.resolvedApparentType = getTypeWithThisArgument(constraintType || emptyObjectType, type);
3547+
}
3548+
return type.resolvedApparentType;
3549+
}
3550+
35363551
/**
35373552
* For a type parameter, return the base constraint of the type parameter. For the string, number,
35383553
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
35393554
* type itself. Note that the apparent type of a union type is the union type itself.
35403555
*/
35413556
function getApparentType(type: Type): Type {
35423557
if (type.flags & TypeFlags.TypeParameter) {
3543-
do {
3544-
type = getConstraintOfTypeParameter(<TypeParameter>type);
3545-
} while (type && type.flags & TypeFlags.TypeParameter);
3546-
if (!type) {
3547-
type = emptyObjectType;
3548-
}
3558+
type = getApparentTypeOfTypeParameter(<TypeParameter>type);
35493559
}
35503560
if (type.flags & TypeFlags.StringLike) {
35513561
type = globalStringType;
@@ -5603,18 +5613,31 @@ namespace ts {
56035613
return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
56045614
}
56055615

5616+
function isMatchingSignature(source: Signature, target: Signature, partialMatch: boolean) {
5617+
// A source signature matches a target signature if the two signatures have the same number of required,
5618+
// optional, and rest parameters.
5619+
if (source.parameters.length === target.parameters.length &&
5620+
source.minArgumentCount === target.minArgumentCount &&
5621+
source.hasRestParameter === target.hasRestParameter) {
5622+
return true;
5623+
}
5624+
// A source signature partially matches a target signature if the target signature has no fewer required
5625+
// parameters and no more overall parameters than the source signature (where a signature with a rest
5626+
// parameter is always considered to have more overall parameters than one without).
5627+
if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (
5628+
source.hasRestParameter && !target.hasRestParameter ||
5629+
source.hasRestParameter === target.hasRestParameter && source.parameters.length >= target.parameters.length)) {
5630+
return true;
5631+
}
5632+
return false;
5633+
}
5634+
56065635
function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
56075636
if (source === target) {
56085637
return Ternary.True;
56095638
}
5610-
if (source.parameters.length !== target.parameters.length ||
5611-
source.minArgumentCount !== target.minArgumentCount ||
5612-
source.hasRestParameter !== target.hasRestParameter) {
5613-
if (!partialMatch ||
5614-
source.parameters.length < target.parameters.length && !source.hasRestParameter ||
5615-
source.minArgumentCount > target.minArgumentCount) {
5616-
return Ternary.False;
5617-
}
5639+
if (!(isMatchingSignature(source, target, partialMatch))) {
5640+
return Ternary.False;
56185641
}
56195642
let result = Ternary.True;
56205643
if (source.typeParameters && target.typeParameters) {
@@ -6421,9 +6444,10 @@ namespace ts {
64216444

64226445
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
64236446
// Check that type is not any, assumed result is true, and we have variable symbol on the left
6424-
if (isTypeAny(type) || !assumeTrue || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
6447+
if (isTypeAny(type) || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
64256448
return type;
64266449
}
6450+
64276451
// Check that right operand is a function type with a prototype property
64286452
const rightType = checkExpression(expr.right);
64296453
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
@@ -6455,6 +6479,13 @@ namespace ts {
64556479
}
64566480

64576481
if (targetType) {
6482+
if (!assumeTrue) {
6483+
if (type.flags & TypeFlags.Union) {
6484+
return getUnionType(filter((<UnionType>type).types, t => !isTypeSubtypeOf(t, targetType)));
6485+
}
6486+
return type;
6487+
}
6488+
64586489
return getNarrowedType(type, targetType);
64596490
}
64606491

src/compiler/core.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,8 @@ namespace ts {
785785
};
786786

787787
export interface ObjectAllocator {
788-
getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node;
788+
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
789+
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
789790
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
790791
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
791792
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
@@ -804,17 +805,17 @@ namespace ts {
804805
function Signature(checker: TypeChecker) {
805806
}
806807

808+
function Node(kind: SyntaxKind, pos: number, end: number) {
809+
this.kind = kind;
810+
this.pos = pos;
811+
this.end = end;
812+
this.flags = NodeFlags.None;
813+
this.parent = undefined;
814+
}
815+
807816
export let objectAllocator: ObjectAllocator = {
808-
getNodeConstructor: kind => {
809-
function Node(pos: number, end: number) {
810-
this.pos = pos;
811-
this.end = end;
812-
this.flags = NodeFlags.None;
813-
this.parent = undefined;
814-
}
815-
Node.prototype = { kind };
816-
return <any>Node;
817-
},
817+
getNodeConstructor: () => <any>Node,
818+
getSourceFileConstructor: () => <any>Node,
818819
getSymbolConstructor: () => <any>Symbol,
819820
getTypeConstructor: () => <any>Type,
820821
getSignatureConstructor: () => <any>Signature

0 commit comments

Comments
 (0)