Skip to content

Revert "[Master] wip-dynamic import" #16264

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2333,7 +2333,7 @@ namespace ts {
// A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports'
// is still pointing to 'module.exports'.
// We do not want to consider this as 'export=' since a module can have only one of these.
// Similarly we do not want to treat 'module.exports = exports' as an 'export='.
// Similarlly we do not want to treat 'module.exports = exports' as an 'export='.
const assignedExpression = getRightMostAssignedExpression(node.right);
if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) {
// Mark it as a module in case there are no other exports in the file
Expand Down Expand Up @@ -2741,10 +2741,6 @@ namespace ts {
transformFlags |= TransformFlags.AssertES2015;
}

if (expression.kind === SyntaxKind.ImportKeyword) {
transformFlags |= TransformFlags.ContainsDynamicImport;
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
}
Expand Down
70 changes: 3 additions & 67 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8356,12 +8356,6 @@ namespace ts {
/**
* This is *not* a bi-directional relationship.
* If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'.
*
* 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.
* It is used to check following cases:
* - the types of the left and right sides of equality/inequality operators (`===`, `!==`, `==`, `!=`).
* - the types of `case` clause expressions and their respective `switch` expressions.
* - the type of an expression in a type assertion with the type being asserted.
*/
function isTypeComparableTo(source: Type, target: Type): boolean {
return isTypeRelatedTo(source, target, comparableRelation);
Expand Down Expand Up @@ -16164,35 +16158,6 @@ namespace ts {
return getReturnTypeOfSignature(signature);
}

function checkImportCallExpression(node: ImportCall): Type {
// Check grammar of dynamic import
checkGrammarArguments(node, node.arguments) || checkGrammarImportCallExpression(node);

if (node.arguments.length === 0) {
return createPromiseReturnType(node, anyType);
}
const specifier = node.arguments[0];
const specifierType = checkExpressionCached(specifier);
// Even though multiple arugments is grammatically incorrect, type-check extra arguments for completion
for (let i = 1; i < node.arguments.length; ++i) {
checkExpressionCached(node.arguments[i]);
}

if (specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) {
error(specifier, Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType));
}

// resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal
const moduleSymbol = resolveExternalModuleName(node, specifier);
if (moduleSymbol) {
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
if (esModuleSymbol) {
return createPromiseReturnType(node, getTypeOfSymbol(esModuleSymbol));
}
}
return createPromiseReturnType(node, anyType);
}

function isCommonJsRequire(node: Node) {
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
return false;
Expand Down Expand Up @@ -16399,18 +16364,14 @@ namespace ts {
return emptyObjectType;
}

function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) {
function createPromiseReturnType(func: FunctionLikeDeclaration, promisedType: Type) {
const promiseType = createPromiseType(promisedType);
if (promiseType === emptyObjectType) {
error(func, isImportCall(func) ?
Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option :
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);
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);
return unknownType;
}
else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) {
error(func, isImportCall(func) ?
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 :
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);
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);
}

return promiseType;
Expand Down Expand Up @@ -17769,10 +17730,6 @@ namespace ts {
case SyntaxKind.ElementAccessExpression:
return checkIndexedAccess(<ElementAccessExpression>node);
case SyntaxKind.CallExpression:
if ((<CallExpression>node).expression.kind === SyntaxKind.ImportKeyword) {
return checkImportCallExpression(<ImportCall>node);
}
/* falls through */
case SyntaxKind.NewExpression:
return checkCallExpression(<CallExpression>node);
case SyntaxKind.TaggedTemplateExpression:
Expand Down Expand Up @@ -24698,27 +24655,6 @@ namespace ts {
});
return result;
}

function checkGrammarImportCallExpression(node: ImportCall): boolean {
if (modulekind === ModuleKind.ES2015) {
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules);
}

if (node.typeArguments) {
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_have_type_arguments);
}

const arguments = node.arguments;
if (arguments.length !== 1) {
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument);
}

// see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import.
// parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import.
if (isSpreadElement(arguments[0])) {
return grammarErrorOnNode(arguments[0], Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element);
}
}
}

/** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */
Expand Down
3 changes: 1 addition & 2 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,11 @@ namespace ts {
"umd": ModuleKind.UMD,
"es6": ModuleKind.ES2015,
"es2015": ModuleKind.ES2015,
"esnext": ModuleKind.ESNext
}),
paramType: Diagnostics.KIND,
showInSimplifiedHelpView: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_es2015_or_ESNext,
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
},
{
name: "lib",
Expand Down
36 changes: 5 additions & 31 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -883,23 +883,6 @@
"category": "Error",
"code": 1322
},
"Dynamic import cannot be used when targeting ECMAScript 2015 modules.": {
"category": "Error",
"code": 1323
},
"Dynamic import must have one specifier as an argument.": {
"category": "Error",
"code": 1324
},
"Specifier of dynamic import cannot be spread element.": {
"category": "Error",
"code": 1325
},
"Dynamic import cannot have type arguments": {
"category": "Error",
"code": 1326
},

"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2300
Expand Down Expand Up @@ -1944,6 +1927,10 @@
"category": "Error",
"code": 2649
},
"Cannot emit namespaced JSX elements in React.": {
"category": "Error",
"code": 2650
},
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": {
"category": "Error",
"code": 2651
Expand Down Expand Up @@ -2176,14 +2163,6 @@
"category": "Error",
"code": 2710
},
"A dynamic import call returns a 'Promise'. Make sure you have a declaration for 'Promise' or include 'ES2015' in your `--lib` option.": {
"category": "Error",
"code": 2711
},
"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.": {
"category": "Error",
"code": 2712
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down Expand Up @@ -2650,7 +2629,7 @@
"category": "Message",
"code": 6015
},
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'.": {
"category": "Message",
"code": 6016
},
Expand Down Expand Up @@ -3386,11 +3365,6 @@
"category": "Error",
"code": 7035
},
"Dynamic import's specifier must be of type 'string', but here has type '{0}'.": {
"category": "Error",
"code": 7036
},

