Skip to content

Commit

Permalink
Create old buildInfo program from program so host can be passed aroun…
Browse files Browse the repository at this point in the history
…d correctly

Thist also fixes module resolution state creation so that some of the package.json are not missed
  • Loading branch information
sheetalkamat committed Jul 28, 2022
1 parent b71c45a commit 890b6f2
Show file tree
Hide file tree
Showing 16 changed files with 218 additions and 141 deletions.
44 changes: 15 additions & 29 deletions src/compiler/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1895,17 +1895,18 @@ namespace ts {
}
}

function createGetProgramOrOldBuildInfoProgramUndefined(state: ReusableBuilderProgramState): () => Program | OldBuildInfoProgram | undefined {
let oldProgram: OldBuildInfoProgram | undefined;
return () => state.program ?? oldProgram ?? (oldProgram = memoize(() => createOldBuildInfoProgram(
function createGetProgramOrOldBuildInfoProgramUndefined(state: ReusableBuilderProgramState): () => Program | OldBuildInfoProgramConstructor | undefined {
return () => state.program ?? (host => createOldBuildInfoProgram(
host,
state.compilerOptions,
state.cacheResolutions,
// Prefer cached resolutions over serialized format
!state.cacheResolutions ? state.resuableCacheResolutions : undefined,
))());
));
}

export function createOldBuildInfoProgram(
host: OldBuildInfoProgramHost,
compilerOptions: CompilerOptions,
cacheResolutions: ReusableBuilderProgramState["cacheResolutions"],
resuableCacheResolutions: ReusableBuilderProgramState["resuableCacheResolutions"],
Expand All @@ -1929,8 +1930,7 @@ namespace ts {

return {
getCompilerOptions: () => compilerOptions,
getResolvedModule: (host, dirPath, name, mode, redirectedReference) => getResolvedFromCache(
host,
getResolvedModule: (dirPath, name, mode, redirectedReference) => getResolvedFromCache(
cacheResolutions?.modules,
resuableCacheResolutions?.cache.modules,
decodedResolvedModules,
Expand All @@ -1941,8 +1941,7 @@ namespace ts {
cacheResolutions?.moduleNameToDirectoryMap,
decodedModuleNameToDirectoryMap,
),
getResolvedTypeReferenceDirective: (host, dirPath, name, mode, redirectedReference) => getResolvedFromCache(
host,
getResolvedTypeReferenceDirective: (dirPath, name, mode, redirectedReference) => getResolvedFromCache(
cacheResolutions?.typeRefs,
resuableCacheResolutions?.cache.typeRefs,
decodedResolvedTypeRefs,
Expand All @@ -1953,24 +1952,15 @@ namespace ts {
/*moduleNameToDirectoryMap*/ undefined,
/*decodedModuleNameToDirectoryMap*/ undefined,
),
clearRedirectsMap: () => {
cacheResolutions?.modules?.clearRedirectsMap();
cacheResolutions?.typeRefs?.clearRedirectsMap();
cacheResolutions?.moduleNameToDirectoryMap.clearRedirectsMap();
decodedResolvedModules.clearRedirectsMap();
decodedResolvedTypeRefs.clearRedirectsMap();
decodedModuleNameToDirectoryMap.clearRedirectsMap();
}
};

function fileExists(host: OldBuildInfoProgramResolutionHost, fileName: string) {
function fileExists(fileName: string) {
let result = fileExistsMap.get(fileName);
if (result === undefined) fileExistsMap.set(fileName, result = host.fileExists(fileName));
return result;
}

function affectingLocationsSame(
host: OldBuildInfoProgramResolutionHost,
fileName: string,
expected: PackageJsonInfoCacheEntry | string | undefined
): boolean {
Expand All @@ -1990,7 +1980,6 @@ namespace ts {
}

function getResolvedFromCache<T extends ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations>(
host: OldBuildInfoProgramResolutionHost,
cache: CacheWithRedirects<Path, ModeAwareCache<T>> | undefined,
reusableCache: ProgramBuildInfoResolutionCacheWithRedirects | undefined,
decodedReusableCache: DecodedResolvedMap,
Expand All @@ -2006,14 +1995,11 @@ namespace ts {
moduleNameToDirectoryMap?.getMapOfCacheRedirects(redirectedReference)?.get(getModeAwareCacheKey(name, mode))?.get(dirPath);
if (fromCache) {
return fileExists(
host,
(fromCache as ResolvedModuleWithFailedLookupLocations).resolvedModule?.resolvedFileName ||
(fromCache as ResolvedTypeReferenceDirectiveWithFailedLookupLocations).resolvedTypeReferenceDirective!.resolvedFileName!
) && every(
fromCache.affectingLocations,
fileName => affectingLocationsSame(
host, fileName, cacheResolutions!.packageJsonCache?.getPackageJsonInfo(fileName)
)
fileName => affectingLocationsSame(fileName, cacheResolutions!.packageJsonCache?.getPackageJsonInfo(fileName))
) ? fromCache as Resolution : undefined;
}
if (!reusableCache) return undefined;
Expand Down Expand Up @@ -2043,7 +2029,7 @@ namespace ts {

const resolutionId = decodedReusableCache.getMapOfCacheRedirects(redirectedReference)?.get(dirPath)?.get(name, mode) ||
decodedModuleNameToDirectoryMap?.getMapOfCacheRedirects(redirectedReference)?.get(getModeAwareCacheKey(name, mode))?.get(dirPath);
return resolutionId ? toResolution(host, resolutionId) : undefined;
return resolutionId ? toResolution(resolutionId) : undefined;
}

function setBuildInfoResolutionEntries(
Expand Down Expand Up @@ -2116,16 +2102,16 @@ namespace ts {
));
}

function toAffectingFileLocation(host: OldBuildInfoProgramResolutionHost, fileId: ProgramBuildInfoAbsoluteFileId) {
function toAffectingFileLocation(fileId: ProgramBuildInfoAbsoluteFileId) {
if (!decodedHashes && resuableCacheResolutions!.cache.hash) {
decodedHashes = arrayToMap(resuableCacheResolutions!.cache.hash, hash => isArray(hash) ? hash[0] : hash, hash => isArray(hash) ? hash[1] : undefined);
}
const hash = decodedHashes?.get(fileId);
const file = resuableCacheResolutions!.getProgramBuildInfoFilePathDecoder().toFileAbsolutePath(fileId);
return affectingLocationsSame(host, file, hash) ? file : undefined;
return affectingLocationsSame(file, hash) ? file : undefined;
}

function toResolution(host: OldBuildInfoProgramResolutionHost, resolutionId: ProgramBuildInfoResolutionId): Resolution | undefined {
function toResolution(resolutionId: ProgramBuildInfoResolutionId): Resolution | undefined {
const existing = resolutions?.[resolutionId - 1];
if (existing !== undefined) return existing || undefined;
resolutions ??= new Array(resuableCacheResolutions!.cache.resolutions.length);
Expand All @@ -2134,8 +2120,8 @@ namespace ts {
resolution.resolvedModule?.resolvedFileName || resolution.resolvedTypeReferenceDirective!.resolvedFileName
);
let affectingLocations: string[] | undefined;
if (fileExists(host, resolvedFileName) && every(resolution.affectingLocations, fileId => {
const file = toAffectingFileLocation(host, fileId);
if (fileExists(resolvedFileName) && every(resolution.affectingLocations, fileId => {
const file = toAffectingFileLocation(fileId);
if (file) (affectingLocations ??= []).push(file);
return !!file;
})) {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/builderPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace ts {
* Returns current program that could be undefined if the program was released, or cached build info program (currently module and type ref cache)
*/
/*@internal*/
getProgramOrOldBuildInfoProgramUndefined(): Program | OldBuildInfoProgram | undefined;
getProgramOrOldBuildInfoProgramUndefined(): Program | OldBuildInfoProgramConstructor | undefined;
/**
* Releases reference to the program, making all the other operations that need program to fail.
*/
Expand Down
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
Loading

0 comments on commit 890b6f2

Please sign in to comment.