Skip to content

Commit

Permalink
Start Node ESM stable version at Node16 (#48879)
Browse files Browse the repository at this point in the history
* Remove Node12, add Node16.

* Accepted baselines.

* Refactor checking for top-level await, give a better error message in CJS files.

* Accepted baselines.

* Stop erroring on JSON module imports in node ESM since they're no longer experimental.

* Accepted baselines.

* More refactoring, do the same checks for for-await loops.

* Accepted baselines.

* Adjust phrasing to permit for-await on CJS error.

* Accepted baselines.

* Accepted baselines.

* Fix lints.
  • Loading branch information
DanielRosenwasser committed May 3, 2022
1 parent 38c1460 commit 5f9c9a6
Show file tree
Hide file tree
Showing 403 changed files with 21,233 additions and 1,371 deletions.
97 changes: 68 additions & 29 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ namespace ts {
es2020: ModuleKind.ES2020,
es2022: ModuleKind.ES2022,
esnext: ModuleKind.ESNext,
node12: ModuleKind.Node12,
node16: ModuleKind.Node16,
nodenext: ModuleKind.NodeNext,
})),
affectsModuleResolution: true,
Expand Down Expand Up @@ -781,7 +781,7 @@ namespace ts {
type: new Map(getEntries({
node: ModuleResolutionKind.NodeJs,
classic: ModuleResolutionKind.Classic,
node12: ModuleResolutionKind.Node12,
node16: ModuleResolutionKind.Node16,
nodenext: ModuleResolutionKind.NodeNext,
})),
affectsModuleResolution: true,
Expand Down Expand Up @@ -1263,7 +1263,7 @@ namespace ts {
affectsModuleResolution: true,
description: Diagnostics.Control_what_method_is_used_to_detect_module_format_JS_files,
category: Diagnostics.Language_and_Environment,
defaultValueDescription: Diagnostics.auto_Colon_Treat_files_with_imports_exports_import_meta_jsx_with_jsx_Colon_react_jsx_or_esm_format_with_module_Colon_node12_as_modules,
defaultValueDescription: Diagnostics.auto_Colon_Treat_files_with_imports_exports_import_meta_jsx_with_jsx_Colon_react_jsx_or_esm_format_with_module_Colon_node16_as_modules,
}
];

