Don't crash when a JS file appears in an inferred context

This commit is contained in:
Ryan Cavanaugh 2017-08-29 13:29:56 -07:00
parent 78524c1b90
commit 0e2d399c49
3 changed files with 35 additions and 15 deletions

View file

@ -1774,6 +1774,28 @@ namespace ts.projectSystem {
checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path, file3.path]);
});
it("regression test for crash in acquireOrUpdateDocument", () => {
const tsFile = {
fileName: "/a/b/file1.ts",
path: "/a/b/file1.ts",
content: ""
};
const jsFile = {
path: "/a/b/file1.js",
content: "var x = 10;",
fileName: "/a/b/file1.js",
scriptKind: "JS" as "JS"
};
const host = createServerHost([]);
const projectService = createProjectService(host);
projectService.applyChangesInOpenFiles([tsFile], [], []);
const projs = projectService.synchronizeProjectList([]);
projectService.findProject(projs[0].info.projectName).getLanguageService().getNavigationBarItems(tsFile.fileName);
projectService.synchronizeProjectList([projs[0].info]);
projectService.applyChangesInOpenFiles([jsFile], [], []);
});
it("config file is deleted", () => {
const file1 = {
path: "/a/b/f1.ts",
@ -1874,7 +1896,7 @@ namespace ts.projectSystem {
// Open HTML file
projectService.applyChangesInOpenFiles(
/*openFiles*/ [{ fileName: file2.path, hasMixedContent: true, scriptKind: ScriptKind.JS, content: `var hello = "hello";` }],
/*openFiles*/[{ fileName: file2.path, hasMixedContent: true, scriptKind: ScriptKind.JS, content: `var hello = "hello";` }],
/*changedFiles*/ undefined,
/*closedFiles*/ undefined);
@ -1891,7 +1913,7 @@ namespace ts.projectSystem {
projectService.applyChangesInOpenFiles(
/*openFiles*/ undefined,
/*changedFiles*/ undefined,
/*closedFiles*/ [file2.path]);
/*closedFiles*/[file2.path]);
// HTML file is still included in project
checkNumberOfProjects(projectService, { configuredProjects: 1 });
@ -3322,7 +3344,7 @@ namespace ts.projectSystem {
const error1Result = <protocol.Diagnostic[]>session.executeCommand(dTsFile1GetErrRequest).response;
assert.isTrue(error1Result.length === 0);
const dTsFile2GetErrRequest = makeSessionRequest<protocol.SemanticDiagnosticsSyncRequestArgs>(
const dTsFile2GetErrRequest = makeSessionRequest<protocol.SemanticDiagnosticsSyncRequestArgs>(
CommandNames.SemanticDiagnosticsSync,
{ file: dTsFile2.path }
);

View file

@ -1648,7 +1648,7 @@ namespace ts.server {
if (openFiles) {
for (const file of openFiles) {
const scriptInfo = this.getScriptInfo(file.fileName);
Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen());
Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen(), "Script should not exist and not be open already");
const normalizedPath = scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName);
this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent);
}

View file

@ -173,14 +173,12 @@ namespace ts {
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true);
let entry = bucket.get(path);
if (!entry) {
Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
// Have never seen this file with these settings. Create a new source file for it.
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind);
entry = {
sourceFile,
languageServiceRefCount: 0,
languageServiceRefCount: 1,
owners: []
};
bucket.set(path, entry);
@ -193,15 +191,15 @@ namespace ts {
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
}
}
// If we're acquiring, then this is the first time this LS is asking for this document.
// Increase our ref count so we know there's another LS using the document. If we're
// not acquiring, then that means the LS is 'updating' the file instead, and that means
// it has already acquired the document previously. As such, we do not need to increase
// the ref count.
if (acquiring) {
entry.languageServiceRefCount++;
// If we're acquiring, then this is the first time this LS is asking for this document.
// Increase our ref count so we know there's another LS using the document. If we're
// not acquiring, then that means the LS is 'updating' the file instead, and that means
// it has already acquired the document previously. As such, we do not need to increase
// the ref count.
if (acquiring) {
entry.languageServiceRefCount++;
}
}
return entry.sourceFile;