Skip to content

Commit 5d79052

Browse files
authored
Pass correct module resolution state when reading package.json info so that they are correctly tracked in the resolution (microsoft#50085)
1 parent 949fffb commit 5d79052

File tree

5 files changed

+35
-54
lines changed

5 files changed

+35
-54
lines changed

src/compiler/core.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,11 @@ namespace ts {
17241724
/** Does nothing. */
17251725
export function noop(_?: unknown): void { }
17261726

1727+
export const noopPush: Push<any> = {
1728+
push: noop,
1729+
length: 0
1730+
};
1731+
17271732
/** Do nothing and return false */
17281733
export function returnFalse(): false {
17291734
return false;

src/compiler/moduleNameResolver.ts

Lines changed: 24 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ namespace ts {
117117
resultFromCache?: ResolvedModuleWithFailedLookupLocations;
118118
packageJsonInfoCache: PackageJsonInfoCache | undefined;
119119
features: NodeResolutionFeatures;
120-
conditions: string[];
120+
conditions: readonly string[];
121121
requestContainingDirectory: string | undefined;
122122
reportDiagnostic: DiagnosticReporter;
123123
}
@@ -486,18 +486,7 @@ namespace ts {
486486
host: ModuleResolutionHost,
487487
cache: ModuleResolutionCache | undefined,
488488
): PackageJsonInfo | undefined {
489-
const moduleResolutionState: ModuleResolutionState = {
490-
compilerOptions: options,
491-
host,
492-
traceEnabled: isTraceEnabled(options, host),
493-
failedLookupLocations: [],
494-
affectingLocations: [],
495-
packageJsonInfoCache: cache?.getPackageJsonInfoCache(),
496-
conditions: emptyArray,
497-
features: NodeResolutionFeatures.None,
498-
requestContainingDirectory: containingDirectory,
499-
reportDiagnostic: noop
500-
};
489+
const moduleResolutionState = getTemporaryModuleResolutionState(cache?.getPackageJsonInfoCache(), host, options);
501490

502491
return forEachAncestorDirectory(containingDirectory, ancestorDirectory => {
503492
if (getBaseFileName(ancestorDirectory) !== "node_modules") {
@@ -1692,18 +1681,9 @@ namespace ts {
16921681
let entrypoints: string[] | undefined;
16931682
const extensions = resolveJs ? Extensions.JavaScript : Extensions.TypeScript;
16941683
const features = getDefaultNodeResolutionFeatures(options);
1695-
const requireState: ModuleResolutionState = {
1696-
compilerOptions: options,
1697-
host,
1698-
traceEnabled: isTraceEnabled(options, host),
1699-
failedLookupLocations: [],
1700-
affectingLocations: [],
1701-
packageJsonInfoCache: cache?.getPackageJsonInfoCache(),
1702-
conditions: ["node", "require", "types"],
1703-
features,
1704-
requestContainingDirectory: packageJsonInfo.packageDirectory,
1705-
reportDiagnostic: noop
1706-
};
1684+
const requireState = getTemporaryModuleResolutionState(cache?.getPackageJsonInfoCache(), host, options);
1685+
requireState.conditions = ["node", "require", "types"];
1686+
requireState.requestContainingDirectory = packageJsonInfo.packageDirectory;
17071687
const requireResolution = loadNodeModuleFromDirectoryWorker(
17081688
extensions,
17091689
packageJsonInfo.packageDirectory,
@@ -1789,6 +1769,22 @@ namespace ts {
17891769
}
17901770
}
17911771

1772+
/*@internal*/
1773+
export function getTemporaryModuleResolutionState(packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ModuleResolutionState {
1774+
return {
1775+
host,
1776+
compilerOptions: options,
1777+
traceEnabled: isTraceEnabled(options, host),
1778+
failedLookupLocations: noopPush,
1779+
affectingLocations: noopPush,
1780+
packageJsonInfoCache,
1781+
features: NodeResolutionFeatures.None,
1782+
conditions: emptyArray,
1783+
requestContainingDirectory: undefined,
1784+
reportDiagnostic: noop
1785+
};
1786+
}
1787+
17921788
/*@internal*/
17931789
interface PackageJsonInfo {
17941790
packageDirectory: string;
@@ -1802,31 +1798,7 @@ namespace ts {
18021798
* A function for locating the package.json scope for a given path
18031799
*/
18041800
/*@internal*/
1805-
export function getPackageScopeForPath(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): PackageJsonInfo | undefined {
1806-
const state: {
1807-
host: ModuleResolutionHost;
1808-
compilerOptions: CompilerOptions;
1809-
traceEnabled: boolean;
1810-
failedLookupLocations: Push<string>;
1811-
affectingLocations: Push<string>;
1812-
resultFromCache?: ResolvedModuleWithFailedLookupLocations;
1813-
packageJsonInfoCache: PackageJsonInfoCache | undefined;
1814-
features: number;
1815-
conditions: never[];
1816-
requestContainingDirectory: string | undefined;
1817-
reportDiagnostic: DiagnosticReporter
1818-
} = {
1819-
host,
1820-
compilerOptions: options,
1821-
traceEnabled: isTraceEnabled(options, host),
1822-
failedLookupLocations: [],
1823-
affectingLocations: [],
1824-
packageJsonInfoCache,
1825-
features: 0,
1826-
conditions: [],
1827-
requestContainingDirectory: undefined,
1828-
reportDiagnostic: noop
1829-
};
1801+
export function getPackageScopeForPath(fileName: Path, state: ModuleResolutionState): PackageJsonInfo | undefined {
18301802
const parts = getPathComponents(fileName);
18311803
parts.pop();
18321804
while (parts.length > 0) {
@@ -2004,7 +1976,7 @@ namespace ts {
20041976
function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult<Resolved> {
20051977
const useCaseSensitiveFileNames = typeof state.host.useCaseSensitiveFileNames === "function" ? state.host.useCaseSensitiveFileNames() : state.host.useCaseSensitiveFileNames;
20061978
const directoryPath = toPath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.(), createGetCanonicalFileName(useCaseSensitiveFileNames === undefined ? true : useCaseSensitiveFileNames));
2007-
const scope = getPackageScopeForPath(directoryPath, state.packageJsonInfoCache, state.host, state.compilerOptions);
1979+
const scope = getPackageScopeForPath(directoryPath, state);
20081980
if (!scope || !scope.packageJsonContent.exports) {
20091981
return undefined;
20101982
}
@@ -2066,7 +2038,7 @@ namespace ts {
20662038
}
20672039
const useCaseSensitiveFileNames = typeof state.host.useCaseSensitiveFileNames === "function" ? state.host.useCaseSensitiveFileNames() : state.host.useCaseSensitiveFileNames;
20682040
const directoryPath = toPath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.(), createGetCanonicalFileName(useCaseSensitiveFileNames === undefined ? true : useCaseSensitiveFileNames));
2069-
const scope = getPackageScopeForPath(directoryPath, state.packageJsonInfoCache, state.host, state.compilerOptions);
2041+
const scope = getPackageScopeForPath(directoryPath, state);
20702042
if (!scope) {
20712043
if (state.traceEnabled) {
20722044
trace(state.host, Diagnostics.Directory_0_has_no_containing_package_json_scope_Imports_will_not_resolve, directoryPath);

src/compiler/program.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ namespace ts {
854854
return undefined;
855855
}
856856
function lookupFromPackageJson(): ModuleKind.ESNext | ModuleKind.CommonJS {
857-
const scope = getPackageScopeForPath(fileName, packageJsonInfoCache, host, options);
857+
const scope = getPackageScopeForPath(fileName, getTemporaryModuleResolutionState(packageJsonInfoCache, host, options));
858858
return scope?.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
859859

860860
}

src/server/session.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,7 @@ namespace ts.server {
13781378
const packageDirectory = fileName.substring(0, nodeModulesPathParts.packageRootIndex);
13791379
const packageJsonCache = project.getModuleResolutionCache()?.getPackageJsonInfoCache();
13801380
const compilerOptions = project.getCompilationSettings();
1381-
const packageJson = getPackageScopeForPath(project.toPath(packageDirectory + "/package.json"), packageJsonCache, project, compilerOptions);
1381+
const packageJson = getPackageScopeForPath(project.toPath(packageDirectory + "/package.json"), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions));
13821382
if (!packageJson) return undefined;
13831383
// Use fake options instead of actual compiler options to avoid following export map if the project uses node16 or nodenext -
13841384
// Mapping from an export map entry across packages is out of scope for now. Returned entrypoints will only be what can be

tests/baselines/reference/tscWatch/nodenext watch emit/esm-mode-file-is-edited.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ WatchedFiles::
6363
{"fileName":"/project/src/index.ts","pollingInterval":250}
6464
/a/lib/lib.es2020.full.d.ts:
6565
{"fileName":"/a/lib/lib.es2020.full.d.ts","pollingInterval":250}
66+
/project/package.json:
67+
{"fileName":"/project/package.json","pollingInterval":250}
6668
/project/node_modules/@types:
6769
{"fileName":"/project/node_modules/@types","pollingInterval":500}
6870

@@ -119,6 +121,8 @@ WatchedFiles::
119121
{"fileName":"/project/src/index.ts","pollingInterval":250}
120122
/a/lib/lib.es2020.full.d.ts:
121123
{"fileName":"/a/lib/lib.es2020.full.d.ts","pollingInterval":250}
124+
/project/package.json:
125+
{"fileName":"/project/package.json","pollingInterval":250}
122126
/project/node_modules/@types:
123127
{"fileName":"/project/node_modules/@types","pollingInterval":500}
124128

0 commit comments

Comments
 (0)