Expand Down
26 changes: 13 additions & 13 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,10 @@
"category": "Error",
"code": 1308
},
"The current file is a CommonJS module and cannot use 'await' at the top level.": {
"category": "Error",
"code": 1309
},
"Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern.": {
"category": "Error",
"code": 1312
Expand Down Expand Up @@ -944,11 +948,11 @@
"category": "Error",
"code": 1322
},
"Dynamic imports are only supported when the '--module' flag is set to 'es2020', 'es2022', 'esnext', 'commonjs', 'amd', 'system', 'umd', 'node12', or 'nodenext'.": {
"Dynamic imports are only supported when the '--module' flag is set to 'es2020', 'es2022', 'esnext', 'commonjs', 'amd', 'system', 'umd', 'node16', or 'nodenext'.": {
"category": "Error",
"code": 1323
},
"Dynamic imports only support a second argument when the '--module' option is set to 'esnext' or 'nodenext'.": {
"Dynamic imports only support a second argument when the '--module' option is set to 'esnext', 'node16', or 'nodenext'.": {
"category": "Error",
"code": 1324
},
Expand Down Expand Up @@ -1016,7 +1020,7 @@
"category": "Error",
"code": 1342
},
"The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node12', or 'nodenext'.": {
"The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', or 'nodenext'.": {
"category": "Error",
"code": 1343
},
Expand Down Expand Up @@ -1140,7 +1144,7 @@
"category": "Message",
"code": 1377
},
"Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', 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', or 'nodenext', and the 'target' option is set to 'es2017' or higher.": {
"category": "Error",
"code": 1378
},
Expand Down Expand Up @@ -1348,7 +1352,7 @@
"category": "Error",
"code": 1431
},
"Top-level 'for await' loops are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', 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', or 'nodenext', and the 'target' option is set to 'es2017' or higher.": {
"category": "Error",
"code": 1432
},
Expand Down Expand Up @@ -1420,7 +1424,7 @@
"category": "Error",
"code": 1451
},
"Resolution modes are only supported when `moduleResolution` is `node12` or `nodenext`.": {
"Resolution modes are only supported when `moduleResolution` is `node16` or `nodenext`.": {
"category": "Error",
"code": 1452
},
Expand Down Expand Up @@ -1465,7 +1469,7 @@
"category": "Message",
"code": 1475
},
"\"auto\": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node12+) as modules.": {
"\"auto\": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules.": {
"category": "Message",
"code": 1476
},
Expand Down Expand Up @@ -3418,11 +3422,11 @@
"category": "Error",
"code": 2833
},
"Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node12' or 'nodenext'. Consider adding an extension to the import path.": {
"Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Consider adding an extension to the import path.": {
"category": "Error",
"code": 2834
},
"Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node12' or 'nodenext'. Did you mean '{0}'?": {
"Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean '{0}'?": {
"category": "Error",
"code": 2835
},
Expand Down Expand Up @@ -6106,10 +6110,6 @@
"category": "Error",
"code": 7061
},
"JSON imports are experimental in ES module mode imports.": {
"category": "Error",
"code": 7062
},

"You cannot rename this element.": {
"category": "Error",
Expand Down
24 changes: 12 additions & 12 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,9 @@ namespace ts {
// set in a non-modal module resolution setting here. Do note that our behavior is not particularly well defined when these mode-overriding imports
// are present in a non-modal project; while in theory we'd like to either ignore the mode or provide faithful modern resolution, depending on what we feel is best,
// in practice, not every cache has the options available to intelligently make the choice to ignore the mode request, and it's unclear how modern "faithful modern
// resolution" should be (`node12`? `nodenext`?). As such, witnessing a mode-overriding triple-slash reference in a non-modal module resolution
// resolution" should be (`node16`? `nodenext`?). As such, witnessing a mode-overriding triple-slash reference in a non-modal module resolution
// context should _probably_ be an error - and that should likely be handled by the `Program` (which is what we do).
if (resolutionMode === ModuleKind.ESNext && (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node12 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext)) {
if (resolutionMode === ModuleKind.ESNext && (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext)) {
features |= NodeResolutionFeatures.EsmMode;
}
const conditions = features & NodeResolutionFeatures.Exports ? features & NodeResolutionFeatures.EsmMode ? ["node", "import", "types"] : ["node", "require", "types"] : [];
Expand Down Expand Up @@ -444,7 +444,7 @@ namespace ts {
}

function getDefaultNodeResolutionFeatures(options: CompilerOptions) {
return getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node12 ? NodeResolutionFeatures.Node12Default :
return getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 ? NodeResolutionFeatures.Node16Default :
getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext ? NodeResolutionFeatures.NodeNextDefault :
NodeResolutionFeatures.None;
}
Expand Down Expand Up @@ -950,8 +950,8 @@ namespace ts {
case ModuleKind.CommonJS:
moduleResolution = ModuleResolutionKind.NodeJs;
break;
case ModuleKind.Node12:
moduleResolution = ModuleResolutionKind.Node12;
case ModuleKind.Node16:
moduleResolution = ModuleResolutionKind.Node16;
break;
case ModuleKind.NodeNext:
moduleResolution = ModuleResolutionKind.NodeNext;
Expand All @@ -972,8 +972,8 @@ namespace ts {

perfLogger.logStartResolveModule(moduleName /* , containingFile, ModuleResolutionKind[moduleResolution]*/);
switch (moduleResolution) {
case ModuleResolutionKind.Node12:
result = node12ModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode);
case ModuleResolutionKind.Node16:
result = node16ModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode);
break;
case ModuleResolutionKind.NodeNext:
result = nodeNextModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode);
Expand Down Expand Up @@ -1231,22 +1231,22 @@ namespace ts {
// respecting the `.exports` member of packages' package.json files and its (conditional) mappings of export names
Exports = 1 << 3,
// allowing `*` in the LHS of an export to be followed by more content, eg `"./whatever/*.js"`
// not currently backported to node 12 - https://github.com/nodejs/Release/issues/690
// not supported in node 12 - https://github.com/nodejs/Release/issues/690
ExportsPatternTrailers = 1 << 4,
AllFeatures = Imports | SelfName | Exports | ExportsPatternTrailers,

Node12Default = Imports | SelfName | Exports,
Node16Default = Imports | SelfName | Exports | ExportsPatternTrailers,

NodeNextDefault = AllFeatures,

EsmMode = 1 << 5,
}

function node12ModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions,
function node16ModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions,
host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference,
resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations {
return nodeNextModuleNameResolverWorker(
NodeResolutionFeatures.Node12Default,
NodeResolutionFeatures.Node16Default,
moduleName,
containingFile,
compilerOptions,
Expand Down Expand Up @@ -1310,7 +1310,7 @@ namespace ts {
const traceEnabled = isTraceEnabled(compilerOptions, host);

const failedLookupLocations: string[] = [];
// conditions are only used by the node12/nodenext resolver - there's no priority order in the list,
// conditions are only used by the node16/nodenext resolver - there's no priority order in the list,
//it's essentially a set (priority is determined by object insertion order in the object we look at).
const conditions = features & NodeResolutionFeatures.EsmMode ? ["node", "import", "types"] : ["node", "require", "types"];
if (compilerOptions.noDtsResolution) {
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/moduleSpecifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace ts.moduleSpecifiers {
}

function isFormatRequiringExtensions(compilerOptions: CompilerOptions, importingSourceFileName: Path, host: ModuleSpecifierResolutionHost) {
if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node12
if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16
&& getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) {
return false;
}
Expand Down Expand Up @@ -734,7 +734,7 @@ namespace ts.moduleSpecifiers {
const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath);
if (typeof cachedPackageJson === "object" || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) {
const packageJsonContent = cachedPackageJson?.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!);
if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node12 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext) {
if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext) {
// `conditions` *could* be made to go against `importingSourceFile.impliedNodeFormat` if something wanted to generate
// an ImportEqualsDeclaration in an ESM-implied file or an ImportCall in a CJS-implied file. But since this function is
// usually called to conjure an import out of thin air, we don't have an existing usage to call `getModeForUsageAtIndex`
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ namespace ts {
/**
* Controls the format the file is detected as - this can be derived from only the path
* and files on disk, but needs to be done with a module resolution cache in scope to be performant.
* This is usually `undefined` for compilations that do not have `moduleResolution` values of `node12` or `nodenext`.
* This is usually `undefined` for compilations that do not have `moduleResolution` values of `node16` or `nodenext`.
*/
impliedNodeFormat?: ModuleKind.ESNext | ModuleKind.CommonJS;
/**
Expand Down
10 changes: 5 additions & 5 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ namespace ts {
*/
export function getImpliedNodeFormatForFile(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ModuleKind.ESNext | ModuleKind.CommonJS | undefined {
switch (getEmitModuleResolutionKind(options)) {
case ModuleResolutionKind.Node12:
case ModuleResolutionKind.Node16:
case ModuleResolutionKind.NodeNext:
return fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Mjs]) ? ModuleKind.ESNext :
fileExtensionIsOneOf(fileName, [Extension.Dcts, Extension.Cts, Extension.Cjs]) ? ModuleKind.CommonJS :
Expand Down Expand Up @@ -1210,7 +1210,7 @@ namespace ts {
const containingFilename = combinePaths(containingDirectory, inferredTypesContainingFile);
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename);
for (let i = 0; i < typeReferences.length; i++) {
// under node12/nodenext module resolution, load `types`/ata include names as cjs resolution results by passing an `undefined` mode
// under node16/nodenext module resolution, load `types`/ata include names as cjs resolution results by passing an `undefined` mode
processTypeReferenceDirective(typeReferences[i], /*mode*/ undefined, resolutions[i], { kind: FileIncludeKind.AutomaticTypeDirectiveFile, typeReference: typeReferences[i], packageId: resolutions[i]?.packageId });
}
tracing?.pop();
Expand Down Expand Up @@ -3085,8 +3085,8 @@ namespace ts {
const fileName = toFileNameLowerCase(ref.fileName);
setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective);
const mode = ref.resolutionMode || file.impliedNodeFormat;
if (mode && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node12 && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext) {
programDiagnostics.add(createDiagnosticForRange(file, ref, Diagnostics.Resolution_modes_are_only_supported_when_moduleResolution_is_node12_or_nodenext));
if (mode && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext) {
programDiagnostics.add(createDiagnosticForRange(file, ref, Diagnostics.Resolution_modes_are_only_supported_when_moduleResolution_is_node16_or_nodenext));
}
processTypeReferenceDirective(fileName, mode, resolvedTypeReferenceDirective, { kind: FileIncludeKind.TypeReferenceDirective, file: file.path, index, });
}
Expand Down Expand Up @@ -3515,7 +3515,7 @@ namespace ts {

if (options.resolveJsonModule) {
if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs &&
getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node12 &&
getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node16 &&
getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext) {
createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy, "resolveJsonModule");
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace ts {
return transformECMAScriptModule;
case ModuleKind.System:
return transformSystemModule;
case ModuleKind.Node12:
case ModuleKind.Node16:
case ModuleKind.NodeNext:
return transformNodeModule;
default:
Expand Down
Loading

0 comments on commit 5f9c9a6

Please sign in to comment.