Handle already released source files that dont match scriptKind (#54401)

This commit is contained in:
Sheetal Nandi
2023-05-25 15:58:22 -07:00
committed by GitHub
parent da686774dc
commit c64a378ef9
3 changed files with 249 additions and 1 deletions

View File

@@ -1713,9 +1713,13 @@ export function createLanguageService(
// calculate this early so it's not undefined if downleveled to a var (or, if emitted
// as a const variable without downleveling, doesn't crash).
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
let releasedScriptKinds: Set<Path> | undefined = new Set();
// If the program is already up-to-date, we can reuse it
if (isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileName => compilerHost!.fileExists(fileName), hasInvalidatedResolutions, hasInvalidatedLibResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) {
compilerHost = undefined;
parsedCommandLines = undefined;
releasedScriptKinds = undefined;
return;
}
@@ -1738,6 +1742,7 @@ export function createLanguageService(
// After this point, the cache needs to be cleared to allow all collected snapshots to be released
compilerHost = undefined;
parsedCommandLines = undefined;
releasedScriptKinds = undefined;
// We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above,
// Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during
@@ -1841,12 +1846,13 @@ export function createLanguageService(
// We do not support the scenario where a host can modify a registered
// file's script kind, i.e. in one project some file is treated as ".ts"
// and in another as ".js"
if (scriptKind === oldSourceFile.scriptKind) {
if (scriptKind === oldSourceFile.scriptKind || releasedScriptKinds!.has(oldSourceFile.resolvedPath)) {
return documentRegistry.updateDocumentWithKey(fileName, path, host, documentRegistryBucketKey, scriptSnapshot, scriptVersion, scriptKind, languageVersionOrOptions);
}
else {
// Release old source file and fall through to aquire new file with new script kind
documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, documentRegistry.getKeyForCompilationSettings(program.getCompilerOptions()), oldSourceFile.scriptKind, oldSourceFile.impliedNodeFormat);
releasedScriptKinds!.add(oldSourceFile.resolvedPath);
}
}