Skip to content
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

Add --module node20 with require(esm) support #60761

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
22 changes: 14 additions & 8 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4714,7 +4714,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (errorNode && resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) {
errorOnImplicitAnyModule(/*isError*/ false, errorNode, currentSourceFile, mode, resolvedModule, moduleReference);
}
if (errorNode && (moduleResolutionKind === ModuleResolutionKind.Node16 || moduleResolutionKind === ModuleResolutionKind.NodeNext)) {
if (errorNode && (moduleKind === ModuleKind.Node16 || moduleKind === ModuleKind.Node18)) {
const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) || !!findAncestor(location, isImportEqualsDeclaration);
const overrideHost = findAncestor(location, l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l) || isJSDocImportTag(l));
// An override clause will take effect for type-only imports and import types, and allows importing the types across formats, regardless of
Expand Down Expand Up @@ -39215,6 +39215,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
switch (moduleKind) {
case ModuleKind.Node16:
case ModuleKind.Node18:
case ModuleKind.Node20:
case ModuleKind.NodeNext:
if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) {
span ??= getSpanOfTokenAtPosition(sourceFile, node.pos);
Expand All @@ -39235,8 +39236,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// fallthrough
default:
span ??= getSpanOfTokenAtPosition(sourceFile, node.pos);
const message = isAwaitExpression(node) ? Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher :
Diagnostics.Top_level_await_using_statements_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher;
const message = isAwaitExpression(node) ? Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_node20_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher :
Diagnostics.Top_level_await_using_statements_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_node20_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher;
diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, message));
hasError = true;
break;
Expand Down Expand Up @@ -48071,11 +48072,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return grammarErrorOnNode(
node,
isImportAttributes
? Diagnostics.Import_attributes_are_only_supported_when_the_module_option_is_set_to_esnext_node18_nodenext_or_preserve
: Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_node18_nodenext_or_preserve,
? Diagnostics.Import_attributes_are_only_supported_when_the_module_option_is_set_to_esnext_node18_node20_nodenext_or_preserve
: Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_node18_node20_nodenext_or_preserve,
);
}

if (moduleKind === ModuleKind.NodeNext && !isImportAttributes) {
return grammarErrorOnFirstToken(node, Diagnostics.Import_assertions_have_been_replaced_by_import_attributes_Use_with_instead_of_asserts);
}

if (declaration.moduleSpecifier && getEmitSyntaxForModuleSpecifierExpression(declaration.moduleSpecifier) === ModuleKind.CommonJS) {
return grammarErrorOnNode(
node,
Expand Down Expand Up @@ -52072,6 +52077,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
switch (moduleKind) {
case ModuleKind.Node16:
case ModuleKind.Node18:
case ModuleKind.Node20:
case ModuleKind.NodeNext:
if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) {
diagnostics.add(
Expand All @@ -52090,7 +52096,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// fallthrough
default:
diagnostics.add(
createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher),
createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_node20_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher),
);
break;
}
Expand Down Expand Up @@ -52892,7 +52898,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

if (moduleKind === ModuleKind.ES2015) {
return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_node18_or_nodenext);
return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_node18_node20_or_nodenext);
}

