Skip to content

Commit fdcd2ee

Browse files
committed
Preserve snapshot identity across no-op updates
1 parent f59326d commit fdcd2ee

4 files changed

Lines changed: 41 additions & 0 deletions

File tree

‎packages/typescript/src/api/async/api.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
407407
snapshot: baseSnapshot.id,
408408
changes: toCreateSnapshotRequest(params),
409409
});
410+
if (data.snapshot === baseSnapshot.id) {
411+
return baseSnapshot;
412+
}
410413
this.sourceFileCache.retainForSnapshot(data.snapshot, baseSnapshot.id, data.changes);
411414
const snapshot = new Snapshot(
412415
data,

‎packages/typescript/src/api/sync/api.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,9 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
639639
snapshot: baseSnapshot.id,
640640
changes: toCreateSnapshotRequest(params),
641641
});
642+
if (data.snapshot === baseSnapshot.id) {
643+
return baseSnapshot;
644+
}
642645
owner.sourceFileCache.retainForSnapshot(data.snapshot, baseSnapshot.id, data.changes);
643646
const snapshot = new Snapshot(
644647
data,
@@ -666,6 +669,9 @@ export class API<FromLSP extends boolean = false> implements FormatDiagnosticsHo
666669
snapshot: baseSnapshot.id,
667670
changes: toCreateSnapshotRequest(params),
668671
});
672+
if (data.snapshot === baseSnapshot.id) {
673+
return baseSnapshot;
674+
}
669675
owner.sourceFileCache.retainForSnapshot(data.snapshot, baseSnapshot.id, data.changes);
670676
const snapshot = new Snapshot(
671677
data,

‎packages/typescript/test/async/api.test.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,22 @@ describe("API", () => {
400400
assert.equal("openedFiles" in empty.operation, false);
401401
});
402402

403+
test("snapshot.update preserves identity when the server returns the same snapshot", async () => {
404+
await using api = spawnAPI();
405+
const snapshot = await api.createSnapshot();
406+
const client = (api as unknown as {
407+
client: { apiRequest(method: string, params: unknown): Promise<unknown>; };
408+
}).client;
409+
const apiRequest = client.apiRequest.bind(client);
410+
client.apiRequest = async (method, params) => {
411+
const response = await apiRequest(method, params);
412+
if (method !== "updateSnapshot" || typeof response !== "object" || response === null) return response;
413+
return { ...response, snapshot: snapshot.id };
414+
};
415+
416+
assert.strictEqual(await snapshot.update({}), snapshot);
417+
});
418+
403419
test("snapshot.update reconfigures a synthetic program", async () => {
404420
await using api = spawnAPI({
405421
"/src/a.ts": `export const a = 1;`,

‎packages/typescript/test/sync/api.test.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,22 @@ describe("API", () => {
389389
assert.equal("openedFiles" in empty.operation, false);
390390
});
391391

392+
test("snapshot.update preserves identity when the server returns the same snapshot", () => {
393+
using api = spawnAPI();
394+
const snapshot = api.createSnapshot();
395+
const client = (api as unknown as {
396+
client: { apiRequest(method: string, params: unknown): unknown; };
397+
}).client;
398+
const apiRequest = client.apiRequest.bind(client);
399+
client.apiRequest = (method, params) => {
400+
const response = apiRequest(method, params);
401+
if (method !== "updateSnapshot" || typeof response !== "object" || response === null) return response;
402+
return { ...response, snapshot: snapshot.id };
403+
};
404+
405+
assert.strictEqual(snapshot.update({}), snapshot);
406+
});
407+
392408
test("snapshot.update reconfigures a synthetic program", () => {
393409
using api = spawnAPI({
394410
"/src/a.ts": `export const a = 1;`,

0 commit comments

Comments
 (0)