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

Support require(esm) in --module nodenext #60761

Merged
merged 11 commits into from
Jan 23, 2025
Next Next commit
Add option, update diagnostics
andrewbranch committed Dec 13, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 90d35e2f17edff504ecef1746848ee31db19c1a1
16 changes: 9 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
@@ -39214,6 +39214,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);
@@ -39234,8 +39235,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;
@@ -48070,8 +48071,8 @@ 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,
);
}

@@ -52071,6 +52072,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(
@@ -52089,7 +52091,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;
}
@@ -52891,7 +52893,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) {
@@ -52905,7 +52907,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);
}
}

1 change: 1 addition & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
@@ -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,
})),
14 changes: 7 additions & 7 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
@@ -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
},
@@ -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
},
@@ -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
},
@@ -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
},
@@ -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
},
1 change: 1 addition & 0 deletions src/compiler/transformer.ts
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
@@ -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);
},
@@ -8964,6 +8965,7 @@ const _computedOptions = createComputedCompilerOptions({
break;
case ModuleKind.Node16:
case ModuleKind.Node18:
case ModuleKind.Node20:
moduleResolution = ModuleResolutionKind.Node16;
break;
case ModuleKind.NodeNext:
@@ -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;
1 change: 1 addition & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
@@ -3255,6 +3255,7 @@ export const enum ModuleKind {
ESNext = "esnext",
Node16 = "node16",
Node18 = "node18",
Node20 = "node20",
NodeNext = "nodenext",
Preserve = "preserve",
}
6 changes: 3 additions & 3 deletions src/services/codefixes/fixModuleAndTargetOptions.ts
Original file line number Diff line number Diff line change
@@ -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();
1 change: 1 addition & 0 deletions src/services/codefixes/importFixes.ts
Original file line number Diff line number Diff line change
@@ -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:
2 changes: 2 additions & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
@@ -2517,6 +2517,7 @@ declare namespace ts {
ESNext = "esnext",
Node16 = "node16",
Node18 = "node18",
Node20 = "node20",
NodeNext = "nodenext",
Preserve = "preserve",
}
@@ -7133,6 +7134,7 @@ declare namespace ts {
ESNext = 99,
Node16 = 100,
Node18 = 101,
Node20 = 102,
NodeNext = 199,
Preserve = 200,
}
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