Skip to content

Commit 0621245

Browse files
author
Matt Bierner
committed
Make sure we dispose of every custom editors input individually
Fixes microsoft#88229 There should a 1:1 mapping between VS Code's custom editors and custom editors (specifically the webviews) that extensions know about. This was previously not true as a single `CustomEditorInput` could end up being shared between multiple editor groups. With this change, we always create a copy of the custom editor input during split, and then add a listener for `onDidCloseEditor` so that we can make sure we get rid of the unique inputs (and notify extensions of this)
1 parent 5d49873 commit 0621245

3 files changed

Lines changed: 37 additions & 10 deletions

File tree

src/vs/workbench/common/editor.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,8 +552,10 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
552552
}
553553

554554
dispose(): void {
555-
this.disposed = true;
556-
this._onDispose.fire();
555+
if (!this.disposed) {
556+
this.disposed = true;
557+
this._onDispose.fire();
558+
}
557559

558560
super.dispose();
559561
}

src/vs/workbench/contrib/customEditor/browser/customEditors.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { coalesce } from 'vs/base/common/arrays';
7+
import { Emitter } from 'vs/base/common/event';
78
import { Lazy } from 'vs/base/common/lazy';
89
import { Disposable } from 'vs/base/common/lifecycle';
910
import { basename, isEqual } from 'vs/base/common/resources';
@@ -15,9 +16,11 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
1516
import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
1617
import { FileOperation, IFileService } from 'vs/platform/files/common/files';
1718
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
19+
import { ILabelService } from 'vs/platform/label/common/label';
1820
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
1921
import * as colorRegistry from 'vs/platform/theme/common/colorRegistry';
2022
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
23+
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
2124
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
2225
import { EditorInput, EditorOptions, IEditor, IEditorInput } from 'vs/workbench/common/editor';
2326
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
@@ -30,8 +33,6 @@ import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor
3033
import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService';
3134
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
3235
import { CustomFileEditorInput } from './customEditorInput';
33-
import { Emitter } from 'vs/base/common/event';
34-
import { ILabelService } from 'vs/platform/label/common/label';
3536

3637
export const defaultEditorId = 'default';
3738

@@ -314,12 +315,26 @@ export const customEditorsAssociationsKey = 'workbench.experimental.editorAssoci
314315

315316
export type CustomEditorsAssociations = readonly (CustomEditorSelector & { readonly viewType: string; })[];
316317

317-
export class CustomEditorContribution implements IWorkbenchContribution {
318+
export class CustomEditorContribution extends Disposable implements IWorkbenchContribution {
318319
constructor(
319-
@IEditorService private readonly editorService: IEditorService,
320+
@IEditorService private readonly editorService: EditorServiceImpl,
320321
@ICustomEditorService private readonly customEditorService: ICustomEditorService,
321322
) {
322-
this.editorService.overrideOpenEditor((editor, options, group) => this.onEditorOpening(editor, options, group));
323+
super();
324+
325+
this._register(this.editorService.overrideOpenEditor((editor, options, group) => {
326+
return this.onEditorOpening(editor, options, group);
327+
}));
328+
329+
this._register(this.editorService.onDidCloseEditor(({ editor }) => {
330+
if (!(editor instanceof CustomFileEditorInput)) {
331+
return;
332+
}
333+
334+
if (!this.editorService.editors.some(other => other === editor)) {
335+
editor.dispose();
336+
}
337+
}));
323338
}
324339

325340
private onEditorOpening(
@@ -329,7 +344,15 @@ export class CustomEditorContribution implements IWorkbenchContribution {
329344
): IOpenEditorOverride | undefined {
330345
if (editor instanceof CustomFileEditorInput) {
331346
if (editor.group === group.id) {
347+
// No need to do anything
332348
return undefined;
349+
} else {
350+
// Create a copy of the input.
351+
// Unlike normal editor inputs, we do not want to share custom editor inputs
352+
// between multiple editors / groups.
353+
return {
354+
override: this.customEditorService.openWith(editor.getResource(), editor.viewType, options, group)
355+
};
333356
}
334357
}
335358

src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ export class WebviewInput extends EditorInput {
3939
}
4040

4141
dispose() {
42-
if (!this._didSomeoneTakeMyWebview) {
43-
this._webview?.rawValue?.dispose();
44-
this._onDisposeWebview.fire();
42+
if (!this.isDisposed()) {
43+
if (!this._didSomeoneTakeMyWebview) {
44+
this._webview?.rawValue?.dispose();
45+
this._onDisposeWebview.fire();
46+
}
4547
}
4648
super.dispose();
4749
}

0 commit comments

Comments
 (0)