Skip to content

Commit cb38d99

Browse files
authored
Add --module node20 (#61805)
1 parent 97cfa26 commit cb38d99

File tree

536 files changed

+35473
-583
lines changed

Some content is hidden

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

536 files changed

+35473
-583
lines changed

src/compiler/checker.ts

Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3688,6 +3688,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
36883688
getExternalModuleRequireArgument(node) || getExternalModuleImportEqualsDeclarationExpression(node),
36893689
);
36903690
const resolved = resolveExternalModuleSymbol(immediate);
3691+
if (resolved && ModuleKind.Node20 <= moduleKind && moduleKind <= ModuleKind.NodeNext) {
3692+
const moduleExports = getExportOfModule(resolved, "module.exports" as __String, node, dontResolveAlias);
3693+
if (moduleExports) {
3694+
return moduleExports;
3695+
}
3696+
}
36913697
markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false);
36923698
return resolved;
36933699
}
@@ -3803,16 +3809,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
38033809
}
38043810

38053811
function getTargetofModuleDefault(moduleSymbol: Symbol, node: ImportClause | ImportOrExportSpecifier, dontResolveAlias: boolean) {
3812+
const file = moduleSymbol.declarations?.find(isSourceFile);
3813+
const specifier = getModuleSpecifierForImportOrExport(node);
38063814
let exportDefaultSymbol: Symbol | undefined;
3815+
let exportModuleDotExportsSymbol: Symbol | undefined;
38073816
if (isShorthandAmbientModuleSymbol(moduleSymbol)) {
38083817
exportDefaultSymbol = moduleSymbol;
38093818
}
3819+
else if (
3820+
file && specifier &&
3821+
ModuleKind.Node20 <= moduleKind && moduleKind <= ModuleKind.NodeNext &&
3822+
getEmitSyntaxForModuleSpecifierExpression(specifier) === ModuleKind.CommonJS &&
3823+
host.getImpliedNodeFormatForEmit(file) === ModuleKind.ESNext &&
3824+
(exportModuleDotExportsSymbol = resolveExportByName(moduleSymbol, "module.exports" as __String, node, dontResolveAlias))
3825+
) {
3826+
// We have a transpiled default import where the `require` resolves to an ES module with a `module.exports` named
3827+
// export. If `esModuleInterop` is enabled, this will work:
3828+
//
3829+
// const dep_1 = __importDefault(require("./dep.mjs")); // wraps like { default: require("./dep.mjs") }
3830+
// dep_1.default; // require("./dep.mjs") -> the `module.exports` export value
3831+
//
3832+
// But without `esModuleInterop`, it will be broken:
3833+
//
3834+
// const dep_1 = require("./dep.mjs"); // the `module.exports` export value (could be primitive)
3835+
// dep_1.default; // `default` property access on the `module.exports` export value
3836+
//
3837+
// We could try to resolve the 'default' property in the latter case, but it's a mistake to run in this
3838+
// environment without `esModuleInterop`, so just error.
3839+
if (!getESModuleInterop(compilerOptions)) {
3840+
error(node.name, Diagnostics.Module_0_can_only_be_default_imported_using_the_1_flag, symbolToString(moduleSymbol), "esModuleInterop");
3841+
return undefined;
3842+
}
3843+
markSymbolOfAliasDeclarationIfTypeOnly(node, exportModuleDotExportsSymbol, /*finalTarget*/ undefined, /*overwriteEmpty*/ false);
3844+
return exportModuleDotExportsSymbol;
3845+
}
38103846
else {
38113847
exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, node, dontResolveAlias);
38123848
}
38133849

3814-
const file = moduleSymbol.declarations?.find(isSourceFile);
3815-
const specifier = getModuleSpecifierForImportOrExport(node);
38163850
if (!specifier) {
38173851
return exportDefaultSymbol;
38183852
}
@@ -4958,10 +4992,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
49584992
}
49594993

49604994
const referenceParent = referencingLocation.parent;
4961-
if (
4962-
(isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) ||
4963-
isImportCall(referenceParent)
4964-
) {
4995+
const namespaceImport = isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent);
4996+
if (namespaceImport || isImportCall(referenceParent)) {
49654997
const reference = isImportCall(referenceParent) ? referenceParent.arguments[0] : referenceParent.moduleSpecifier;
49664998
const type = getTypeOfSymbol(symbol);
49674999
const defaultOnlyType = getTypeWithSyntheticDefaultOnly(type, symbol, moduleSymbol!, reference);
@@ -4970,14 +5002,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
49705002
}
49715003

