Skip to content

Commit 0e2d399

Browse files
committed
Don't crash when a JS file appears in an inferred context
1 parent 78524c1 commit 0e2d399

File tree

3 files changed

+35
-15
lines changed

3 files changed

+35
-15
lines changed

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,6 +1774,28 @@ namespace ts.projectSystem {
17741774
checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path, file3.path]);
17751775
});
17761776

1777+
it("regression test for crash in acquireOrUpdateDocument", () => {
1778+
const tsFile = {
1779+
fileName: "/a/b/file1.ts",
1780+
path: "/a/b/file1.ts",
1781+
content: ""
1782+
};
1783+
const jsFile = {
1784+
path: "/a/b/file1.js",
1785+
content: "var x = 10;",
1786+
fileName: "/a/b/file1.js",
1787+
scriptKind: "JS" as "JS"
1788+
};
1789+
1790+
const host = createServerHost([]);
1791+
const projectService = createProjectService(host);
1792+
projectService.applyChangesInOpenFiles([tsFile], [], []);
1793+
const projs = projectService.synchronizeProjectList([]);
1794+
projectService.findProject(projs[0].info.projectName).getLanguageService().getNavigationBarItems(tsFile.fileName);
1795+
projectService.synchronizeProjectList([projs[0].info]);
1796+
projectService.applyChangesInOpenFiles([jsFile], [], []);
1797+
});
1798+
17771799
it("config file is deleted", () => {
17781800
const file1 = {
17791801
path: "/a/b/f1.ts",
@@ -1874,7 +1896,7 @@ namespace ts.projectSystem {
18741896

18751897
// Open HTML file
18761898
projectService.applyChangesInOpenFiles(
1877-
/*openFiles*/ [{ fileName: file2.path, hasMixedContent: true, scriptKind: ScriptKind.JS, content: `var hello = "hello";` }],
1899+
/*openFiles*/[{ fileName: file2.path, hasMixedContent: true, scriptKind: ScriptKind.JS, content: `var hello = "hello";` }],
18781900
/*changedFiles*/ undefined,
18791901
/*closedFiles*/ undefined);
18801902

@@ -1891,7 +1913,7 @@ namespace ts.projectSystem {
18911913
projectService.applyChangesInOpenFiles(
18921914
/*openFiles*/ undefined,
18931915
/*changedFiles*/ undefined,
1894-
/*closedFiles*/ [file2.path]);
1916+
/*closedFiles*/[file2.path]);
18951917

18961918
// HTML file is still included in project
18971919
checkNumberOfProjects(projectService, { configuredProjects: 1 });
@@ -3322,7 +3344,7 @@ namespace ts.projectSystem {
33223344
const error1Result = <protocol.Diagnostic[]>session.executeCommand(dTsFile1GetErrRequest).response;
33233345
assert.isTrue(error1Result.length === 0);
33243346

3325-
const dTsFile2GetErrRequest = makeSessionRequest<protocol.SemanticDiagnosticsSyncRequestArgs>(
3347+
const dTsFile2GetErrRequest = makeSessionRequest<protocol.SemanticDiagnosticsSyncRequestArgs>(
33263348
CommandNames.SemanticDiagnosticsSync,
33273349
{ file: dTsFile2.path }
33283350
);

src/server/editorServices.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1648,7 +1648,7 @@ namespace ts.server {
16481648
if (openFiles) {
16491649
for (const file of openFiles) {
16501650
const scriptInfo = this.getScriptInfo(file.fileName);
1651-
Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen());
1651+
Debug.assert(!scriptInfo || !scriptInfo.isScriptOpen(), "Script should not exist and not be open already");
16521652
const normalizedPath = scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName);
16531653
this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent);
16541654
}

src/services/documentRegistry.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,12 @@ namespace ts {
173173
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true);
174174
let entry = bucket.get(path);
175175
if (!entry) {
176-
Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
177-
178176
// Have never seen this file with these settings. Create a new source file for it.
179177
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind);
180178

181179
entry = {
182180
sourceFile,
183-
languageServiceRefCount: 0,
181+
languageServiceRefCount: 1,
184182
owners: []
185183
};
186184
bucket.set(path, entry);
@@ -193,15 +191,15 @@ namespace ts {
193191
entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version,
194192
scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
195193
}
196-
}
197194

198-
// If we're acquiring, then this is the first time this LS is asking for this document.
199-
// Increase our ref count so we know there's another LS using the document. If we're
200-
// not acquiring, then that means the LS is 'updating' the file instead, and that means
201-
// it has already acquired the document previously. As such, we do not need to increase
202-
// the ref count.
203-
if (acquiring) {
204-
entry.languageServiceRefCount++;
195+
// If we're acquiring, then this is the first time this LS is asking for this document.
196+
// Increase our ref count so we know there's another LS using the document. If we're
197+
// not acquiring, then that means the LS is 'updating' the file instead, and that means
198+
// it has already acquired the document previously. As such, we do not need to increase
199+
// the ref count.
200+
if (acquiring) {
201+
entry.languageServiceRefCount++;
202+
}
205203
}
206204

207205
return entry.sourceFile;

0 commit comments

Comments
 (0)