Skip to content

Commit 24dd222

Browse files
authored
SCM - all calls from extHostSCM to mainThreadSCM should use a sequencer to ensure that the source control object is created (microsoft#213792)
1 parent 60c04ea commit 24dd222

File tree

1 file changed

+27
-25
lines changed

1 file changed

+27
-25
lines changed

src/vs/workbench/api/common/extHostSCM.ts

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
99
import { Event, Emitter } from 'vs/base/common/event';
1010
import { debounce } from 'vs/base/common/decorators';
1111
import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
12-
import { asPromise } from 'vs/base/common/async';
12+
import { asPromise, Sequencer } from 'vs/base/common/async';
1313
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
1414
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto, MainThreadTelemetryShape, SCMGroupFeatures, SCMHistoryItemDto, SCMHistoryItemChangeDto } from './extHost.protocol';
1515
import { sortedDiff, equals } from 'vs/base/common/arrays';
@@ -259,7 +259,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
259259

260260
set value(value: string) {
261261
value = value ?? '';
262-
this.#proxy.$setInputBoxValue(this._sourceControlHandle, value);
262+
this._sequencer.queue(async () => this.#proxy.$setInputBoxValue(this._sourceControlHandle, value));
263263
this.updateValue(value);
264264
}
265265

@@ -276,7 +276,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
276276
}
277277

278278
set placeholder(placeholder: string) {
279-
this.#proxy.$setInputBoxPlaceholder(this._sourceControlHandle, placeholder);
279+
this._sequencer.queue(async () => this.#proxy.$setInputBoxPlaceholder(this._sourceControlHandle, placeholder));
280280
this._placeholder = placeholder;
281281
}
282282

@@ -296,7 +296,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
296296
}
297297

298298
this._validateInput = fn;
299-
this.#proxy.$setValidationProviderIsEnabled(this._sourceControlHandle, !!fn);
299+
this._sequencer.queue(async () => this.#proxy.$setValidationProviderIsEnabled(this._sourceControlHandle, !!fn));
300300
}
301301

302302
private _enabled: boolean = true;
@@ -313,7 +313,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
313313
}
314314

315315
this._enabled = enabled;
316-
this.#proxy.$setInputBoxEnablement(this._sourceControlHandle, enabled);
316+
this._sequencer.queue(async () => this.#proxy.$setInputBoxEnablement(this._sourceControlHandle, enabled));
317317
}
318318

319319
private _visible: boolean = true;
@@ -330,7 +330,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
330330
}
331331

332332
this._visible = visible;
333-
this.#proxy.$setInputBoxVisibility(this._sourceControlHandle, visible);
333+
this._sequencer.queue(async () => this.#proxy.$setInputBoxVisibility(this._sourceControlHandle, visible));
334334
}
335335

336336
get document(): vscode.TextDocument {
@@ -339,15 +339,15 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
339339
return this.#extHostDocuments.getDocument(this._documentUri);
340340
}
341341

