Skip to content

Commit 6c5087f

Browse files
Andysandersn
Andy
authored andcommitted
Use SHA256 hash for project info telemetry (#24099)
* Use SHA256 hash for project info telemetry * Update API baselines
1 parent feeea64 commit 6c5087f

File tree

7 files changed

+26
-15
lines changed

7 files changed

+26
-15
lines changed

src/compiler/sys.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,10 +448,11 @@ namespace ts {
448448
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
449449
getModifiedTime?(path: string): Date;
450450
/**
451-
* This should be cryptographically secure.
452451
* A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
453452
*/
454453
createHash?(data: string): string;
454+
/** This must be cryptographically secure. Only implement this method using `crypto.createHash("sha256")`. */
455+
createSHA256Hash?(data: string): string;
455456
getMemoryUsage?(): number;
456457
exit(exitCode?: number): void;
457458
realpath?(path: string): string;
@@ -527,7 +528,7 @@ namespace ts {
527528
const _path = require("path");
528529
const _os = require("os");
529530
// crypto can be absent on reduced node installations
530-
let _crypto: any;
531+
let _crypto: typeof import("crypto");
531532
try {
532533
_crypto = require("crypto");
533534
}
@@ -590,6 +591,7 @@ namespace ts {
590591
readDirectory,
591592
getModifiedTime,
592593
createHash: _crypto ? createMD5HashUsingNativeCrypto : generateDjb2Hash,
594+
createSHA256Hash: _crypto ? createSHA256Hash : undefined,
593595
getMemoryUsage() {
594596
if (global.gc) {
595597
global.gc();
@@ -1072,11 +1074,17 @@ namespace ts {
10721074
return `${chars.reduce((prev, curr) => ((prev << 5) + prev) + curr, 5381)}`;
10731075
}
10741076

1075-
function createMD5HashUsingNativeCrypto(data: string) {
1077+
function createMD5HashUsingNativeCrypto(data: string): string {
10761078
const hash = _crypto.createHash("md5");
10771079
hash.update(data);
10781080
return hash.digest("hex");
10791081
}
1082+
1083+
function createSHA256Hash(data: string): string {
1084+
const hash = _crypto.createHash("sha256");
1085+
hash.update(data);
1086+
return hash.digest("hex");
1087+
}
10801088
}
10811089

10821090
function getChakraSystem(): System {

src/harness/unittests/telemetry.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ namespace ts.projectSystem {
5959

6060
// TODO: Apparently compilerOptions is mutated, so have to repeat it here!
6161
et.assertProjectInfoTelemetryEvent({
62-
projectId: Harness.mockHash("/hunter2/foo.csproj"),
6362
compilerOptions: { strict: true },
6463
compileOnSave: true,
6564
// These properties can't be present for an external project, so they are undefined instead of false.
@@ -69,7 +68,7 @@ namespace ts.projectSystem {
6968
exclude: undefined,
7069
configFileName: "other",
7170
projectType: "external",
72-
});
71+
}, "/hunter2/foo.csproj");
7372

7473
// Also test that opening an external project only sends an event once.
7574

@@ -202,7 +201,6 @@ namespace ts.projectSystem {
202201
const et = new TestServerEventManager([jsconfig, file]);
203202
et.service.openClientFile(file.path);
204203
et.assertProjectInfoTelemetryEvent({
205-
projectId: Harness.mockHash("/jsconfig.json"),
206204
fileStats: fileStats({ js: 1 }),
207205
compilerOptions: autoJsCompilerOptions,
208206
typeAcquisition: {
@@ -211,7 +209,7 @@ namespace ts.projectSystem {
211209
exclude: false,
212210
},
213211
configFileName: "jsconfig.json",
214-
});
212+
}, "/jsconfig.json");
215213
});
216214

217215
it("detects whether language service was disabled", () => {
@@ -222,7 +220,6 @@ namespace ts.projectSystem {
222220
et.service.openClientFile(file.path);
223221
et.getEvent<server.ProjectLanguageServiceStateEvent>(server.ProjectLanguageServiceStateEvent);
224222
et.assertProjectInfoTelemetryEvent({
225-
projectId: Harness.mockHash("/jsconfig.json"),
226223
fileStats: fileStats({ js: 1 }),
227224
compilerOptions: autoJsCompilerOptions,
228225
configFileName: "jsconfig.json",
@@ -232,7 +229,7 @@ namespace ts.projectSystem {
232229
exclude: false,
233230
},
234231
languageServiceEnabled: false,
235-
});
232+
}, "/jsconfig.json");
236233
});
237234

238235
describe("open files telemetry", () => {

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,9 @@ namespace ts.projectSystem {
214214
assert.equal(eventData.triggerFile, triggerFile);
215215
}
216216

217-
assertProjectInfoTelemetryEvent(partial: Partial<server.ProjectInfoTelemetryEventData>, configFile?: string): void {
217+
assertProjectInfoTelemetryEvent(partial: Partial<server.ProjectInfoTelemetryEventData>, configFile = "/tsconfig.json"): void {
218218
assert.deepEqual<server.ProjectInfoTelemetryEventData>(this.getEvent<server.ProjectInfoTelemetryEvent>(server.ProjectInfoTelemetryEvent), {
219-
projectId: Harness.mockHash(configFile || "/tsconfig.json"),
219+
projectId: sys.createSHA256Hash(configFile),
220220
fileStats: fileStats({ ts: 1 }),
221221
compilerOptions: {},
222222
extends: false,

src/harness/virtualFileSystemWithWatch.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,10 @@ interface Array<T> {}`
811811
return Harness.mockHash(s);
812812
}
813813

814+
createSHA256Hash(s: string): string {
815+
return sys.createSHA256Hash(s);
816+
}
817+
814818
watchFile(fileName: string, cb: FileWatcherCallback, pollingInterval: number) {
815819
if (this.dynamicPriorityWatchFile) {
816820
return this.dynamicPriorityWatchFile(fileName, cb, pollingInterval);

src/server/editorServices.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,12 +1429,12 @@ namespace ts.server {
14291429
}
14301430
this.seenProjects.set(projectKey, true);
14311431

1432-
if (!this.eventHandler) {
1432+
if (!this.eventHandler || !this.host.createSHA256Hash) {
14331433
return;
14341434
}
14351435

14361436
const data: ProjectInfoTelemetryEventData = {
1437-
projectId: this.host.createHash(projectKey),
1437+
projectId: this.host.createSHA256Hash(projectKey),
14381438
fileStats: countEachFileTypes(project.getScriptInfos()),
14391439
compilerOptions: convertCompilerOptionsForTelemetry(project.getCompilationSettings()),
14401440
typeAcquisition: convertTypeAcquisition(project.getTypeAcquisition()),

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2995,10 +2995,11 @@ declare namespace ts {
29952995
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
29962996
getModifiedTime?(path: string): Date;
29972997
/**
2998-
* This should be cryptographically secure.
29992998
* A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
30002999
*/
30013000
createHash?(data: string): string;
3001+
/** This must be cryptographically secure. Only implement this method using `crypto.createHash("sha256")`. */
3002+
createSHA256Hash?(data: string): string;
30023003
getMemoryUsage?(): number;
30033004
exit(exitCode?: number): void;
30043005
realpath?(path: string): string;

tests/baselines/reference/api/typescript.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2995,10 +2995,11 @@ declare namespace ts {
29952995
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
29962996
getModifiedTime?(path: string): Date;
29972997
/**
2998-
* This should be cryptographically secure.
29992998
* A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
30002999
*/
30013000
createHash?(data: string): string;
3001+
/** This must be cryptographically secure. Only implement this method using `crypto.createHash("sha256")`. */
3002+
createSHA256Hash?(data: string): string;
30023003
getMemoryUsage?(): number;
30033004
exit(exitCode?: number): void;
30043005
realpath?(path: string): string;

0 commit comments

Comments
 (0)