Skip to content

Commit 9e46573

Browse files
code-asherAkash Satheesan
authored andcommitted
Restore async storage write patch
This issue can be reliably replicated by creating an extension with the following code: await context.globalState.update("key", "value") vscode.commands.executeCommand("workbench.action.reloadWindow"); If you do this the global state will never update. This can be seen by logging with a notification or browsing the global state manually. This is probably a bug with upstream because without this patch it is impossible to wait for the actual storage write. This actually required more patching than we previously had; I don't think it was working in 1.56 either.
1 parent 47d8866 commit 9e46573

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

lib/vscode/src/vs/platform/storage/common/storage.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,10 @@ export interface IStorageService {
105105
*
106106
* @param target allows to define the target of the storage operation
107107
* to either the current machine or user.
108+
*
109+
* NOTE@coder: Add a promise so extensions can await storage writes.
108110
*/
109-
store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): void;
111+
store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): Promise<void> | void;
110112

111113
/**
112114
* Delete an element stored under the provided key from storage.
@@ -333,46 +335,49 @@ export abstract class AbstractStorageService extends Disposable implements IStor
333335
return this.getStorage(scope)?.getNumber(key, fallbackValue);
334336
}
335337

336-
store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): void {
338+
// NOTE@coder: Make a promise so extensions can await storage writes.
339+
store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): Promise<void> | void {
337340

338341
// We remove the key for undefined/null values
339342
if (isUndefinedOrNull(value)) {
340343
this.remove(key, scope);
341-
return;
344+
return Promise.resolve();
342345
}
343346

344347
// Update our datastructures but send events only after
345-
this.withPausedEmitters(() => {
348+
return this.withPausedEmitters(() => {
346349

347350
// Update key-target map
348351
this.updateKeyTarget(key, scope, target);
349352

350353
// Store actual value
351-
this.getStorage(scope)?.set(key, value);
354+
return this.getStorage(scope)?.set(key, value);
352355
});
353356
}
354357

355-
remove(key: string, scope: StorageScope): void {
358+
// NOTE@coder: Make a promise so extensions can await the storage write.
359+
remove(key: string, scope: StorageScope): Promise<void> | void {
356360

357361
// Update our datastructures but send events only after
358-
this.withPausedEmitters(() => {
362+
return this.withPausedEmitters(() => {
359363

360364
// Update key-target map
361365
this.updateKeyTarget(key, scope, undefined);
362366

363367
// Remove actual key
364-
this.getStorage(scope)?.delete(key);
368+
return this.getStorage(scope)?.delete(key);
365369
});
366370
}
367371

368-
private withPausedEmitters(fn: Function): void {
372+
// NOTE@coder: Return the function's return so extensions can await the storage write.
373+
private withPausedEmitters<T>(fn: () => T): T {
369374

370375
// Pause emitters
371376
this._onDidChangeValue.pause();
372377
this._onDidChangeTarget.pause();
373378

374379
try {
375-
fn();
380+
return fn();
376381
} finally {
377382

378383
// Resume emitters

lib/vscode/src/vs/workbench/api/browser/mainThreadStorage.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ export class MainThreadStorage implements MainThreadStorageShape {
6262
return JSON.parse(jsonValue);
6363
}
6464

65-
$setValue(shared: boolean, key: string, value: object): Promise<void> {
65+
async $setValue(shared: boolean, key: string, value: object): Promise<void> {
6666
let jsonValue: string;
6767
try {
6868
jsonValue = JSON.stringify(value);
6969
// Extension state is synced separately through extensions
70-
this._storageService.store(key, jsonValue, shared ? StorageScope.GLOBAL : StorageScope.WORKSPACE, StorageTarget.MACHINE);
70+
// NOTE@coder: Wait for the actual storage write.
71+
await this._storageService.store(key, jsonValue, shared ? StorageScope.GLOBAL : StorageScope.WORKSPACE, StorageTarget.MACHINE);
7172
} catch (err) {
7273
return Promise.reject(err);
7374
}

0 commit comments

Comments
 (0)