342-
constructor(private _extension: IExtensionDescription, _extHostDocuments: ExtHostDocuments, proxy: MainThreadSCMShape, private _sourceControlHandle: number, private _documentUri: URI) {
342+
constructor(private _extension: IExtensionDescription, _extHostDocuments: ExtHostDocuments, proxy: MainThreadSCMShape, private _sequencer: Sequencer, private _sourceControlHandle: number, private _documentUri: URI) {
343343
this.#extHostDocuments = _extHostDocuments;
344344
this.#proxy = proxy;
345345
}
346346

347347
showValidationMessage(message: string | vscode.MarkdownString, type: vscode.SourceControlInputBoxValidationType) {
348348
checkProposedApiEnabled(this._extension, 'scmValidation');
349349

350-
this.#proxy.$showValidationMessage(this._sourceControlHandle, message, type as any);
350+
this._sequencer.queue(async () => this.#proxy.$showValidationMessage(this._sourceControlHandle, message, type as any));
351351
}
352352

353353
$onInputBoxValueChange(value: string): void {
@@ -386,14 +386,14 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
386386
get label(): string { return this._label; }
387387
set label(label: string) {
388388
this._label = label;
389-
this._proxy.$updateGroupLabel(this._sourceControlHandle, this.handle, label);
389+
this._sequencer.queue(async () => this._proxy.$updateGroupLabel(this._sourceControlHandle, this.handle, label));
390390
}
391391

392392
private _hideWhenEmpty: boolean | undefined = undefined;
393393
get hideWhenEmpty(): boolean | undefined { return this._hideWhenEmpty; }
394394
set hideWhenEmpty(hideWhenEmpty: boolean | undefined) {
395395
this._hideWhenEmpty = hideWhenEmpty;
396-
this._proxy.$updateGroup(this._sourceControlHandle, this.handle, this.features);
396+
this._sequencer.queue(async () => this._proxy.$updateGroup(this._sourceControlHandle, this.handle, this.features));
397397
}
398398

399399
get features(): SCMGroupFeatures {
@@ -413,6 +413,7 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
413413
constructor(
414414
private _proxy: MainThreadSCMShape,
415415
private _commands: ExtHostCommands,
416+
private _sequencer: Sequencer,
416417
private _sourceControlHandle: number,
417418
private _id: string,
418419
private _label: string,
@@ -511,6 +512,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
511512

512513
#proxy: MainThreadSCMShape;
513514

515+
private readonly _sequencer = new Sequencer();
514516
private _groups: Map<GroupHandle, ExtHostSourceControlResourceGroup> = new Map<GroupHandle, ExtHostSourceControlResourceGroup>();
515517

516518
get id(): string {
@@ -540,7 +542,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
540542
}
541543

542544
this._count = count;
543-
this.#proxy.$updateSourceControl(this.handle, { count });
545+
this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { count }));
544546
}
545547

546548
private _quickDiffProvider: vscode.QuickDiffProvider | undefined = undefined;
@@ -555,7 +557,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
555557
if (isProposedApiEnabled(this._extension, 'quickDiffProvider')) {
556558
quickDiffLabel = quickDiffProvider?.label;
557559
}
558-
this.#proxy.$updateSourceControl(this.handle, { hasQuickDiffProvider: !!quickDiffProvider, quickDiffLabel });
560+
this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { hasQuickDiffProvider: !!quickDiffProvider, quickDiffLabel }));
559561
}
560562

561563
private _historyProvider: vscode.SourceControlHistoryProvider | undefined;
@@ -573,12 +575,12 @@ class ExtHostSourceControl implements vscode.SourceControl {
573575
this._historyProvider = historyProvider;
574576
this._historyProviderDisposable.value = new DisposableStore();
575577

576-
this.#proxy.$updateSourceControl(this.handle, { hasHistoryProvider: !!historyProvider });
578+
this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { hasHistoryProvider: !!historyProvider }));
577579

578580
if (historyProvider) {
579581
this._historyProviderDisposable.value.add(historyProvider.onDidChangeCurrentHistoryItemGroup(() => {
580582
this._historyProviderCurrentHistoryItemGroup = historyProvider?.currentHistoryItemGroup;
581-
this.#proxy.$onDidChangeHistoryProviderCurrentHistoryItemGroup(this.handle, this._historyProviderCurrentHistoryItemGroup);
583+
this._sequencer.queue(async () => this.#proxy.$onDidChangeHistoryProviderCurrentHistoryItemGroup(this.handle, this._historyProviderCurrentHistoryItemGroup));
582584
}));
583585
}
584586
}
@@ -595,7 +597,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
595597
}
596598

597599
this._commitTemplate = commitTemplate;
598-
this.#proxy.$updateSourceControl(this.handle, { commitTemplate });
600+
this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { commitTemplate }));
599601
}
600602

601603
private readonly _acceptInputDisposables = new MutableDisposable<DisposableStore>();
@@ -611,7 +613,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
611613
this._acceptInputCommand = acceptInputCommand;
612614

613615
const internal = this._commands.converter.toInternal(acceptInputCommand, this._acceptInputDisposables.value);
614-
this.#proxy.$updateSourceControl(this.handle, { acceptInputCommand: internal });
616+
this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { acceptInputCommand: internal }));
615617
}
616618

617619
private readonly _actionButtonDisposables = new MutableDisposable<DisposableStore>();
@@ -635,7 +637,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
635637
description: actionButton.description,
636638
enabled: actionButton.enabled
637639
} : undefined;
638-
this.#proxy.$updateSourceControl(this.handle, { actionButton: internal ?? null });
640+
this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { actionButton: internal ?? null }));
639641
}
640642

