Skip to content

Commit

Permalink
Pass correct module resolution state when reading package.json info s…
Browse files Browse the repository at this point in the history
…o that they are correctly tracked in the resolution
  • Loading branch information
sheetalkamat committed Jul 28, 2022
1 parent bef492e commit b52e333
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 74 deletions.
5 changes: 5 additions & 0 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,11 @@ namespace ts {
/** Does nothing. */
export function noop(_?: unknown): void { }

export const noopPush: Push<any> = {
push: noop,
length: 0
};

/** Do nothing and return false */
export function returnFalse(): false {
return false;
Expand Down
84 changes: 28 additions & 56 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ namespace ts {
resultFromCache?: ResolvedModuleWithFailedLookupLocations;
packageJsonInfoCache: PackageJsonInfoCache | undefined;
features: NodeResolutionFeatures;
conditions: string[];
conditions: readonly string[];
requestContainingDirectory: string | undefined;
reportResolutionDiagnostic: (d: ResolutionDiagnostic) => void;
}
Expand Down Expand Up @@ -506,18 +506,7 @@ namespace ts {
host: ModuleResolutionHost,
cache: ModuleResolutionCache | undefined,
): PackageJsonInfo | undefined {
const moduleResolutionState: ModuleResolutionState = {
compilerOptions: options,
host,
traceEnabled: isTraceEnabled(options, host),
failedLookupLocations: [],
affectingLocations: [],
packageJsonInfoCache: cache?.getPackageJsonInfoCache(),
conditions: emptyArray,
features: NodeResolutionFeatures.None,
requestContainingDirectory: containingDirectory,
reportResolutionDiagnostic: noop
};
const moduleResolutionState = getTemporaryModuleResolutionState(cache?.getPackageJsonInfoCache(), host, options);

return forEachAncestorDirectory(containingDirectory, ancestorDirectory => {
if (getBaseFileName(ancestorDirectory) !== "node_modules") {
Expand Down Expand Up @@ -1440,8 +1429,8 @@ namespace ts {
}

function node16ModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions,
host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference,
resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations {
host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference,
resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations {
return nodeNextModuleNameResolverWorker(
NodeResolutionFeatures.Node16Default,
moduleName,
Expand All @@ -1455,8 +1444,8 @@ namespace ts {
}

function nodeNextModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions,
host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference,
resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations {
host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference,
resolutionMode?: ResolutionMode): ResolvedModuleWithFailedLookupLocations {
return nodeNextModuleNameResolverWorker(
NodeResolutionFeatures.NodeNextDefault,
moduleName,
Expand Down Expand Up @@ -1861,18 +1850,9 @@ namespace ts {
let entrypoints: string[] | undefined;
const extensions = resolveJs ? Extensions.JavaScript : Extensions.TypeScript;
const features = getDefaultNodeResolutionFeatures(options);
const requireState: ModuleResolutionState = {
compilerOptions: options,
host,
traceEnabled: isTraceEnabled(options, host),
failedLookupLocations: [],
affectingLocations: [],
packageJsonInfoCache: cache?.getPackageJsonInfoCache(),
conditions: ["node", "require", "types"],
features,
requestContainingDirectory: packageJsonInfo.packageDirectory,
reportResolutionDiagnostic: noop
};
const requireState = getTemporaryModuleResolutionState(cache?.getPackageJsonInfoCache(), host, options);
requireState.conditions = ["node", "require", "types"];
requireState.requestContainingDirectory = packageJsonInfo.packageDirectory;
const requireResolution = loadNodeModuleFromDirectoryWorker(
extensions,
packageJsonInfo.packageDirectory,
Expand Down Expand Up @@ -1958,6 +1938,22 @@ namespace ts {
}
}

/*@internal*/
export function getTemporaryModuleResolutionState(packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ModuleResolutionState {
return {
host,
compilerOptions: options,
traceEnabled: isTraceEnabled(options, host),
failedLookupLocations: noopPush,
affectingLocations: noopPush,
packageJsonInfoCache,
features: NodeResolutionFeatures.None,
conditions: emptyArray,
requestContainingDirectory: undefined,
reportResolutionDiagnostic: noop
};
}

/*@internal*/
interface PackageJsonInfo {
packageDirectory: string;
Expand All @@ -1972,31 +1968,7 @@ namespace ts {
* A function for locating the package.json scope for a given path
*/
/*@internal*/
export function getPackageScopeForPath(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): PackageJsonInfo | undefined {
const state: {
host: ModuleResolutionHost;
compilerOptions: CompilerOptions;
traceEnabled: boolean;
failedLookupLocations: Push<string>;
affectingLocations: Push<string>;
resultFromCache?: ResolvedModuleWithFailedLookupLocations;
packageJsonInfoCache: PackageJsonInfoCache | undefined;
features: number;
conditions: never[];
requestContainingDirectory: string | undefined;
reportResolutionDiagnostic: (d: ResolutionDiagnostic) => void;
} = {
host,
compilerOptions: options,
traceEnabled: isTraceEnabled(options, host),
failedLookupLocations: [],
affectingLocations: [],
packageJsonInfoCache,
features: 0,
conditions: [],
requestContainingDirectory: undefined,
reportResolutionDiagnostic: noop
};
export function getPackageScopeForPath(fileName: Path, state: ModuleResolutionState): PackageJsonInfo | undefined {
const parts = getPathComponents(fileName);
parts.pop();
while (parts.length > 0) {
Expand Down Expand Up @@ -2175,7 +2147,7 @@ namespace ts {
function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult<Resolved> {
const useCaseSensitiveFileNames = typeof state.host.useCaseSensitiveFileNames === "function" ? state.host.useCaseSensitiveFileNames() : state.host.useCaseSensitiveFileNames;
const directoryPath = toPath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.(), createGetCanonicalFileName(useCaseSensitiveFileNames === undefined ? true : useCaseSensitiveFileNames));
const scope = getPackageScopeForPath(directoryPath, state.packageJsonInfoCache, state.host, state.compilerOptions);
const scope = getPackageScopeForPath(directoryPath, state);
if (!scope || !scope.packageJsonContent.exports) {
return undefined;
}
Expand Down Expand Up @@ -2237,7 +2209,7 @@ namespace ts {
}
const useCaseSensitiveFileNames = typeof state.host.useCaseSensitiveFileNames === "function" ? state.host.useCaseSensitiveFileNames() : state.host.useCaseSensitiveFileNames;
const directoryPath = toPath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.(), createGetCanonicalFileName(useCaseSensitiveFileNames === undefined ? true : useCaseSensitiveFileNames));
const scope = getPackageScopeForPath(directoryPath, state.packageJsonInfoCache, state.host, state.compilerOptions);
const scope = getPackageScopeForPath(directoryPath, state);
if (!scope) {
if (state.traceEnabled) {
trace(state.host, Diagnostics.Directory_0_has_no_containing_package_json_scope_Imports_will_not_resolve, directoryPath);
Expand Down
15 changes: 2 additions & 13 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ namespace ts {
return undefined;
}
function lookupFromPackageJson(): NonNullable<ResolutionMode> {
const scope = getPackageScopeForPath(fileName, packageJsonInfoCache, host, options);
const scope = getPackageScopeForPath(fileName, getTemporaryModuleResolutionState(packageJsonInfoCache, host, options));
return scope?.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
}
}
Expand Down Expand Up @@ -1174,18 +1174,7 @@ namespace ts {
let oldProgram = typeof oldProgramOrOldBuildInfoProgramConstructor === "object" ? oldProgramOrOldBuildInfoProgramConstructor : undefined;
let oldBuildInfoProgram: OldBuildInfoProgram | undefined;
if (!oldProgram && typeof oldProgramOrOldBuildInfoProgramConstructor === "function") {
const state: ModuleResolutionState = {
host,
compilerOptions: options,
traceEnabled: isTraceEnabled(options, host),
failedLookupLocations: [],
affectingLocations: [],
packageJsonInfoCache: moduleResolutionCache?.getPackageJsonInfoCache(),
features: 0,
conditions: [],
requestContainingDirectory: undefined,
reportResolutionDiagnostic: noop
};
const state = getTemporaryModuleResolutionState(moduleResolutionCache?.getPackageJsonInfoCache(), host, options);
oldBuildInfoProgram = oldProgramOrOldBuildInfoProgramConstructor({
fileExists: fileName => host.fileExists(fileName),
createHash: maybeBind(host, host.createHash),
Expand Down
2 changes: 1 addition & 1 deletion src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1378,7 +1378,7 @@ namespace ts.server {
const packageDirectory = fileName.substring(0, nodeModulesPathParts.packageRootIndex);
const packageJsonCache = project.getModuleResolutionCache()?.getPackageJsonInfoCache();
const compilerOptions = project.getCompilationSettings();
const packageJson = getPackageScopeForPath(project.toPath(packageDirectory + "/package.json"), packageJsonCache, project, compilerOptions);
const packageJson = getPackageScopeForPath(project.toPath(packageDirectory + "/package.json"), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions));
if (!packageJson) return undefined;
// Use fake options instead of actual compiler options to avoid following export map if the project uses node16 or nodenext -
// Mapping from an export map entry across packages is out of scope for now. Returned entrypoints will only be what can be
Expand Down
Loading

0 comments on commit b52e333

Please sign in to comment.