Skip to content

Commit 4af3937

Browse files
author
Arthur Ozga
committed
Merge branch 'master' into interfaceFixes
2 parents d75d548 + 757af49 commit 4af3937

File tree

73 files changed

+1798
-390
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1798
-390
lines changed

.travis.yml

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

33
node_js:
44
- 'stable'
5+
- '6'
56
- '4'
67

78
sudo: false

netci.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import jobs.generation.Utilities;
55
def project = GithubProject
66
def branch = GithubBranchName
77

8-
def nodeVersions = ['stable', '4']
8+
def nodeVersions = ['stable', '6', '4']
99

1010
nodeVersions.each { nodeVer ->
1111

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"tsserver": "./bin/tsserver"
2727
},
2828
"engines": {
29-
"node": ">=0.8.0"
29+
"node": ">=4.2.0"
3030
},
3131
"devDependencies": {
3232
"@types/browserify": "latest",

src/compiler/checker.ts

Lines changed: 93 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -472,9 +472,7 @@ namespace ts {
472472
// other kinds of value declarations take precedence over modules
473473
target.valueDeclaration = source.valueDeclaration;
474474
}
475-
forEach(source.declarations, node => {
476-
target.declarations.push(node);
477-
});
475+
addRange(target.declarations, source.declarations);
478476
if (source.members) {
479477
if (!target.members) target.members = createMap<Symbol>();
480478
mergeSymbolTable(target.members, source.members);
@@ -1106,7 +1104,7 @@ namespace ts {
11061104
}
11071105

11081106
function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined {
1109-
return forEach(symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined);
1107+
return find<Declaration>(symbol.declarations, isAliasSymbolDeclaration);
11101108
}
11111109

11121110
function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration): Symbol {
@@ -1447,9 +1445,8 @@ namespace ts {
14471445
// May be an untyped module. If so, ignore resolutionDiagnostic.
14481446
if (!isRelative && resolvedModule && !extensionIsTypeScript(resolvedModule.extension)) {
14491447
if (isForAugmentation) {
1450-
Debug.assert(!!moduleNotFoundError);
14511448
const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
1452-
error(errorNode, diag, moduleName, resolvedModule.resolvedFileName);
1449+
error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName);
14531450
}
14541451
else if (compilerOptions.noImplicitAny && moduleNotFoundError) {
14551452
error(errorNode,
@@ -1750,7 +1747,19 @@ namespace ts {
17501747
}
17511748

17521749
function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] {
1753-
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable): Symbol[] {
1750+
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable) {
1751+
return getAccessibleSymbolChainFromSymbolTableWorker(symbols, []);
1752+
}
1753+
1754+
function getAccessibleSymbolChainFromSymbolTableWorker(symbols: SymbolTable, visitedSymbolTables: SymbolTable[]): Symbol[] {
1755+
if (contains(visitedSymbolTables, symbols)) {
1756+
return undefined;
1757+
}
1758+
visitedSymbolTables.push(symbols);
1759+
const result = trySymbolTable(symbols);
1760+
visitedSymbolTables.pop();
1761+
return result;
1762+
17541763
function canQualifySymbol(symbolFromSymbolTable: Symbol, meaning: SymbolFlags) {
17551764
// If the symbol is equivalent and doesn't need further qualification, this symbol is accessible
17561765
if (!needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning)) {
@@ -1772,34 +1781,36 @@ namespace ts {
17721781
}
17731782
}
17741783

1775-
// If symbol is directly available by its name in the symbol table
1776-
if (isAccessible(symbols[symbol.name])) {
1777-
return [symbol];
1778-
}
1784+
function trySymbolTable(symbols: SymbolTable) {
1785+
// If symbol is directly available by its name in the symbol table
1786+
if (isAccessible(symbols[symbol.name])) {
1787+
return [symbol];
1788+
}
17791789

1780-
// Check if symbol is any of the alias
1781-
return forEachProperty(symbols, symbolFromSymbolTable => {
1782-
if (symbolFromSymbolTable.flags & SymbolFlags.Alias
1783-
&& symbolFromSymbolTable.name !== "export="
1784-
&& !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) {
1785-
if (!useOnlyExternalAliasing || // We can use any type of alias to get the name
1786-
// Is this external alias, then use it to name
1787-
ts.forEach(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) {
1790+
// Check if symbol is any of the alias
1791+
return forEachProperty(symbols, symbolFromSymbolTable => {
1792+
if (symbolFromSymbolTable.flags & SymbolFlags.Alias
1793+
&& symbolFromSymbolTable.name !== "export="
1794+
&& !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) {
1795+
if (!useOnlyExternalAliasing || // We can use any type of alias to get the name
1796+
// Is this external alias, then use it to name
1797+
ts.forEach(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) {
17881798

1789-
const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
1790-
if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
1791-
return [symbolFromSymbolTable];
1792-
}
1799+
const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
1800+
if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
1801+
return [symbolFromSymbolTable];
1802+
}
17931803

1794-
// Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
1795-
// but only if the symbolFromSymbolTable can be qualified
1796-
const accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTable(resolvedImportedSymbol.exports) : undefined;
1797-
if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
1798-
return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
1804+
// Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
1805+
// but only if the symbolFromSymbolTable can be qualified
1806+
const accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTableWorker(resolvedImportedSymbol.exports, visitedSymbolTables) : undefined;
1807+
if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
1808+
return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
1809+
}
17991810
}
18001811
}
1801-
}
1802-
});
1812+
});
1813+
}
18031814
}
18041815

18051816
if (symbol) {
@@ -4603,12 +4614,22 @@ namespace ts {
46034614

46044615
function getModifiersTypeFromMappedType(type: MappedType) {
46054616
if (!type.modifiersType) {
4606-
// If the mapped type was declared as { [P in keyof T]: X } or as { [P in K]: X }, where
4607-
// K is constrained to 'K extends keyof T', then we will copy property modifiers from T.
4608-
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
4609-
const constraint = getConstraintTypeFromMappedType(declaredType);
4610-
const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
4611-
type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
4617+
const constraintDeclaration = type.declaration.typeParameter.constraint;
4618+
if (constraintDeclaration.kind === SyntaxKind.TypeOperator) {
4619+
// If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check
4620+
// AST nodes here because, when T is a non-generic type, the logic below eagerly resolves
4621+
// 'keyof T' to a literal union type and we can't recover T from that type.
4622+
type.modifiersType = instantiateType(getTypeFromTypeNode((<TypeOperatorNode>constraintDeclaration).type), type.mapper || identityMapper);
4623+
}
4624+
else {
4625+
// Otherwise, get the declared constraint type, and if the constraint type is a type parameter,
4626+
// get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T',
4627+
// the modifiers type is T. Otherwise, the modifiers type is {}.
4628+
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
4629+
const constraint = getConstraintTypeFromMappedType(declaredType);
4630+
const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
4631+
type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
4632+
}
46124633
}
46134634
return type.modifiersType;
46144635
}
@@ -7224,6 +7245,25 @@ namespace ts {
72247245
}
72257246
}
72267247

7248+
function isUnionOrIntersectionTypeWithoutNullableConstituents(type: Type): boolean {
7249+
if (!(type.flags & TypeFlags.UnionOrIntersection)) {
7250+
return false;
7251+
}
7252+
// at this point we know that this is union or intersection type possibly with nullable constituents.
7253+
// check if we still will have compound type if we ignore nullable components.
7254+
let seenNonNullable = false;
7255+
for (const t of (<UnionOrIntersectionType>type).types) {
7256+
if (t.flags & TypeFlags.Nullable) {
7257+
continue;
7258+
}
7259+
if (seenNonNullable) {
7260+
return true;
7261+
}
7262+
seenNonNullable = true;
7263+
}
7264+
return false;
7265+
}
7266+
72277267
/**
72287268
* Compare two types and return
72297269
* * Ternary.True if they are related with no assumptions,
@@ -7258,7 +7298,7 @@ namespace ts {
72587298
// and intersection types are further deconstructed on the target side, we don't want to
72597299
// make the check again (as it might fail for a partial target type). Therefore we obtain
72607300
// the regular source type and proceed with that.
7261-
if (target.flags & TypeFlags.UnionOrIntersection) {
7301+
if (isUnionOrIntersectionTypeWithoutNullableConstituents(target)) {
72627302
source = getRegularTypeOfObjectLiteral(source);
72637303
}
72647304
}
@@ -11334,13 +11374,7 @@ namespace ts {
1133411374
}
1133511375

1133611376
function checkSpreadExpression(node: SpreadElement, contextualMapper?: TypeMapper): Type {
11337-
// It is usually not safe to call checkExpressionCached if we can be contextually typing.
11338-
// You can tell that we are contextually typing because of the contextualMapper parameter.
11339-
// While it is true that a spread element can have a contextual type, it does not do anything
11340-
// with this type. It is neither affected by it, nor does it propagate it to its operand.
11341-
// So the fact that contextualMapper is passed is not important, because the operand of a spread
11342-
// element is not contextually typed.
11343-
const arrayOrIterableType = checkExpressionCached(node.expression, contextualMapper);
11377+
const arrayOrIterableType = checkExpression(node.expression, contextualMapper);
1134411378
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false);
1134511379
}
1134611380

@@ -11630,8 +11664,11 @@ namespace ts {
1163011664
if (propertiesArray.length > 0) {
1163111665
spread = getSpreadType(spread, createObjectLiteralType(), /*isFromObjectLiteral*/ true);
1163211666
}
11633-
spread.flags |= propagatedFlags;
11634-
spread.symbol = node.symbol;
11667+
if (spread.flags & TypeFlags.Object) {
11668+
// only set the symbol and flags if this is a (fresh) object type
11669+
spread.flags |= propagatedFlags;
11670+
spread.symbol = node.symbol;
11671+
}
1163511672
return spread;
1163611673
}
1163711674

@@ -16573,6 +16610,10 @@ namespace ts {
1657316610
}
1657416611
}
1657516612

16613+
function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode {
16614+
return node.dotDotDotToken ? getRestParameterElementType(node.type) : node.type;
16615+
}
16616+
1657616617
/** Check the decorators of a node */
1657716618
function checkDecorators(node: Node): void {
1657816619
if (!node.decorators) {
@@ -16604,7 +16645,7 @@ namespace ts {
1660416645
const constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
1660516646
if (constructor) {
1660616647
for (const parameter of constructor.parameters) {
16607-
markTypeNodeAsReferenced(parameter.type);
16648+
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
1660816649
}
1660916650
}
1661016651
break;
@@ -16613,15 +16654,17 @@ namespace ts {
1661316654
case SyntaxKind.GetAccessor:
1661416655
case SyntaxKind.SetAccessor:
1661516656
for (const parameter of (<FunctionLikeDeclaration>node).parameters) {
16616-
markTypeNodeAsReferenced(parameter.type);
16657+
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
1661716658
}
1661816659

1661916660
markTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
1662016661
break;
1662116662

1662216663
case SyntaxKind.PropertyDeclaration:
16664+
markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(<ParameterDeclaration>node));
16665+
break;
1662316666
case SyntaxKind.Parameter:
16624-
markTypeNodeAsReferenced((<PropertyDeclaration | ParameterDeclaration>node).type);
16667+
markTypeNodeAsReferenced((<PropertyDeclaration>node).type);
1662516668
break;
1662616669
}
1662716670
}
@@ -18092,7 +18135,7 @@ namespace ts {
1809218135

1809318136
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
1809418137
if (baseTypeNode) {
18095-
if (languageVersion < ScriptTarget.ES2015) {
18138+
if (languageVersion < ScriptTarget.ES2015 && !isInAmbientContext(node)) {
1809618139
checkExternalEmitHelpers(baseTypeNode.parent, ExternalEmitHelpers.Extends);
1809718140
}
1809818141

src/compiler/comments.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ namespace ts {
156156

157157
if (!skipTrailingComments) {
158158
emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true);
159+
if (hasWrittenComment && !writer.isAtStartOfLine()) {
160+
writer.writeLine();
161+
}
159162
}
160163

161164
if (extendedDiagnostics) {

src/compiler/parser.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6337,7 +6337,7 @@ namespace ts {
63376337
break;
63386338
case SyntaxKind.AsteriskToken:
63396339
const asterisk = scanner.getTokenText();
6340-
if (state === JSDocState.SawAsterisk) {
6340+
if (state === JSDocState.SawAsterisk || state === JSDocState.SavingComments) {
63416341
// If we've already seen an asterisk, then we can no longer parse a tag on this line
63426342
state = JSDocState.SavingComments;
63436343
pushComment(asterisk);
@@ -6358,14 +6358,19 @@ namespace ts {
63586358
case SyntaxKind.WhitespaceTrivia:
63596359
// only collect whitespace if we're already saving comments or have just crossed the comment indent margin
63606360
const whitespace = scanner.getTokenText();
6361-
if (state === JSDocState.SavingComments || margin !== undefined && indent + whitespace.length > margin) {
6361+
if (state === JSDocState.SavingComments) {
6362+
comments.push(whitespace);
6363+
}
6364+
else if (margin !== undefined && indent + whitespace.length > margin) {
63626365
comments.push(whitespace.slice(margin - indent - 1));
63636366
}
63646367
indent += whitespace.length;
63656368
break;
63666369
case SyntaxKind.EndOfFileToken:
63676370
break;
63686371
default:
6372+
// anything other than whitespace or asterisk at the beginning of the line starts the comment text
6373+
state = JSDocState.SavingComments;
63696374
pushComment(scanner.getTokenText());
63706375
break;
63716376
}

src/compiler/transformers/es2015.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,14 +2286,19 @@ namespace ts {
22862286
}
22872287
}
22882288

2289+
startLexicalEnvironment();
22892290
let loopBody = visitNode(node.statement, visitor, isStatement);
2291+
const lexicalEnvironment = endLexicalEnvironment();
22902292

22912293
const currentState = convertedLoopState;
22922294
convertedLoopState = outerConvertedLoopState;
22932295

2294-
if (loopOutParameters.length) {
2296+
if (loopOutParameters.length || lexicalEnvironment) {
22952297
const statements = isBlock(loopBody) ? (<Block>loopBody).statements.slice() : [loopBody];
2296-
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
2298+
if (loopOutParameters.length) {
2299+
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
2300+
}
2301+
addRange(statements, lexicalEnvironment)
22972302
loopBody = createBlock(statements, /*location*/ undefined, /*multiline*/ true);
22982303
}
22992304

0 commit comments

Comments
 (0)