"You cannot rename this element.": {
"category": "Error",
"code": 8000
Expand Down
1 change: 0 additions & 1 deletion src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,6 @@ namespace ts {
case SyntaxKind.SuperKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.ThisKeyword:
case SyntaxKind.ImportKeyword:
writeTokenNode(node);
return;

Expand Down
67 changes: 25 additions & 42 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,10 @@ namespace ts {
}
}

/**
* Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
* stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
* embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
* a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
*
* @param node a given node to visit its children
* @param cbNode a callback to be invoked for all child nodes
* @param cbNodeArray a callback to be invoked for embedded array
*/
// Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
// stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
// embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
// a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
if (!node) {
return;
Expand Down Expand Up @@ -2415,7 +2409,7 @@ namespace ts {
if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
return parseSignatureMember(SyntaxKind.CallSignature);
}
if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) {
return parseSignatureMember(SyntaxKind.ConstructSignature);
}
const fullStart = getNodePos();
Expand All @@ -2426,7 +2420,7 @@ namespace ts {
return parsePropertyOrMethodSignature(fullStart, modifiers);
}

function nextTokenIsOpenParenOrLessThan() {
function isStartOfConstructSignature() {
nextToken();
return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
}
Expand Down Expand Up @@ -2782,7 +2776,6 @@ namespace ts {
case SyntaxKind.SlashToken:
case SyntaxKind.SlashEqualsToken:
case SyntaxKind.Identifier:
case SyntaxKind.ImportKeyword:
return true;
default:
return isIdentifier();
Expand Down Expand Up @@ -3516,10 +3509,10 @@ namespace ts {
* 5) --UnaryExpression[?Yield]
*/
if (isUpdateExpression()) {
const updateExpression = parseUpdateExpression();
const incrementExpression = parseIncrementExpression();
return token() === SyntaxKind.AsteriskAsteriskToken ?
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), updateExpression) :
updateExpression;
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), incrementExpression) :
incrementExpression;
}

/**
Expand Down Expand Up @@ -3585,7 +3578,7 @@ namespace ts {
}
// falls through
default:
return parseUpdateExpression();
return parseIncrementExpression();
}
}

Expand All @@ -3601,7 +3594,7 @@ namespace ts {
*/
function isUpdateExpression(): boolean {
// This function is called inside parseUnaryExpression to decide
// whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly
// whether to call parseSimpleUnaryExpression or call parseIncrementExpression directly
switch (token()) {
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
Expand All @@ -3625,17 +3618,17 @@ namespace ts {
}

/**
* Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression.
* Parse ES7 IncrementExpression. IncrementExpression is used instead of ES6's PostFixExpression.
*
* ES7 UpdateExpression[yield]:
* ES7 IncrementExpression[yield]:
* 1) LeftHandSideExpression[?yield]
* 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++
* 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]--
* 4) ++LeftHandSideExpression[?yield]
* 5) --LeftHandSideExpression[?yield]
* In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression
*/
function parseUpdateExpression(): UpdateExpression {
function parseIncrementExpression(): IncrementExpression {
if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) {
const node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
node.operator = <PrefixUnaryOperator>token();
Expand Down Expand Up @@ -3685,35 +3678,25 @@ namespace ts {
// CallExpression Arguments
// CallExpression[Expression]
// CallExpression.IdentifierName
// import (AssignmentExpression)
// super Arguments
// super ( ArgumentListopt )
// super.IdentifierName
//
// Because of the recursion in these calls, we need to bottom out first. There are three
// bottom out states we can run into: 1) We see 'super' which must start either of
// the last two CallExpression productions. 2) We see 'import' which must start import call.
// 3)we have a MemberExpression which either completes the LeftHandSideExpression,
// or starts the beginning of the first four CallExpression productions.
let expression: MemberExpression;
if (token() === SyntaxKind.ImportKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
// We don't want to eagerly consume all import keyword as import call expression so we look a head to find "("
// For example:
// var foo3 = require("subfolder
// import * as foo1 from "module-from-node -> we want this import to be a statement rather than import call expression
sourceFile.flags |= NodeFlags.PossiblyContainDynamicImport;
expression = parseTokenNode<PrimaryExpression>();
}
else {
expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher();
}
// Because of the recursion in these calls, we need to bottom out first. There are two
// bottom out states we can run into. Either we see 'super' which must start either of
// the last two CallExpression productions. Or we have a MemberExpression which either
// completes the LeftHandSideExpression, or starts the beginning of the first four
// CallExpression productions.
const expression = token() === SyntaxKind.SuperKeyword
? parseSuperExpression()
: parseMemberExpressionOrHigher();

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

function parseMemberExpressionOrHigher(): MemberExpression {
// Note: to make our lives simpler, we decompose the NewExpression productions and
// Note: to make our lives simpler, we decompose the the NewExpression productions and
// place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
// like so:
//
Expand Down Expand Up @@ -4807,11 +4790,11 @@ namespace ts {
// however, we say they are here so that we may gracefully parse them and error later.
case SyntaxKind.CatchKeyword:
case SyntaxKind.FinallyKeyword:
case SyntaxKind.ImportKeyword:
return true;

case SyntaxKind.ConstKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.ImportKeyword:
return isStartOfDeclaration();

case SyntaxKind.AsyncKeyword:
Expand Down
Loading