641643

@@ -656,7 +658,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
656658
this._statusBarCommands = statusBarCommands;
657659

658660
const internal = (statusBarCommands || []).map(c => this._commands.converter.toInternal(c, this._statusBarDisposables.value!)) as ICommandDto[];
659-
this.#proxy.$updateSourceControl(this.handle, { statusBarCommands: internal });
661+
this._sequencer.queue(async () => this.#proxy.$updateSourceControl(this.handle, { statusBarCommands: internal }));
660662
}
661663

662664
private _selected: boolean = false;
@@ -687,16 +689,16 @@ class ExtHostSourceControl implements vscode.SourceControl {
687689
query: _rootUri ? `rootUri=${encodeURIComponent(_rootUri.toString())}` : undefined
688690
});
689691

690-
this._inputBox = new ExtHostSCMInputBox(_extension, _extHostDocuments, this.#proxy, this.handle, inputBoxDocumentUri);
691-
this.#proxy.$registerSourceControl(this.handle, _id, _label, _rootUri, inputBoxDocumentUri);
692+
this._sequencer.queue(() => this.#proxy.$registerSourceControl(this.handle, _id, _label, _rootUri, inputBoxDocumentUri));
693+
this._inputBox = new ExtHostSCMInputBox(_extension, _extHostDocuments, this.#proxy, this._sequencer, this.handle, inputBoxDocumentUri);
692694
}
693695

694696
private createdResourceGroups = new Map<ExtHostSourceControlResourceGroup, IDisposable>();
695697
private updatedResourceGroups = new Set<ExtHostSourceControlResourceGroup>();
696698

697699
createResourceGroup(id: string, label: string, options?: { multiDiffEditorEnableViewChanges?: boolean }): ExtHostSourceControlResourceGroup {
698700
const multiDiffEditorEnableViewChanges = isProposedApiEnabled(this._extension, 'scmMultiDiffEditor') && options?.multiDiffEditorEnableViewChanges === true;
699-
const group = new ExtHostSourceControlResourceGroup(this.#proxy, this._commands, this.handle, id, label, multiDiffEditorEnableViewChanges, this._extension);
701+
const group = new ExtHostSourceControlResourceGroup(this.#proxy, this._commands, this._sequencer, this.handle, id, label, multiDiffEditorEnableViewChanges, this._extension);
700702
const disposable = Event.once(group.onDidDispose)(() => this.createdResourceGroups.delete(group));
701703
this.createdResourceGroups.set(group, disposable);
702704
this.eventuallyAddResourceGroups();
@@ -720,7 +722,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
720722
this.updatedResourceGroups.delete(group);
721723
updateListener.dispose();
722724
this._groups.delete(group.handle);
723-
this.#proxy.$unregisterGroup(this.handle, group.handle);
725+
this._sequencer.queue(async () => this.#proxy.$unregisterGroup(this.handle, group.handle));
724726
});
725727

726728
groups.push([group.handle, group.id, group.label, group.features, group.multiDiffEditorEnableViewChanges]);
@@ -734,7 +736,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
734736
this._groups.set(group.handle, group);
735737
}
736738

737-
this.#proxy.$registerGroups(this.handle, groups, splices);
739+
this._sequencer.queue(async () => this.#proxy.$registerGroups(this.handle, groups, splices));
738740
this.createdResourceGroups.clear();
739741
}
740742

@@ -753,7 +755,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
753755
});
754756

755757
if (splices.length > 0) {
756-
this.#proxy.$spliceResourceStates(this.handle, splices);
758+
this._sequencer.queue(async () => this.#proxy.$spliceResourceStates(this.handle, splices));
757759
}
758760

759761
this.updatedResourceGroups.clear();
@@ -774,7 +776,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
774776
this._statusBarDisposables.dispose();
775777

776778
this._groups.forEach(group => group.dispose());
777-
this.#proxy.$unregisterSourceControl(this.handle);
779+
this._sequencer.queue(async () => this.#proxy.$unregisterSourceControl(this.handle));
778780
}
779781
}
780782

0 commit comments

Comments
 (0)