Skip to content

Commit 96bffce

Browse files
committed
Always set impliedNodeFormat; query it conditionally for emit, module resolution, and interop
1 parent ecb6eb2 commit 96bffce

21 files changed

+421
-122
lines changed

src/compiler/_namespaces/ts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export * from "../transformers/generators";
5454
export * from "../transformers/module/module";
5555
export * from "../transformers/module/system";
5656
export * from "../transformers/module/esnextAnd2015";
57-
export * from "../transformers/module/node";
57+
export * from "../transformers/module/impliedNodeFormatDependent";
5858
export * from "../transformers/declarations/diagnostics";
5959
export * from "../transformers/declarations";
6060
export * from "../transformer";

src/compiler/checker.ts

Lines changed: 65 additions & 35 deletions
Large diffs are not rendered by default.

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,10 @@
967967
"category": "Error",
968968
"code": 1292
969969
},
970+
"ESM syntax is not allowed in a CommonJS module when 'module' is set to 'preserve'.": {
971+
"category": "Error",
972+
"code": 1293
973+
},
970974

971975
"'with' statements are not allowed in an async function block.": {
972976
"category": "Error",

src/compiler/emitter.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ import {
130130
getEmitFlags,
131131
getEmitHelpers,
132132
getEmitModuleKind,
133+
getEmitModuleResolutionKind,
133134
getEmitScriptTarget,
134135
getExternalModuleName,
135136
getIdentifierTypeArguments,
@@ -799,6 +800,7 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi
799800
newLine: compilerOptions.newLine,
800801
noEmitHelpers: compilerOptions.noEmitHelpers,
801802
module: getEmitModuleKind(compilerOptions),
803+
moduleResolution: getEmitModuleResolutionKind(compilerOptions),
802804
target: getEmitScriptTarget(compilerOptions),
803805
sourceMap: compilerOptions.sourceMap,
804806
inlineSourceMap: compilerOptions.inlineSourceMap,
@@ -866,6 +868,7 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi
866868
newLine: compilerOptions.newLine,
867869
noEmitHelpers: true,
868870
module: compilerOptions.module,
871+
moduleResolution: compilerOptions.moduleResolution,
869872
target: compilerOptions.target,
870873
sourceMap: !forceDtsEmit && compilerOptions.declarationMap,
871874
inlineSourceMap: compilerOptions.inlineSourceMap,

src/compiler/factory/utilities.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {
5353
getAllAccessorDeclarations,
5454
getEmitFlags,
5555
getEmitHelpers,
56+
getEmitModuleFormatOfFile,
5657
getEmitModuleKind,
5758
getESModuleInterop,
5859
getExternalModuleName,
@@ -71,6 +72,7 @@ import {
7172
HasIllegalTypeParameters,
7273
Identifier,
7374
idText,
75+
impliedNodeFormatForEmit,
7476
ImportCall,
7577
ImportDeclaration,
7678
ImportEqualsDeclaration,
@@ -712,7 +714,7 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: Node
712714
if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) {
713715
let namedBindings: NamedImportBindings | undefined;
714716
const moduleKind = getEmitModuleKind(compilerOptions);
715-
if ((moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) || sourceFile.impliedNodeFormat === ModuleKind.ESNext) {
717+
if ((moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) || impliedNodeFormatForEmit(sourceFile, compilerOptions) === ModuleKind.ESNext) {
716718
// use named imports
717719
const helpers = getEmitHelpers(sourceFile);
718720
if (helpers) {
@@ -769,10 +771,8 @@ export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactor
769771
return externalHelpersModuleName;
770772
}
771773

772-
const moduleKind = getEmitModuleKind(compilerOptions);
773774
let create = (hasExportStarsToExportValues || (getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault))
774-
&& moduleKind !== ModuleKind.System
775-
&& (moduleKind < ModuleKind.ES2015 || node.impliedNodeFormat === ModuleKind.CommonJS);
775+
&& getEmitModuleFormatOfFile(node, compilerOptions) < ModuleKind.System;
776776
if (!create) {
777777
const helpers = getEmitHelpers(node);
778778
if (helpers) {

src/compiler/moduleSpecifiers.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
getBaseFileName,
3636
GetCanonicalFileName,
3737
getConditions,
38+
getDefaultResolutionModeForFile,
3839
getDirectoryPath,
3940
getEmitModuleResolutionKind,
4041
getModeForResolutionAtIndex,
@@ -134,7 +135,7 @@ export interface ModuleSpecifierPreferences {
134135
/**
135136
* @param syntaxImpliedNodeFormat Used when the import syntax implies ESM or CJS irrespective of the mode of the file.
136137
*/
137-
getAllowedEndingsInPreferredOrder(syntaxImpliedNodeFormat?: SourceFile["impliedNodeFormat"]): ModuleSpecifierEnding[];
138+
getAllowedEndingsInPreferredOrder(syntaxImpliedNodeFormat?: ResolutionMode): ModuleSpecifierEnding[];
138139
}
139140

140141
/** @internal */
@@ -154,8 +155,10 @@ export function getModuleSpecifierPreferences(
154155
importModuleSpecifierPreference === "project-relative" ? RelativePreference.ExternalNonRelative :
155156
RelativePreference.Shortest,
156157
getAllowedEndingsInPreferredOrder: syntaxImpliedNodeFormat => {
157-
const preferredEnding = syntaxImpliedNodeFormat !== importingSourceFile.impliedNodeFormat ? getPreferredEnding(syntaxImpliedNodeFormat) : filePreferredEnding;
158-
if ((syntaxImpliedNodeFormat ?? importingSourceFile.impliedNodeFormat) === ModuleKind.ESNext) {
158+
const impliedNodeFormat = getDefaultResolutionModeForFile(importingSourceFile, compilerOptions);
159+
const preferredEnding = syntaxImpliedNodeFormat !== impliedNodeFormat ? getPreferredEnding(syntaxImpliedNodeFormat) : filePreferredEnding;
160+
const moduleResolution = getEmitModuleResolutionKind(compilerOptions);
161+
if ((syntaxImpliedNodeFormat ?? impliedNodeFormat) === ModuleKind.ESNext && ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext) {
159162
if (shouldAllowImportingTsExtension(compilerOptions, importingSourceFile.fileName)) {
160163
return [ModuleSpecifierEnding.TsExtension, ModuleSpecifierEnding.JsExtension];
161164
}
@@ -195,7 +198,7 @@ export function getModuleSpecifierPreferences(
195198
}
196199
return getModuleSpecifierEndingPreference(
197200
importModuleSpecifierEnding,
198-
resolutionMode ?? importingSourceFile.impliedNodeFormat,
201+
resolutionMode ?? getDefaultResolutionModeForFile(importingSourceFile, compilerOptions),
199202
compilerOptions,
200203
importingSourceFile,
201204
);
@@ -266,7 +269,7 @@ function getModuleSpecifierWorker(
266269
const info = getInfo(importingSourceFileName, host);
267270
const modulePaths = getAllModulePaths(info, toFileName, host, userPreferences, options);
268271
return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode)) ||
269-
getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || importingSourceFile.impliedNodeFormat, preferences);
272+
getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || getDefaultResolutionModeForFile(importingSourceFile, compilerOptions), preferences);
270273
}
271274

272275
/** @internal */
@@ -388,7 +391,11 @@ function computeModuleSpecifiers(
388391
if (reason.kind !== FileIncludeKind.Import || reason.file !== importingSourceFile.path) return undefined;
389392
// If the candidate import mode doesn't match the mode we're generating for, don't consider it
390393
// TODO: maybe useful to keep around as an alternative option for certain contexts where the mode is overridable
391-
if (importingSourceFile.impliedNodeFormat && importingSourceFile.impliedNodeFormat !== getModeForResolutionAtIndex(importingSourceFile, reason.index, compilerOptions)) return undefined;
394+
const existingMode = getModeForResolutionAtIndex(importingSourceFile, reason.index, compilerOptions);
395+
const targetMode = options.overrideImportMode ?? getDefaultResolutionModeForFile(importingSourceFile, compilerOptions);
396+
if (existingMode !== targetMode && existingMode !== undefined && targetMode !== undefined) {
397+
return undefined;
398+
}
392399
const specifier = getModuleNameStringLiteralAt(importingSourceFile, reason.index).text;
393400
// If the preference is for non relative and the module specifier is relative, ignore it
394401
return preferences.relativePreference !== RelativePreference.NonRelative || !pathIsRelative(specifier) ?
@@ -1078,7 +1085,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
10781085
const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath);
10791086
if (isPackageJsonInfo(cachedPackageJson) || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) {
10801087
const packageJsonContent: Record<string, any> | undefined = cachedPackageJson?.contents.packageJsonContent || tryParseJson(host.readFile!(packageJsonPath)!);
1081-
const importMode = overrideMode || importingSourceFile.impliedNodeFormat;
1088+
const importMode = overrideMode || getDefaultResolutionModeForFile(importingSourceFile, options);
10821089
if (getResolvePackageJsonExports(options)) {
10831090
// The package name that we found in node_modules could be different from the package
10841091
// name in the package.json content via url/filepath dependency specifiers. We need to

0 commit comments

Comments
 (0)