Skip to content

Commit a9139bf

Browse files
Only look up package.json type if module is node16/nodenext or file is in node_modules (#58825)
Co-authored-by: Jake Bailey <[email protected]>
1 parent f37482c commit a9139bf

File tree

90 files changed

+3082
-355
lines changed

Some content is hidden

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

90 files changed

+3082
-355
lines changed

src/compiler/_namespaces/ts.ts

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

src/compiler/checker.ts

+63-34
Large diffs are not rendered by default.

src/compiler/diagnosticMessages.json

+4
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

+3
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ import {
131131
getEmitFlags,
132132
getEmitHelpers,
133133
getEmitModuleKind,
134+
getEmitModuleResolutionKind,
134135
getEmitScriptTarget,
135136
getExternalModuleName,
136137
getIdentifierTypeArguments,
@@ -828,6 +829,7 @@ export function emitFiles(
828829
newLine: compilerOptions.newLine,
829830
noEmitHelpers: compilerOptions.noEmitHelpers,
830831
module: getEmitModuleKind(compilerOptions),
832+
moduleResolution: getEmitModuleResolutionKind(compilerOptions),
831833
target: getEmitScriptTarget(compilerOptions),
832834
sourceMap: compilerOptions.sourceMap,
833835
inlineSourceMap: compilerOptions.inlineSourceMap,
@@ -903,6 +905,7 @@ export function emitFiles(
903905
newLine: compilerOptions.newLine,
904906
noEmitHelpers: true,
905907
module: compilerOptions.module,
908+
moduleResolution: compilerOptions.moduleResolution,
906909
target: compilerOptions.target,
907910
sourceMap: !forceDtsEmit && compilerOptions.declarationMap,
908911
inlineSourceMap: compilerOptions.inlineSourceMap,

src/compiler/factory/utilities.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,12 @@ import {
5151
getAllAccessorDeclarations,
5252
getEmitFlags,
5353
getEmitHelpers,
54+
getEmitModuleFormatOfFileWorker,
5455
getEmitModuleKind,
5556
getESModuleInterop,
5657
getExternalModuleName,
5758
getExternalModuleNameFromPath,
59+
getImpliedNodeFormatForEmitWorker,
5860
getJSDocType,
5961
getJSDocTypeTag,
6062
getModifiers,
@@ -687,7 +689,7 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: Node
687689
if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) {
688690
let namedBindings: NamedImportBindings | undefined;
689691
const moduleKind = getEmitModuleKind(compilerOptions);
690-
if ((moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) || sourceFile.impliedNodeFormat === ModuleKind.ESNext) {
692+
if ((moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) || getImpliedNodeFormatForEmitWorker(sourceFile, compilerOptions) === ModuleKind.ESNext) {
691693
// use named imports
692694
const helpers = getEmitHelpers(sourceFile);
693695
if (helpers) {
@@ -743,10 +745,8 @@ function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node
743745
return externalHelpersModuleName;
744746
}
745747

746-
const moduleKind = getEmitModuleKind(compilerOptions);
747748
let create = (hasExportStarsToExportValues || (getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault))
748-
&& moduleKind !== ModuleKind.System
749-
&& (moduleKind < ModuleKind.ES2015 || node.impliedNodeFormat === ModuleKind.CommonJS);
749+
&& getEmitModuleFormatOfFileWorker(node, compilerOptions) < ModuleKind.System;
750750
if (!create) {
751751
const helpers = getEmitHelpers(node);
752752
if (helpers) {

src/compiler/moduleSpecifiers.ts

+24-13
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ import {
3737
getBaseFileName,
3838
GetCanonicalFileName,
3939
getConditions,
40+
getDefaultResolutionModeForFileWorker,
4041
getDirectoryPath,
4142
getEmitModuleResolutionKind,
42-
getModeForResolutionAtIndex,
4343
getModuleNameStringLiteralAt,
4444
getModuleSpecifierEndingPreference,
4545
getNodeModulePathParts,
@@ -143,12 +143,13 @@ export interface ModuleSpecifierPreferences {
143143
/**
144144
* @param syntaxImpliedNodeFormat Used when the import syntax implies ESM or CJS irrespective of the mode of the file.
145145
*/
146-
getAllowedEndingsInPreferredOrder(syntaxImpliedNodeFormat?: SourceFile["impliedNodeFormat"]): ModuleSpecifierEnding[];
146+
getAllowedEndingsInPreferredOrder(syntaxImpliedNodeFormat?: ResolutionMode): ModuleSpecifierEnding[];
147147
}
148148

149149
/** @internal */
150150
export function getModuleSpecifierPreferences(
151151
{ importModuleSpecifierPreference, importModuleSpecifierEnding }: UserPreferences,
152+
host: Pick<ModuleSpecifierResolutionHost, "getDefaultResolutionModeForFile">,
152153
compilerOptions: CompilerOptions,
153154
importingSourceFile: Pick<SourceFile, "fileName" | "impliedNodeFormat">,
154155
oldImportSpecifier?: string,
@@ -163,8 +164,10 @@ export function getModuleSpecifierPreferences(
163164
importModuleSpecifierPreference === "project-relative" ? RelativePreference.ExternalNonRelative :
164165
RelativePreference.Shortest,
165166
getAllowedEndingsInPreferredOrder: syntaxImpliedNodeFormat => {
166-
const preferredEnding = syntaxImpliedNodeFormat !== importingSourceFile.impliedNodeFormat ? getPreferredEnding(syntaxImpliedNodeFormat) : filePreferredEnding;
167-
if ((syntaxImpliedNodeFormat ?? importingSourceFile.impliedNodeFormat) === ModuleKind.ESNext) {
167+
const impliedNodeFormat = getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions);
168+
const preferredEnding = syntaxImpliedNodeFormat !== impliedNodeFormat ? getPreferredEnding(syntaxImpliedNodeFormat) : filePreferredEnding;
169+
const moduleResolution = getEmitModuleResolutionKind(compilerOptions);
170+
if ((syntaxImpliedNodeFormat ?? impliedNodeFormat) === ModuleKind.ESNext && ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext) {
168171
if (shouldAllowImportingTsExtension(compilerOptions, importingSourceFile.fileName)) {
169172
return [ModuleSpecifierEnding.TsExtension, ModuleSpecifierEnding.JsExtension];
170173
}
@@ -204,7 +207,7 @@ export function getModuleSpecifierPreferences(
204207
}
205208
return getModuleSpecifierEndingPreference(
206209
importModuleSpecifierEnding,
207-
resolutionMode ?? importingSourceFile.impliedNodeFormat,
210+
resolutionMode ?? getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions),
208211
compilerOptions,
209212
isFullSourceFile(importingSourceFile) ? importingSourceFile : undefined,
210213
);
@@ -225,7 +228,7 @@ export function updateModuleSpecifier(
225228
oldImportSpecifier: string,
226229
options: ModuleSpecifierOptions = {},
227230
): string | undefined {
228-
const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getModuleSpecifierPreferences({}, compilerOptions, importingSourceFile, oldImportSpecifier), {}, options);
231+
const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getModuleSpecifierPreferences({}, host, compilerOptions, importingSourceFile, oldImportSpecifier), {}, options);
229232
if (res === oldImportSpecifier) return undefined;
230233
return res;
231234
}
@@ -245,7 +248,7 @@ export function getModuleSpecifier(
245248
host: ModuleSpecifierResolutionHost,
246249
options: ModuleSpecifierOptions = {},
247250
): string {
248-
return getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getModuleSpecifierPreferences({}, compilerOptions, importingSourceFile), {}, options);
251+
return getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getModuleSpecifierPreferences({}, host, compilerOptions, importingSourceFile), {}, options);
249252
}
250253

251254
/** @internal */
@@ -275,7 +278,7 @@ function getModuleSpecifierWorker(
275278
const info = getInfo(importingSourceFileName, host);
276279
const modulePaths = getAllModulePaths(info, toFileName, host, userPreferences, compilerOptions, options);
277280
return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode)) ||
278-
getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || importingSourceFile.impliedNodeFormat, preferences);
281+
getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || getDefaultResolutionModeForFile(importingSourceFile, host, compilerOptions), preferences);
279282
}
280283

281284
/** @internal */
@@ -403,7 +406,7 @@ export function getLocalModuleSpecifierBetweenFileNames(
403406
compilerOptions,
404407
host,
405408
importMode,
406-
getModuleSpecifierPreferences({}, compilerOptions, importingFile),
409+
getModuleSpecifierPreferences({}, host, compilerOptions, importingFile),
407410
);
408411
}
409412

@@ -417,15 +420,19 @@ function computeModuleSpecifiers(
417420
forAutoImport: boolean,
418421
): ModuleSpecifierResult {
419422
const info = getInfo(importingSourceFile.fileName, host);
420-
const preferences = getModuleSpecifierPreferences(userPreferences, compilerOptions, importingSourceFile);
423+
const preferences = getModuleSpecifierPreferences(userPreferences, host, compilerOptions, importingSourceFile);
421424
const existingSpecifier = isFullSourceFile(importingSourceFile) && forEach(modulePaths, modulePath =>
422425
forEach(
423426
host.getFileIncludeReasons().get(toPath(modulePath.path, host.getCurrentDirectory(), info.getCanonicalFileName)),
424427
reason => {
425428
if (reason.kind !== FileIncludeKind.Import || reason.file !== importingSourceFile.path) return undefined;
426429
// If the candidate import mode doesn't match the mode we're generating for, don't consider it
427430
// TODO: maybe useful to keep around as an alternative option for certain contexts where the mode is overridable
428-
if (importingSourceFile.impliedNodeFormat && importingSourceFile.impliedNodeFormat !== getModeForResolutionAtIndex(importingSourceFile, reason.index, compilerOptions)) return undefined;
431+
const existingMode = host.getModeForResolutionAtIndex(importingSourceFile, reason.index);
432+
const targetMode = options.overrideImportMode ?? host.getDefaultResolutionModeForFile(importingSourceFile);
433+
if (existingMode !== targetMode && existingMode !== undefined && targetMode !== undefined) {
434+
return undefined;
435+
}
429436
const specifier = getModuleNameStringLiteralAt(importingSourceFile, reason.index).text;
430437
// If the preference is for non relative and the module specifier is relative, ignore it
431438
return preferences.relativePreference !== RelativePreference.NonRelative || !pathIsRelative(specifier) ?
@@ -1093,7 +1100,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
10931100

10941101
// Simplify the full file path to something that can be resolved by Node.
10951102

1096-
const preferences = getModuleSpecifierPreferences(userPreferences, options, importingSourceFile);
1103+
const preferences = getModuleSpecifierPreferences(userPreferences, host, options, importingSourceFile);
10971104
const allowedEndings = preferences.getAllowedEndingsInPreferredOrder();
10981105
let moduleSpecifier = path;
10991106
let isPackageRootPath = false;
@@ -1153,7 +1160,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCan
11531160
const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath);
11541161
if (isPackageJsonInfo(cachedPackageJson) || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) {
11551162
const packageJsonContent: Record<string, any> | undefined = cachedPackageJson?.contents.packageJsonContent || tryParseJson(host.readFile!(packageJsonPath)!);
1156-
const importMode = overrideMode || importingSourceFile.impliedNodeFormat;
1163+
const importMode = overrideMode || getDefaultResolutionModeForFile(importingSourceFile, host, options);
11571164
if (getResolvePackageJsonExports(options)) {
11581165
// The package name that we found in node_modules could be different from the package
11591166
// name in the package.json content via url/filepath dependency specifiers. We need to
@@ -1348,3 +1355,7 @@ function getRelativePathIfInSameVolume(path: string, directoryPath: string, getC
13481355
function isPathRelativeToParent(path: string): boolean {
13491356
return startsWith(path, "..");
13501357
}
1358+
1359+
function getDefaultResolutionModeForFile(file: Pick<SourceFile, "fileName" | "impliedNodeFormat" | "packageJsonScope">, host: Pick<ModuleSpecifierResolutionHost, "getDefaultResolutionModeForFile">, compilerOptions: CompilerOptions) {
1360+
return isFullSourceFile(file) ? host.getDefaultResolutionModeForFile(file) : getDefaultResolutionModeForFileWorker(file, compilerOptions);
1361+
}

0 commit comments

Comments
 (0)