if (node.typeArguments) {
Expand All @@ -52906,7 +52912,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {

if (nodeArguments.length > 1) {
const importAttributesArgument = nodeArguments[1];
return grammarErrorOnNode(importAttributesArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_node18_nodenext_or_preserve);
return grammarErrorOnNode(importAttributesArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_node18_node20_nodenext_or_preserve);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ export const moduleOptionDeclaration: CommandLineOptionOfCustomType = {
esnext: ModuleKind.ESNext,
node16: ModuleKind.Node16,
node18: ModuleKind.Node18,
node20: ModuleKind.Node20,
nodenext: ModuleKind.NodeNext,
preserve: ModuleKind.Preserve,
})),
Expand Down
18 changes: 11 additions & 7 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1028,11 +1028,11 @@
"category": "Error",
"code": 1322
},
"Dynamic imports are only supported when the '--module' flag is set to 'es2020', 'es2022', 'esnext', 'commonjs', 'amd', 'system', 'umd', 'node16', 'node18', or 'nodenext'.": {
"Dynamic imports are only supported when the '--module' flag is set to 'es2020', 'es2022', 'esnext', 'commonjs', 'amd', 'system', 'umd', 'node16', 'node18', 'node20', or 'nodenext'.": {
"category": "Error",
"code": 1323
},
"Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', 'node18', 'nodenext', or 'preserve'.": {
"Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', 'node18', 'node20', 'nodenext', or 'preserve'.": {
"category": "Error",
"code": 1324
},
Expand Down Expand Up @@ -1220,7 +1220,7 @@
"category": "Message",
"code": 1377
},
"Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.": {
"Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.": {
"category": "Error",
"code": 1378
},
Expand Down Expand Up @@ -1424,7 +1424,7 @@
"category": "Error",
"code": 1431
},
"Top-level 'for await' loops are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.": {
"Top-level 'for await' loops are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.": {
"category": "Error",
"code": 1432
},
Expand Down Expand Up @@ -3788,15 +3788,15 @@
"category": "Error",
"code": 2820
},
"Import assertions are only supported when the '--module' option is set to 'esnext', 'node18', 'nodenext', or 'preserve'.": {
"Import assertions are only supported when the '--module' option is set to 'esnext', 'node18', 'node20', 'nodenext', or 'preserve'.": {
"category": "Error",
"code": 2821
},
"Import assertions cannot be used with type-only imports or exports.": {
"category": "Error",
"code": 2822
},
"Import attributes are only supported when the '--module' option is set to 'esnext', 'node18', 'nodenext', or 'preserve'.": {
"Import attributes are only supported when the '--module' option is set to 'esnext', 'node18', 'node20', 'nodenext', or 'preserve'.": {
"category": "Error",
"code": 2823
},
Expand Down Expand Up @@ -3876,7 +3876,7 @@
"category": "Error",
"code": 2853
},
"Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.": {
"Top-level 'await using' statements are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', 'nodenext', or 'preserve', and the 'target' option is set to 'es2017' or higher.": {
"category": "Error",
"code": 2854
},
Expand Down Expand Up @@ -3980,6 +3980,10 @@
"category": "Error",
"code": 2879
},
"Import assertions have been replaced by import attributes. Use 'with' instead of 'asserts'.": {
"category": "Error",
"code": 2880
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
1 change: 1 addition & 0 deletions src/compiler/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<Source
case ModuleKind.ES2015:
case ModuleKind.Node16:
case ModuleKind.Node18:
case ModuleKind.Node20:
case ModuleKind.NodeNext:
case ModuleKind.CommonJS:
// Wraps `transformModule` and `transformECMAScriptModule` and
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7546,6 +7546,7 @@ export enum ModuleKind {
// Node16+ is an amalgam of commonjs (albeit updated) and es2022+, and represents a distinct module system from es2020/esnext
Node16 = 100,
Node18 = 101,
Node20 = 102,
NodeNext = 199,

// Emit as written
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8941,6 +8941,7 @@ const _computedOptions = createComputedCompilerOptions({
return target ??
((compilerOptions.module === ModuleKind.Node16 && ScriptTarget.ES2022) ||
(compilerOptions.module === ModuleKind.Node18 && ScriptTarget.ES2022) ||
(compilerOptions.module === ModuleKind.Node20 && ScriptTarget.ES2023) ||
(compilerOptions.module === ModuleKind.NodeNext && ScriptTarget.ESNext) ||
ScriptTarget.ES5);
},
Expand All @@ -8964,6 +8965,7 @@ const _computedOptions = createComputedCompilerOptions({
break;
case ModuleKind.Node16:
case ModuleKind.Node18:
case ModuleKind.Node20:
moduleResolution = ModuleResolutionKind.Node16;
break;
case ModuleKind.NodeNext:
Expand Down Expand Up @@ -9007,6 +9009,7 @@ const _computedOptions = createComputedCompilerOptions({
switch (_computedOptions.module.computeValue(compilerOptions)) {
case ModuleKind.Node16:
case ModuleKind.Node18:
case ModuleKind.Node20:
case ModuleKind.NodeNext:
case ModuleKind.Preserve:
return true;
Expand Down
1 change: 1 addition & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3255,6 +3255,7 @@ export const enum ModuleKind {
ESNext = "esnext",
Node16 = "node16",
Node18 = "node18",
Node20 = "node20",
NodeNext = "nodenext",
Preserve = "preserve",
}
Expand Down
6 changes: 3 additions & 3 deletions src/services/codefixes/fixModuleAndTargetOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import {

registerCodeFix({
errorCodes: [
Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher.code,
Diagnostics.Top_level_await_using_statements_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher.code,
Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher.code,
Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_node20_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher.code,
Diagnostics.Top_level_await_using_statements_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_node20_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher.code,
Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_node18_node20_nodenext_or_preserve_and_the_target_option_is_set_to_es2017_or_higher.code,
],
getCodeActions: function getCodeActionsToFixModuleAndTarget(context) {
const compilerOptions = context.program.getCompilerOptions();
Expand Down
1 change: 1 addition & 0 deletions src/services/codefixes/importFixes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,7 @@ function getUmdImportKind(importingFile: SourceFile | FutureSourceFile, program:
return ImportKind.Namespace;
case ModuleKind.Node16:
case ModuleKind.Node18:
case ModuleKind.Node20:
case ModuleKind.NodeNext:
return getImpliedNodeFormatForEmit(importingFile, program) === ModuleKind.ESNext ? ImportKind.Namespace : ImportKind.CommonJS;
default:
Expand Down
2 changes: 2 additions & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2517,6 +2517,7 @@ declare namespace ts {
ESNext = "esnext",
Node16 = "node16",
Node18 = "node18",
Node20 = "node20",
NodeNext = "nodenext",
Preserve = "preserve",
}
Expand Down Expand Up @@ -7133,6 +7134,7 @@ declare namespace ts {
ESNext = 99,
Node16 = 100,
Node18 = 101,
Node20 = 102,
NodeNext = 199,
Preserve = 200,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
arbitraryModuleNamespaceIdentifiers_module.ts(20,7): error TS2322: Type '"expect error about someType"' is not assignable to type '"someType"'.
arbitraryModuleNamespaceIdentifiers_module.ts(24,7): error TS2322: Type '"expect error about someType"' is not assignable to type '"someType"'.
arbitraryModuleNamespaceIdentifiers_module.ts(29,7): error TS2322: Type '"expect error about otherType"' is not assignable to type '"otherType"'.


==== arbitraryModuleNamespaceIdentifiers_module.ts (3 errors) ====
const someValue = "someValue";
type someType = "someType";

export { someValue as "<X>" };
import { "<X>" as valueX } from "./arbitraryModuleNamespaceIdentifiers_module";
if (valueX !== "someValue") throw "should be someValue";

export { "<X>" as "<Y>" } from "./arbitraryModuleNamespaceIdentifiers_module";
import { "<Y>" as valueY } from "./arbitraryModuleNamespaceIdentifiers_module";
if (valueY !== "someValue") throw "should be someValue";

export * as "<Z>" from "./arbitraryModuleNamespaceIdentifiers_module";
import { "<Z>" as valueZ } from "./arbitraryModuleNamespaceIdentifiers_module";
if (valueZ["<X>"] !== "someValue") throw "should be someValue";
if (valueZ["<Y>"] !== "someValue") throw "should be someValue";
if (valueZ["<Z>"] !== valueZ) throw "should be export namespace";

export { type someType as "<A>" };
import { type "<A>" as typeA } from "./arbitraryModuleNamespaceIdentifiers_module";
const importTest: typeA = "expect error about someType";
~~~~~~~~~~
!!! error TS2322: Type '"expect error about someType"' is not assignable to type '"someType"'.

export { type "<A>" as "<B>" } from "./arbitraryModuleNamespaceIdentifiers_module";
import { type "<B>" as typeB } from "./arbitraryModuleNamespaceIdentifiers_module";
const reimportTest: typeB = "expect error about someType";
~~~~~~~~~~~~
!!! error TS2322: Type '"expect error about someType"' is not assignable to type '"someType"'.

export type * as "<C>" from "./arbitraryModuleNamespaceIdentifiers_module";
import { type "<C>" as typeC } from "./arbitraryModuleNamespaceIdentifiers_module";
export type otherType = "otherType";
const importStarTestA: typeC.otherType = "expect error about otherType";
~~~~~~~~~~~~~~~
!!! error TS2322: Type '"expect error about otherType"' is not assignable to type '"otherType"'.

Loading
Loading