-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Import assertion #40698
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
Import assertion #40698
Changes from 31 commits
e1b3b78
66d2273
5f3cea6
5a1af04
4b51ca9
375b433
41a881c
46a3eb1
a484ea2
d64f7ba
68c8c5d
29fe0d3
adcfd1b
fb01eb3
4f22a60
f5e594d
60434d1
ff87d3e
43b67b9
c69a05b
d1c48b5
d14f93a
aa8b856
7a5ec34
9cea9cf
6337a7e
eee2cab
2857d69
88e39d5
f941d92
106ff06
7df4964
6ea3c55
fc51c42
bf7ca71
463138a
b07c6e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6503,7 +6503,7 @@ namespace ts { | |
|
||
function inlineExportModifiers(statements: Statement[]) { | ||
// Pass 3: Move all `export {}`'s to `export` modifiers where possible | ||
const index = findIndex(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !!d.exportClause && isNamedExports(d.exportClause)); | ||
const index = findIndex(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !d.assertClause && !!d.exportClause && isNamedExports(d.exportClause)); | ||
if (index >= 0) { | ||
const exportDecl = statements[index] as ExportDeclaration & { readonly exportClause: NamedExports }; | ||
const replacements = mapDefined(exportDecl.exportClause.elements, e => { | ||
|
@@ -6535,7 +6535,8 @@ namespace ts { | |
exportDecl.exportClause, | ||
replacements | ||
), | ||
exportDecl.moduleSpecifier | ||
exportDecl.moduleSpecifier, | ||
exportDecl.assertClause | ||
); | ||
} | ||
} | ||
|
@@ -7195,7 +7196,8 @@ namespace ts { | |
propertyName && isIdentifier(propertyName) ? factory.createIdentifier(idText(propertyName)) : undefined, | ||
factory.createIdentifier(localName) | ||
)])), | ||
factory.createStringLiteral(specifier) | ||
factory.createStringLiteral(specifier), | ||
/*importClause*/ undefined | ||
), ModifierFlags.None); | ||
break; | ||
} | ||
|
@@ -7271,15 +7273,17 @@ namespace ts { | |
// We use `target.parent || target` below as `target.parent` is unset when the target is a module which has been export assigned | ||
// And then made into a default by the `esModuleInterop` or `allowSyntheticDefaultImports` flag | ||
// In such cases, the `target` refers to the module itself already | ||
factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)) | ||
factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)), | ||
/*assertClause*/ undefined | ||
), ModifierFlags.None); | ||
break; | ||
case SyntaxKind.NamespaceImport: | ||
addResult(factory.createImportDeclaration( | ||
/*decorators*/ undefined, | ||
/*modifiers*/ undefined, | ||
factory.createImportClause(/*isTypeOnly*/ false, /*importClause*/ undefined, factory.createNamespaceImport(factory.createIdentifier(localName))), | ||
factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)) | ||
factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)), | ||
/*assertClause*/ undefined | ||
), ModifierFlags.None); | ||
break; | ||
case SyntaxKind.NamespaceExport: | ||
|
@@ -7304,7 +7308,8 @@ namespace ts { | |
factory.createIdentifier(localName) | ||
) | ||
])), | ||
factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)) | ||
factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)), | ||
/*assertClause*/ undefined | ||
), ModifierFlags.None); | ||
break; | ||
case SyntaxKind.ExportSpecifier: | ||
|
@@ -38628,6 +38633,18 @@ namespace ts { | |
} | ||
} | ||
|
||
function checkAssertClause(declaration: ImportDeclaration | ExportDeclaration) { | ||
if (declaration.assertClause) { | ||
if (moduleKind !== ModuleKind.ESNext) { | ||
error(declaration.assertClause, Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext); | ||
} | ||
|
||
if (isImportDeclaration(declaration) ? declaration.importClause?.isTypeOnly : declaration.isTypeOnly) { | ||
error(declaration.assertClause, Diagnostics.Import_assertions_cannot_be_used_with_type_only_imports_or_exports); | ||
Kingwl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} | ||
|
||
function checkImportDeclaration(node: ImportDeclaration) { | ||
if (checkGrammarModuleElementContext(node, Diagnostics.An_import_declaration_can_only_be_used_in_a_namespace_or_module)) { | ||
// If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. | ||
|
@@ -38659,7 +38676,7 @@ namespace ts { | |
} | ||
} | ||
} | ||
|
||
checkAssertClause(node); | ||
} | ||
|
||
function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) { | ||
|
@@ -38754,6 +38771,7 @@ namespace ts { | |
} | ||
} | ||
} | ||
checkAssertClause(node); | ||
} | ||
|
||
function checkGrammarExportDeclaration(node: ExportDeclaration): boolean { | ||
|
@@ -42772,6 +42790,22 @@ namespace ts { | |
return false; | ||
} | ||
|
||
function checkGrammarImportCallArguments(node: ImportCall, nodeArguments: NodeArray<Expression>): boolean { | ||
Kingwl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (moduleKind !== ModuleKind.ESNext) { | ||
// We are allowed trailing comma after proposal-import-assertions. | ||
checkGrammarForDisallowedTrailingComma(nodeArguments); | ||
|
||
if (nodeArguments.length > 1) { | ||
const assertionArgument = nodeArguments[1]; | ||
return grammarErrorOnNode(assertionArgument, Diagnostics.Dynamic_import_only_supports_a_second_argument_when_the_module_option_is_set_to_esnext); | ||
} | ||
} | ||
if (nodeArguments.length !== 1) { | ||
Kingwl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_only_have_a_specifier_and_an_optional_assertion_as_arguments); | ||
} | ||
return false; | ||
} | ||
|
||
function checkGrammarImportCallExpression(node: ImportCall): boolean { | ||
if (moduleKind === ModuleKind.ES2015) { | ||
return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_esnext_commonjs_amd_system_or_umd); | ||
|
@@ -42782,13 +42816,12 @@ namespace ts { | |
} | ||
|
||
const nodeArguments = node.arguments; | ||
if (nodeArguments.length !== 1) { | ||
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument); | ||
if (checkGrammarImportCallArguments(node, nodeArguments)) { | ||
return true; | ||
} | ||
checkGrammarForDisallowedTrailingComma(nodeArguments); | ||
// 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(nodeArguments[0])) { | ||
if (nodeArguments.length && isSpreadElement(nodeArguments[0])) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to check that all elements of the No coercion to string is performed here, the algorithm explicitly checks for strings. We might want to consider something like the // es5.d.ts
interface ImportCallOptions {
assert?: ImportAssertions;
}
interface ImportAssertions {
type?: string;
[key: string]: string | undefined; // not ideal, but necessary so that `type` is optional.
} Then we can check against the global We could consider this as a follow-on PR if necessary, but it would be nice to have. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NOTE: if we wanted to be more specific with interface ImportAssertions {
type?: ImportTypeAssertion;
[key: string]: string | undefined;
}
// see ArrayBufferTypes for reference
interface ImportTypeAssertionTypes {
json: "json";
}
type ImportTypeAssertion = Extract<ImportTypeAssertions[keyof ImportTypeAssertions], string>; That way, we have better completions for interface ImportTypeAssertionTypes {
css: "css";
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We also need to ensure that I would suggest this approach: const spreadElement = forEach(nodeArguments, isSpreadElement);
if (spreadElement) {
return grammarErrorOnNode(spreadElement, Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element);
} That way it checks all arguments, but only reports on the first error (which is almost always the case for grammar errors). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we check the assert clause too?Or just the second parameter of dynamic import. |
||
return grammarErrorOnNode(nodeArguments[0], Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element); | ||
} | ||
return false; | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -948,7 +948,7 @@ | |||||
"category": "Error", | ||||||
"code": 1323 | ||||||
}, | ||||||
"Dynamic import must have one specifier as an argument.": { | ||||||
"Dynamic import only supports a second argument when the '--module' option is set to 'esnext'.": { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
"category": "Error", | ||||||
"code": 1324 | ||||||
}, | ||||||
|
@@ -1408,6 +1408,10 @@ | |||||
"category": "Error", | ||||||
"code": 1443 | ||||||
}, | ||||||
"Dynamic import must only have a specifier and an optional assertion as arguments": { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree, but I think |
||||||
"category": "Message", | ||||||
"code": 1444 | ||||||
}, | ||||||
|
||||||
"The types of '{0}' are incompatible between these types.": { | ||||||
"category": "Error", | ||||||
|
@@ -3412,6 +3416,14 @@ | |||||
"category": "Error", | ||||||
"code": 2819 | ||||||
}, | ||||||
"Import assertions are only supported when the '--module' option is set to 'esnext'.": { | ||||||
"category": "Error", | ||||||
"code": 2820 | ||||||
}, | ||||||
"Import assertions cannot be used with type-only imports or exports.": { | ||||||
"category": "Error", | ||||||
"code": 2821 | ||||||
}, | ||||||
|
||||||
"Import declaration '{0}' is using private name '{1}'.": { | ||||||
"category": "Error", | ||||||
|
Uh oh!
There was an error while loading. Please reload this page.