49725004
const targetFile = moduleSymbol?.declarations?.find(isSourceFile);
4973-
const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(getEmitSyntaxForModuleSpecifierExpression(reference), host.getImpliedNodeFormatForEmit(targetFile));
4974-
if (getESModuleInterop(compilerOptions) || isEsmCjsRef) {
4975-
let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call);
4976-
if (!sigs || !sigs.length) {
4977-
sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct);
5005+
const usageMode = getEmitSyntaxForModuleSpecifierExpression(reference);
5006+
let exportModuleDotExportsSymbol: Symbol | undefined;
5007+
if (
5008+
namespaceImport && targetFile &&
5009+
ModuleKind.Node20 <= moduleKind && moduleKind <= ModuleKind.NodeNext &&
5010+
usageMode === ModuleKind.CommonJS && host.getImpliedNodeFormatForEmit(targetFile) === ModuleKind.ESNext &&
5011+
(exportModuleDotExportsSymbol = resolveExportByName(symbol, "module.exports" as __String, namespaceImport, dontResolveAlias))
5012+
) {
5013+
if (!suppressInteropError && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) {
5014+
error(referencingLocation, Diagnostics.This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, "esModuleInterop");
49785015
}
5016+
if (getESModuleInterop(compilerOptions) && hasSignatures(type)) {
5017+
return cloneTypeAsModuleType(exportModuleDotExportsSymbol, type, referenceParent);
5018+
}
5019+
return exportModuleDotExportsSymbol;
5020+
}
5021+
5022+
const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(usageMode, host.getImpliedNodeFormatForEmit(targetFile));
5023+
if (getESModuleInterop(compilerOptions) || isEsmCjsRef) {
49795024
if (
4980-
(sigs && sigs.length) ||
5025+
hasSignatures(type) ||
49815026
getPropertyOfType(type, InternalSymbolName.Default, /*skipObjectFunctionPropertyAugment*/ true) ||
49825027
isEsmCjsRef
49835028
) {
@@ -4992,6 +5037,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
49925037
return symbol;
49935038
}
49945039

5040+
function hasSignatures(type: Type): boolean {
5041+
return some(getSignaturesOfStructuredType(type, SignatureKind.Call)) || some(getSignaturesOfStructuredType(type, SignatureKind.Construct));
5042+
}
5043+
49955044
/**
49965045
* Create a new symbol which has the module's type less the call and construct signatures
49975046
*/
@@ -38117,7 +38166,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3811738166
}
3811838167
}
3811938168
else if (moduleKind < ModuleKind.ES2020 && moduleKind !== ModuleKind.System) {
38120-
error(node, Diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_es2020_es2022_esnext_system_node16_node18_or_nodenext);
38169+
error(node, Diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_es2020_es2022_esnext_system_node16_node18_node20_or_nodenext);
3812138170
}
3812238171
const file = getSourceFileOfNode(node);
3812338172
Debug.assert(!!(file.flags & NodeFlags.PossiblyContainsImportMeta), "Containing file is missing import meta node flag.");
@@ -39699,6 +39748,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3969939748
switch (moduleKind) {
3970039749
case ModuleKind.Node16:
3970139750
case ModuleKind.Node18:
39751+
case ModuleKind.Node20:
3970239752
case ModuleKind.NodeNext:
3970339753
if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) {
3970439754
span ??= getSpanOfTokenAtPosition(sourceFile, node.pos);
@@ -39719,8 +39769,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3971939769
// fallthrough
3972039770
default:
3972139771
span ??= getSpanOfTokenAtPosition(sourceFile, node.pos);
39722-
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 :
39723-
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;
39772+
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 :
39773+
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;
3972439774
diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, message));
3972539775
hasError = true;
3972639776
break;
@@ -48330,12 +48380,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4833048380
return grammarErrorOnNode(
4833148381
node,
4833248382
isImportAttributes
48333-
? Diagnostics.Import_attributes_are_only_supported_when_the_module_option_is_set_to_esnext_node18_nodenext_or_preserve
48334-
: Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_node18_nodenext_or_preserve,
48383+
? Diagnostics.Import_attributes_are_only_supported_when_the_module_option_is_set_to_esnext_node18_node20_nodenext_or_preserve
48384+
: Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_node18_node20_nodenext_or_preserve,
4833548385
);
4833648386
}
4833748387

48338-
if (moduleKind === ModuleKind.NodeNext && !isImportAttributes) {
48388+
if (ModuleKind.Node20 <= moduleKind && moduleKind <= ModuleKind.NodeNext && !isImportAttributes) {
4833948389
return grammarErrorOnFirstToken(node, Diagnostics.Import_assertions_have_been_replaced_by_import_attributes_Use_with_instead_of_assert);
4834048390
}
4834148391

@@ -52383,6 +52433,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5238352433
switch (moduleKind) {
5238452434
case ModuleKind.Node16:
5238552435
case ModuleKind.Node18:
52436+
case ModuleKind.Node20:
5238652437
case ModuleKind.NodeNext:
5238752438
if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) {
5238852439
diagnostics.add(
@@ -52401,7 +52452,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5240152452
// fallthrough
5240252453
default:
5240352454
diagnostics.add(
52404-
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),
52455+
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),
5240552456
);
5240652457
break;
5240752458
}
@@ -53244,7 +53295,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5324453295
}
5324553296
}
5324653297
else if (moduleKind === ModuleKind.ES2015) {
53247-
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);
53298+
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);
5324853299
}
5324953300

