Skip to content

Commit ae04ec4

Browse files
committed
fix(41736): tsserver should not crash if external file does not exist
If a file does not exist, `projectService.getOrCreateScriptInfoNotOpenedByClient()` will return `undefined`, but tsserver does not handle this case. Fix #41736
1 parent 1bd8e38 commit ae04ec4

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/server/project.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,8 +1188,8 @@ namespace ts.server {
11881188
// by the host for files in the program when the program is retrieved above but
11891189
// the program doesn't contain external files so this must be done explicitly.
11901190
inserted => {
1191-
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost)!;
1192-
scriptInfo.attachToProject(this);
1191+
const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost);
1192+
scriptInfo?.attachToProject(this);
11931193
},
11941194
removed => this.detachScriptInfoFromProject(removed)
11951195
);

src/testRunner/unittests/tsserver/externalProjects.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,5 +898,44 @@ namespace ts.projectSystem {
898898
const jsConfigProject = service.configuredProjects.get(jsConfig.path.toLowerCase())!;
899899
checkProjectActualFiles(jsConfigProject, [jsConfig.path, jsFilePath, libFile.path]);
900900
});
901+
902+
it("does not crash if external file does not exist", () => {
903+
const f1 = {
904+
path: "/a/file1.ts",
905+
content: "let x = [1, 2];",
906+
};
907+
const p1 = {
908+
projectFileName: "/a/proj1.csproj",
909+
rootFiles: [toExternalFile(f1.path)],
910+
options: {},
911+
};
912+
913+
const host = createServerHost([f1]);
914+
host.require = (_initialPath, moduleName) => {
915+
assert.equal(moduleName, "myplugin");
916+
return {
917+
module: () => ({
918+
create(info: server.PluginCreateInfo) {
919+
return Harness.LanguageService.makeDefaultProxy(info);
920+
},
921+
getExternalFiles() {
922+
return ["/does/not/exist"];
923+
},
924+
}),
925+
error: undefined,
926+
};
927+
};
928+
const session = createSession(host, {
929+
globalPlugins: ["myplugin"],
930+
});
931+
const projectService = session.getProjectService();
932+
// When the external project is opened, the graph will be updated,
933+
// and in the process getExternalFiles() above will be called.
934+
// Since the external file does not exist, there will not be a script
935+
// info for it. If tsserver does not handle this case, the following
936+
// method call will crash.
937+
projectService.openExternalProject(p1);
938+
checkNumberOfProjects(projectService, { externalProjects: 1 });
939+
});
901940
});
902941
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy