Skip to content

Commit 50b24ee

Browse files
committed
Merge branch 'master' into stricterGenericChecks
2 parents 3154a6c + 5888804 commit 50b24ee

File tree

248 files changed

+7832
-462
lines changed

Some content is hidden

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

248 files changed

+7832
-462
lines changed

Jakefile.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,8 @@ function runConsoleTests(defaultReporter, runInParallel) {
802802

803803
var debug = process.env.debug || process.env.d;
804804
var inspect = process.env.inspect;
805-
tests = process.env.test || process.env.tests || process.env.t;
805+
var testTimeout = process.env.timeout || defaultTestTimeout;
806+
var tests = process.env.test || process.env.tests || process.env.t;
806807
var light = process.env.light || false;
807808
var stackTraceLimit = process.env.stackTraceLimit;
808809
var testConfigFile = 'test.config';
@@ -820,7 +821,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
820821
} while (fs.existsSync(taskConfigsFolder));
821822
fs.mkdirSync(taskConfigsFolder);
822823

823-
workerCount = process.env.workerCount || os.cpus().length;
824+
workerCount = process.env.workerCount || process.env.p || os.cpus().length;
824825
}
825826

826827
if (tests || light || taskConfigsFolder) {
@@ -925,7 +926,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
925926
}
926927
}
927928