5325053301
if (node.typeArguments) {
@@ -53258,7 +53309,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5325853309

5325953310
if (nodeArguments.length > 1) {
5326053311
const importAttributesArgument = nodeArguments[1];
53261-
return grammarErrorOnNode(importAttributesArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_node18_nodenext_or_preserve);
53312+
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);
5326253313
}
5326353314
}
5326453315

src/compiler/commandLineParser.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ export const moduleOptionDeclaration: CommandLineOptionOfCustomType = {
603603
esnext: ModuleKind.ESNext,
604604
node16: ModuleKind.Node16,
605605
node18: ModuleKind.Node18,
606+
node20: ModuleKind.Node20,
606607
nodenext: ModuleKind.NodeNext,
607608
preserve: ModuleKind.Preserve,
608609
})),

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,11 +1031,11 @@
10311031
"category": "Error",
10321032
"code": 1322
10331033
},
1034-
"Dynamic imports are only supported when the '--module' flag is set to 'es2020', 'es2022', 'esnext', 'commonjs', 'amd', 'system', 'umd', 'node16', 'node18', or 'nodenext'.": {
1034+
"Dynamic imports are only supported when the '--module' flag is set to 'es2020', 'es2022', 'esnext', 'commonjs', 'amd', 'system', 'umd', 'node16', 'node18', 'node20', or 'nodenext'.": {
10351035
"category": "Error",
10361036
"code": 1323
10371037
},
1038-
"Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', 'node18', 'nodenext', or 'preserve'.": {
1038+
"Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', 'node18', 'node20', 'nodenext', or 'preserve'.": {
10391039
"category": "Error",
10401040
"code": 1324
10411041
},
@@ -1103,7 +1103,7 @@
11031103
"category": "Error",
11041104
"code": 1341
11051105
},
1106-
"The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', 'node18', or 'nodenext'.": {
1106+
"The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', 'node18', 'node20', or 'nodenext'.": {
11071107
"category": "Error",
11081108
"code": 1343
11091109
},
@@ -1223,7 +1223,7 @@
12231223
"category": "Message",
12241224
"code": 1377
12251225
},
1226-
"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.": {
1226+
"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.": {
12271227
"category": "Error",
12281228
"code": 1378
12291229
},
@@ -1427,7 +1427,7 @@
14271427
"category": "Error",
14281428
"code": 1431
14291429
},
1430-
"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.": {
1430+
"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.": {
14311431
"category": "Error",
14321432
"code": 1432
14331433
},
@@ -3799,15 +3799,15 @@
37993799
"category": "Error",
38003800
"code": 2820
38013801
},
3802-
"Import assertions are only supported when the '--module' option is set to 'esnext', 'node18', 'nodenext', or 'preserve'.": {
3802+
"Import assertions are only supported when the '--module' option is set to 'esnext', 'node18', 'node20', 'nodenext', or 'preserve'.": {
38033803
"category": "Error",
38043804
"code": 2821
38053805
},
38063806
"Import assertions cannot be used with type-only imports or exports.": {
38073807
"category": "Error",
38083808
"code": 2822
38093809
},
3810-
"Import attributes are only supported when the '--module' option is set to 'esnext', 'node18', 'nodenext', or 'preserve'.": {
3810+
"Import attributes are only supported when the '--module' option is set to 'esnext', 'node18', 'node20', 'nodenext', or 'preserve'.": {
38113811
"category": "Error",
38123812
"code": 2823
38133813
},
@@ -3887,7 +3887,7 @@
38873887
"category": "Error",
38883888
"code": 2853
38893889
},
3890-
"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.": {
3890+
"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.": {
38913891
"category": "Error",
38923892
"code": 2854
38933893
},

src/compiler/transformer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<Source
8787
case ModuleKind.ES2015:
8888
case ModuleKind.Node16:
8989
case ModuleKind.Node18:
90+
case ModuleKind.Node20:
9091
case ModuleKind.NodeNext:
9192
case ModuleKind.CommonJS:
9293
// Wraps `transformModule` and `transformECMAScriptModule` and

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7606,6 +7606,7 @@ export enum ModuleKind {
76067606
// Node16+ is an amalgam of commonjs (albeit updated) and es2022+, and represents a distinct module system from es2020/esnext
76077607
Node16 = 100,
76087608
Node18 = 101,
7609+
Node20 = 102,
76097610
NodeNext = 199,
76107611

76117612
// Emit as written

0 commit comments

Comments
 (0)