Skip to content

Commit dfa4bc0

Browse files
committed
Use empty object for invalid package json contents instead of undefined
Fixes #34726
1 parent ba5e86f commit dfa4bc0

File tree

3 files changed

+82
-13
lines changed

3 files changed

+82
-13
lines changed

src/services/utilities.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,22 +2218,22 @@ namespace ts {
22182218
type PackageJsonRaw = Record<typeof dependencyKeys[number], Record<string, string> | undefined>;
22192219
const dependencyKeys = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"] as const;
22202220
const stringContent = host.readFile(fileName);
2221-
const content = stringContent && tryParseJson(stringContent) as PackageJsonRaw;
2222-
if (!content) {
2223-
return undefined;
2224-
}
2221+
if (!stringContent) return undefined;
22252222

2223+
const content = tryParseJson(stringContent) as PackageJsonRaw;
22262224
const info: Pick<PackageJsonInfo, typeof dependencyKeys[number]> = {};
2227-
for (const key of dependencyKeys) {
2228-
const dependencies = content[key];
2229-
if (!dependencies) {
2230-
continue;
2231-
}
2232-
const dependencyMap = createMap<string>();
2233-
for (const packageName in dependencies) {
2234-
dependencyMap.set(packageName, dependencies[packageName]);
2225+
if (content) {
2226+
for (const key of dependencyKeys) {
2227+
const dependencies = content[key];
2228+
if (!dependencies) {
2229+
continue;
2230+
}
2231+
const dependencyMap = createMap<string>();
2232+
for (const packageName in dependencies) {
2233+
dependencyMap.set(packageName, dependencies[packageName]);
2234+
}
2235+
info[key] = dependencyMap;
22352236
}
2236-
info[key] = dependencyMap;
22372237
}
22382238

22392239
const dependencyGroups = [

src/testRunner/unittests/tsserver/packageJsonInfo.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ namespace ts.projectSystem {
7171
assert.lengthOf(project.getPackageJsonsVisibleToFile("/a.ts" as Path), 1);
7272
assert.lengthOf(project.getPackageJsonsVisibleToFile("/src/b.ts" as Path), 2);
7373
});
74+
75+
it("handles errors in json parsing of package.json", () => {
76+
const packageJsonContent = `{ "mod" }`;
77+
const { project } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]);
78+
project.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as Path);
79+
const packageJsonInfo = project.packageJsonCache.getInDirectory("/" as Path)!;
80+
assert.isObject(packageJsonInfo);
81+
assert.isUndefined(packageJsonInfo.dependencies);
82+
assert.isUndefined(packageJsonInfo.devDependencies);
83+
assert.isUndefined(packageJsonInfo.peerDependencies);
84+
assert.isUndefined(packageJsonInfo.optionalDependencies);
85+
});
7486
});
7587

7688
function setup(files: readonly File[] = [tsConfig, packageJson]) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/// <reference path="../fourslash.ts" />
2+
3+
// @Filename: /jsconfig.json
4+
////{
5+
//// "compilerOptions": {
6+
//// "module": "commonjs",
7+
//// },
8+
////}
9+
10+
// @Filename: /node_modules/@types/node/index.d.ts
11+
////declare module 'fs' {
12+
//// export function readFile(): void;
13+
////}
14+
////declare module 'util' {
15+
//// export function promisify(): void;
16+
////}
17+
18+
// @Filename: /package.json
19+
////{ "mod" }
20+
21+
// @Filename: /a.js
22+
////
23+
////readF/**/
24+
25+
verifyExcludes("readFile");
26+
edit.replaceLine(0, "import { promisify } from 'util';");
27+
verifyIncludes("readFile");
28+
edit.deleteLine(0);
29+
verifyExcludes("readFile");
30+
31+
function verifyIncludes(name: string) {
32+
goTo.marker("");
33+
verify.completions({
34+
includes: {
35+
name,
36+
source: "fs",
37+
hasAction: true,
38+
sortText: completion.SortText.AutoImportSuggestions,
39+
},
40+
preferences: {
41+
includeCompletionsForModuleExports: true,
42+
includeInsertTextCompletions: true,
43+
},
44+
});
45+
}
46+
47+
function verifyExcludes(name: string) {
48+
goTo.marker("");
49+
verify.completions({
50+
excludes: name,
51+
preferences: {
52+
includeCompletionsForModuleExports: true,
53+
includeInsertTextCompletions: true,
54+
},
55+
});
56+
}
57+

0 commit comments

Comments
 (0)