928-
var testTimeout = 20000;
929+
var defaultTestTimeout = 22000;
929930
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
930931
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function () {
931932
runConsoleTests('min', /*runInParallel*/ true);

scripts/tslint/nextLineRule.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class Rule extends Lint.Rules.AbstractRule {
1818

1919
function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boolean): void {
2020
const { sourceFile } = ctx;
21-
function recur(node: ts.Node): void {
21+
ts.forEachChild(sourceFile, function recur(node) {
2222
switch (node.kind) {
2323
case ts.SyntaxKind.IfStatement:
2424
checkIf(node as ts.IfStatement);
@@ -28,7 +28,7 @@ function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boole
2828
break;
2929
}
3030
ts.forEachChild(node, recur);
31-
}
31+
});
3232

3333
function checkIf(node: ts.IfStatement): void {
3434
const { thenStatement, elseStatement } = node;

src/compiler/binder.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2333,7 +2333,7 @@ namespace ts {
23332333
// A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports'
23342334
// is still pointing to 'module.exports'.
23352335
// We do not want to consider this as 'export=' since a module can have only one of these.
2336-
// Similarlly we do not want to treat 'module.exports = exports' as an 'export='.
2336+
// Similarly we do not want to treat 'module.exports = exports' as an 'export='.
23372337
const assignedExpression = getRightMostAssignedExpression(node.right);
23382338
if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) {
23392339
// Mark it as a module in case there are no other exports in the file
@@ -2741,6 +2741,10 @@ namespace ts {
27412741
transformFlags |= TransformFlags.AssertES2015;
27422742
}
27432743

2744+
if (expression.kind === SyntaxKind.ImportKeyword) {
2745+
transformFlags |= TransformFlags.ContainsDynamicImport;
2746+
}
2747+
27442748
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
27452749
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
27462750
}

src/compiler/checker.ts

Lines changed: 147 additions & 28 deletions
Large diffs are not rendered by default.

src/compiler/commandLineParser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,12 @@ namespace ts {
100100
"umd": ModuleKind.UMD,
101101
"es6": ModuleKind.ES2015,
102102
"es2015": ModuleKind.ES2015,
103+
"esnext": ModuleKind.ESNext
103104
}),
104105
paramType: Diagnostics.KIND,
105106
showInSimplifiedHelpView: true,
106107
category: Diagnostics.Basic_Options,
107-
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
108+
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_es2015_or_ESNext,
108109
},
109110
{
110111
name: "lib",

src/compiler/core.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ namespace ts {
473473
* @param array The array to map.
474474
* @param mapfn The callback used to map the result into one or more values.
475475
*/
476-
export function flatMap<T, U>(array: T[], mapfn: (x: T, i: number) => U | U[]): U[] {
476+
export function flatMap<T, U>(array: T[] | undefined, mapfn: (x: T, i: number) => U | U[] | undefined): U[] | undefined {
477477
let result: U[];
478478
if (array) {
479479
result = [];

src/compiler/diagnosticMessages.json

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,23 @@
883883
"category": "Error",
884884
"code": 1322
885885
},
886+
"Dynamic import cannot be used when targeting ECMAScript 2015 modules.": {
887+
"category": "Error",
888+
"code": 1323
889+
},
890+
"Dynamic import must have one specifier as an argument.": {
891+
"category": "Error",
892+
"code": 1324
893+
},
894+
"Specifier of dynamic import cannot be spread element.": {
895+
"category": "Error",
896+
"code": 1325
897+
},
898+
"Dynamic import cannot have type arguments": {
899+
"category": "Error",
900+
"code": 1326
901+
},
902+
886903
"Duplicate identifier '{0}'.": {
887904
"category": "Error",
888905
"code": 2300
@@ -1927,10 +1944,6 @@
19271944
"category": "Error",
19281945
"code": 2649
19291946
},
1930-
"Cannot emit namespaced JSX elements in React.": {
1931-
"category": "Error",
1932-
"code": 2650
1933-
},
19341947
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": {
19351948
"category": "Error",
19361949
"code": 2651
@@ -2163,6 +2176,14 @@
21632176
"category": "Error",
21642177
"code": 2710
21652178
},
2179+
"A dynamic import call returns a 'Promise'. Make sure you have a declaration for 'Promise' or include 'ES2015' in your `--lib` option.": {
2180+
"category": "Error",
2181+
"code": 2711
2182+
},
2183+
"A dynamic import call in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.": {
2184+
"category": "Error",
2185+
"code": 2712
2186+
},
21662187

21672188
"Import declaration '{0}' is using private name '{1}'.": {
21682189
"category": "Error",
@@ -2629,7 +2650,7 @@
26292650
"category": "Message",
26302651
"code": 6015
26312652
},
2632-
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'.": {
2653+
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
26332654
"category": "Message",
26342655
"code": 6016
26352656
},
@@ -3365,6 +3386,11 @@
33653386
"category": "Error",
33663387
"code": 7035
33673388
},
3389+
"Dynamic import's specifier must be of type 'string', but here has type '{0}'.": {
3390+
"category": "Error",
3391+
"code": 7036
3392+
},
3393+
33683394
"You cannot rename this element.": {
33693395
"category": "Error",
33703396
"code": 8000
@@ -3559,11 +3585,11 @@
35593585
"category": "Message",
35603586
"code": 90015
35613587
},
3562-
"Add declaration for missing property '{0}'.": {
3588+
"Declare property '{0}'.": {
35633589
"category": "Message",
35643590
"code": 90016
35653591
},
3566-
"Add index signature for missing property '{0}'.": {
3592+
"Add index signature for property '{0}'.": {
35673593
"category": "Message",
35683594
"code": 90017
35693595
},
@@ -3587,7 +3613,15 @@
35873613
"category": "Message",
35883614
"code": 90022
35893615
},
3590-
3616+
"Declare method '{0}'.": {
3617+
"category": "Message",
3618+
"code": 90023
3619+
},
3620+
"Declare static method '{0}'.": {
3621+
"category": "Message",
3622+
"code": 90024
3623+
},
3624+
35913625
"Convert function to an ES2015 class": {
35923626
"category": "Message",
35933627
"code": 95001

src/compiler/emitter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ namespace ts {
676676
case SyntaxKind.SuperKeyword:
677677
case SyntaxKind.TrueKeyword:
678678
case SyntaxKind.ThisKeyword:
679+
case SyntaxKind.ImportKeyword:
679680
writeTokenNode(node);
680681
return;
681682

src/compiler/factory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,6 +2503,7 @@ namespace ts {
25032503
helpers
25042504
} = sourceEmitNode;
25052505
if (!destEmitNode) destEmitNode = {};
2506+
// We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later.
25062507
if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
25072508
if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
25082509
if (flags) destEmitNode.flags = flags;

src/compiler/parser.ts

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,16 @@ namespace ts {
4646
}
4747
}
4848

49-
// Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
50-
// stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
51-
// embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
52-
// a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
49+
/**
50+
* Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
51+
* stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
52+
* embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
53+
* a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
54+
*
55+
* @param node a given node to visit its children
56+
* @param cbNode a callback to be invoked for all child nodes
57+
* @param cbNodeArray a callback to be invoked for embedded array
58+
*/
5359
export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
5460
if (!node) {
5561
return;
@@ -2409,7 +2415,7 @@ namespace ts {
24092415
if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
24102416
return parseSignatureMember(SyntaxKind.CallSignature);
24112417
}
2412-
if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) {
2418+
if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
24132419
return parseSignatureMember(SyntaxKind.ConstructSignature);
24142420
}
24152421
const fullStart = getNodePos();
@@ -2420,7 +2426,7 @@ namespace ts {
24202426
return parsePropertyOrMethodSignature(fullStart, modifiers);
24212427
}
24222428

2423-
function isStartOfConstructSignature() {
2429+
function nextTokenIsOpenParenOrLessThan() {
24242430
nextToken();
24252431
return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
24262432
}
@@ -2777,6 +2783,8 @@ namespace ts {
27772783
case SyntaxKind.SlashEqualsToken:
27782784
case SyntaxKind.Identifier:
27792785
return true;
2786+
case SyntaxKind.ImportKeyword:
2787+
return lookAhead(nextTokenIsOpenParenOrLessThan);
27802788
default:
27812789
return isIdentifier();
27822790
}
@@ -3509,10 +3517,10 @@ namespace ts {
35093517
* 5) --UnaryExpression[?Yield]
35103518
*/
35113519
if (isUpdateExpression()) {
3512-
const incrementExpression = parseIncrementExpression();
3520+
const updateExpression = parseUpdateExpression();
35133521
return token() === SyntaxKind.AsteriskAsteriskToken ?
3514-
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), incrementExpression) :
3515-
incrementExpression;
3522+
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), updateExpression) :
3523+
updateExpression;
35163524
}
35173525

35183526
/**
@@ -3578,7 +3586,7 @@ namespace ts {
35783586
}
35793587
// falls through
35803588
default:
3581-
return parseIncrementExpression();
3589+
return parseUpdateExpression();
35823590
}
35833591
}
35843592

@@ -3594,7 +3602,7 @@ namespace ts {
35943602
*/
35953603
function isUpdateExpression(): boolean {
35963604
// This function is called inside parseUnaryExpression to decide
3597-
// whether to call parseSimpleUnaryExpression or call parseIncrementExpression directly
3605+
// whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly
35983606
switch (token()) {
35993607
case SyntaxKind.PlusToken:
36003608
case SyntaxKind.MinusToken:
@@ -3618,17 +3626,17 @@ namespace ts {
36183626
}
36193627

36203628
/**
3621-
* Parse ES7 IncrementExpression. IncrementExpression is used instead of ES6's PostFixExpression.
3629+
* Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression.
36223630
*
3623-
* ES7 IncrementExpression[yield]:
3631+
* ES7 UpdateExpression[yield]:
36243632
* 1) LeftHandSideExpression[?yield]
36253633
* 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++
36263634
* 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]--
36273635
* 4) ++LeftHandSideExpression[?yield]
36283636
* 5) --LeftHandSideExpression[?yield]
36293637
* In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression
36303638
*/
3631-
function parseIncrementExpression(): IncrementExpression {
3639+
function parseUpdateExpression(): UpdateExpression {
36323640
if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) {
36333641
const node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
36343642
node.operator = <PrefixUnaryOperator>token();
@@ -3678,25 +3686,35 @@ namespace ts {
36783686
// CallExpression Arguments
36793687
// CallExpression[Expression]
36803688
// CallExpression.IdentifierName
3681-
// super ( ArgumentListopt )
3689+
// import (AssignmentExpression)
3690+
// super Arguments
36823691
// super.IdentifierName
36833692
//
3684-
// Because of the recursion in these calls, we need to bottom out first. There are two
3685-
// bottom out states we can run into. Either we see 'super' which must start either of
3686-
// the last two CallExpression productions. Or we have a MemberExpression which either
3687-
// completes the LeftHandSideExpression, or starts the beginning of the first four
3688-
// CallExpression productions.
3689-
const expression = token() === SyntaxKind.SuperKeyword
3690-
? parseSuperExpression()
3691-
: parseMemberExpressionOrHigher();
3693+
// Because of the recursion in these calls, we need to bottom out first. There are three
3694+
// bottom out states we can run into: 1) We see 'super' which must start either of
3695+
// the last two CallExpression productions. 2) We see 'import' which must start import call.
3696+
// 3)we have a MemberExpression which either completes the LeftHandSideExpression,
3697+
// or starts the beginning of the first four CallExpression productions.
3698+
let expression: MemberExpression;
3699+
if (token() === SyntaxKind.ImportKeyword) {
3700+
// We don't want to eagerly consume all import keyword as import call expression so we look a head to find "("
3701+
// For example:
3702+
// var foo3 = require("subfolder
3703+
// import * as foo1 from "module-from-node -> we want this import to be a statement rather than import call expression
3704+
sourceFile.flags |= NodeFlags.PossiblyContainDynamicImport;
3705+
expression = parseTokenNode<PrimaryExpression>();
3706+
}
3707+
else {
3708+
expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher();
3709+
}
36923710

36933711
// Now, we *may* be complete. However, we might have consumed the start of a
36943712
// CallExpression. As such, we need to consume the rest of it here to be complete.
36953713
return parseCallExpressionRest(expression);
36963714
}
36973715

36983716
function parseMemberExpressionOrHigher(): MemberExpression {
3699-
// Note: to make our lives simpler, we decompose the the NewExpression productions and
3717+
// Note: to make our lives simpler, we decompose the NewExpression productions and
37003718
// place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
37013719
// like so:
37023720
//
@@ -4792,9 +4810,11 @@ namespace ts {
47924810
case SyntaxKind.FinallyKeyword:
47934811
return true;
47944812

4813+
case SyntaxKind.ImportKeyword:
4814+
return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThan);
4815+
47954816
case SyntaxKind.ConstKeyword:
47964817
case SyntaxKind.ExportKeyword:
4797-
case SyntaxKind.ImportKeyword:
47984818
return isStartOfDeclaration();
47994819

48004820
case SyntaxKind.AsyncKeyword:
@@ -6513,6 +6533,10 @@ namespace ts {
65136533
case "augments":
65146534
tag = parseAugmentsTag(atToken, tagName);
65156535
break;
6536+
case "class":
6537+
case "constructor":
6538+
tag = parseClassTag(atToken, tagName);
6539+
break;
65166540
case "arg":
65176541
case "argument":
65186542
case "param":
@@ -6732,6 +6756,13 @@ namespace ts {
67326756
return finishNode(result);
67336757
}
67346758

6759+
function parseClassTag(atToken: AtToken, tagName: Identifier): JSDocClassTag {
6760+
const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, atToken.pos);
6761+
tag.atToken = atToken;
6762+
tag.tagName = tagName;
6763+
return finishNode(tag);
6764+
}
6765+
67356766
function parseTypedefTag(atToken: AtToken, tagName: Identifier): JSDocTypedefTag {
67366767
const typeExpression = tryParseTypeExpression();
67376768
skipWhitespace();

0 commit comments

Comments
 (0)