Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a6e1ced

Browse filesBrowse files
authored
Merge pull request microsoft#16281 from Microsoft/master-MergeDynamicImport
[Master] Remerge this back to master after fixing test failure
2 parents cbdf02f + fe4fec5 commit a6e1ced
Copy full SHA for a6e1ced

169 files changed

+5,274-103Lines changed: 5274 additions & 103 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/binder.ts‎

Copy file name to clipboardExpand all lines: src/compiler/binder.ts
+5-1Lines 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
}
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+67-3Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8366,6 +8366,12 @@ namespace ts {
83668366
/**
83678367
* This is *not* a bi-directional relationship.
83688368
* If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'.
8369+
*
8370+
* A type S is comparable to a type T if some (but not necessarily all) of the possible values of S are also possible values of T.
8371+
* It is used to check following cases:
8372+
* - the types of the left and right sides of equality/inequality operators (`===`, `!==`, `==`, `!=`).
8373+
* - the types of `case` clause expressions and their respective `switch` expressions.
8374+
* - the type of an expression in a type assertion with the type being asserted.
83698375
*/
83708376
function isTypeComparableTo(source: Type, target: Type): boolean {
83718377
return isTypeRelatedTo(source, target, comparableRelation);
@@ -16173,6 +16179,35 @@ namespace ts {
1617316179
return getReturnTypeOfSignature(signature);
1617416180
}
1617516181

16182+
function checkImportCallExpression(node: ImportCall): Type {
16183+
// Check grammar of dynamic import
16184+
checkGrammarArguments(node, node.arguments) || checkGrammarImportCallExpression(node);
16185+
16186+
if (node.arguments.length === 0) {
16187+
return createPromiseReturnType(node, anyType);
16188+
}
16189+
const specifier = node.arguments[0];
16190+
const specifierType = checkExpressionCached(specifier);
16191+
// Even though multiple arugments is grammatically incorrect, type-check extra arguments for completion
16192+
for (let i = 1; i < node.arguments.length; ++i) {
16193+
checkExpressionCached(node.arguments[i]);
16194+
}
16195+
16196+
if (specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) {
16197+
error(specifier, Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType));
16198+
}
16199+
16200+
// resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal
16201+
const moduleSymbol = resolveExternalModuleName(node, specifier);
16202+
if (moduleSymbol) {
16203+
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
16204+
if (esModuleSymbol) {
16205+
return createPromiseReturnType(node, getTypeOfSymbol(esModuleSymbol));
16206+
}
16207+
}
16208+
return createPromiseReturnType(node, anyType);
16209+
}
16210+
1617616211
function isCommonJsRequire(node: Node) {
1617716212
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
1617816213
return false;
@@ -16379,14 +16414,18 @@ namespace ts {
1637916414
return emptyObjectType;
1638016415
}
1638116416

16382-
function createPromiseReturnType(func: FunctionLikeDeclaration, promisedType: Type) {
16417+
function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) {
1638316418
const promiseType = createPromiseType(promisedType);
1638416419
if (promiseType === emptyObjectType) {
16385-
error(func, Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
16420+
error(func, isImportCall(func) ?
16421+
Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option :
16422+
Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
1638616423
return unknownType;
1638716424
}
1638816425
else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) {
16389-
error(func, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
16426+
error(func, isImportCall(func) ?
16427+
Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option :
16428+
Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
1639016429
}
1639116430

1639216431
return promiseType;
@@ -17745,6 +17784,10 @@ namespace ts {
1774517784
case SyntaxKind.ElementAccessExpression:
1774617785
return checkIndexedAccess(<ElementAccessExpression>node);
1774717786
case SyntaxKind.CallExpression:
17787+
if ((<CallExpression>node).expression.kind === SyntaxKind.ImportKeyword) {
17788+
return checkImportCallExpression(<ImportCall>node);
17789+
}
17790+
/* falls through */
1774817791
case SyntaxKind.NewExpression:
1774917792
return checkCallExpression(<CallExpression>node);
1775017793
case SyntaxKind.TaggedTemplateExpression:
@@ -24670,6 +24713,27 @@ namespace ts {
2467024713
});
2467124714
return result;
2467224715
}
24716+
24717+
function checkGrammarImportCallExpression(node: ImportCall): boolean {
24718+
if (modulekind === ModuleKind.ES2015) {
24719+
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules);
24720+
}
24721+
24722+
if (node.typeArguments) {
24723+
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_have_type_arguments);
24724+
}
24725+
24726+
const arguments = node.arguments;
24727+
if (arguments.length !== 1) {
24728+
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument);
24729+
}
24730+
24731+
// see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import.
24732+
// parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import.
24733+
if (isSpreadElement(arguments[0])) {
24734+
return grammarErrorOnNode(arguments[0], Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element);
24735+
}
24736+
}
2467324737
}
2467424738

2467524739
/** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */
Collapse file

‎src/compiler/commandLineParser.ts‎

Copy file name to clipboardExpand all lines: src/compiler/commandLineParser.ts
+2-1Lines 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",
Collapse file

‎src/compiler/diagnosticMessages.json‎

Copy file name to clipboardExpand all lines: src/compiler/diagnosticMessages.json
+31-5Lines changed: 31 additions & 5 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
Collapse file

‎src/compiler/emitter.ts‎

Copy file name to clipboardExpand all lines: src/compiler/emitter.ts
+1Lines 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

Collapse file

‎src/compiler/parser.ts‎

Copy file name to clipboardExpand all lines: src/compiler/parser.ts
+45-25Lines changed: 45 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:

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.