Path: blob/main/src/vs/workbench/api/common/extHostCodeInsets.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Emitter } from '../../../base/common/event.js';6import { DisposableStore } from '../../../base/common/lifecycle.js';7import { IExtensionDescription } from '../../../platform/extensions/common/extensions.js';8import { ExtHostTextEditor } from './extHostTextEditor.js';9import { ExtHostEditors } from './extHostTextEditors.js';10import { asWebviewUri, webviewGenericCspSource, WebviewRemoteInfo } from '../../contrib/webview/common/webview.js';11import type * as vscode from 'vscode';12import { ExtHostEditorInsetsShape, MainThreadEditorInsetsShape } from './extHost.protocol.js';1314export class ExtHostEditorInsets implements ExtHostEditorInsetsShape {1516private _handlePool = 0;17private readonly _disposables = new DisposableStore();18private _insets = new Map<number, { editor: vscode.TextEditor; inset: vscode.WebviewEditorInset; onDidReceiveMessage: Emitter<any> }>();1920constructor(21private readonly _proxy: MainThreadEditorInsetsShape,22private readonly _editors: ExtHostEditors,23private readonly _remoteInfo: WebviewRemoteInfo24) {2526// dispose editor inset whenever the hosting editor goes away27this._disposables.add(_editors.onDidChangeVisibleTextEditors(() => {28const visibleEditor = _editors.getVisibleTextEditors();29for (const value of this._insets.values()) {30if (visibleEditor.indexOf(value.editor) < 0) {31value.inset.dispose(); // will remove from `this._insets`32}33}34}));35}3637dispose(): void {38this._insets.forEach(value => value.inset.dispose());39this._disposables.dispose();40}4142createWebviewEditorInset(editor: vscode.TextEditor, line: number, height: number, options: vscode.WebviewOptions | undefined, extension: IExtensionDescription): vscode.WebviewEditorInset {4344let apiEditor: ExtHostTextEditor | undefined;45for (const candidate of this._editors.getVisibleTextEditors(true)) {46if (candidate.value === editor) {47apiEditor = <ExtHostTextEditor>candidate;48break;49}50}51if (!apiEditor) {52throw new Error('not a visible editor');53}5455const that = this;56const handle = this._handlePool++;57const onDidReceiveMessage = new Emitter<any>();58const onDidDispose = new Emitter<void>();5960const webview = new class implements vscode.Webview {6162private _html: string = '';63private _options: vscode.WebviewOptions = Object.create(null);6465asWebviewUri(resource: vscode.Uri): vscode.Uri {66return asWebviewUri(resource, that._remoteInfo);67}6869get cspSource(): string {70return webviewGenericCspSource;71}7273set options(value: vscode.WebviewOptions) {74this._options = value;75that._proxy.$setOptions(handle, value);76}7778get options(): vscode.WebviewOptions {79return this._options;80}8182set html(value: string) {83this._html = value;84that._proxy.$setHtml(handle, value);85}8687get html(): string {88return this._html;89}9091get onDidReceiveMessage(): vscode.Event<any> {92return onDidReceiveMessage.event;93}9495postMessage(message: any): Thenable<boolean> {96return that._proxy.$postMessage(handle, message);97}98};99100const inset = new class implements vscode.WebviewEditorInset {101102readonly editor: vscode.TextEditor = editor;103readonly line: number = line;104readonly height: number = height;105readonly webview: vscode.Webview = webview;106readonly onDidDispose: vscode.Event<void> = onDidDispose.event;107108dispose(): void {109if (that._insets.has(handle)) {110that._insets.delete(handle);111that._proxy.$disposeEditorInset(handle);112onDidDispose.fire();113114// final cleanup115onDidDispose.dispose();116onDidReceiveMessage.dispose();117}118}119};120121this._proxy.$createEditorInset(handle, apiEditor.id, apiEditor.value.document.uri, line + 1, height, options || {}, extension.identifier, extension.extensionLocation);122this._insets.set(handle, { editor, inset, onDidReceiveMessage });123124return inset;125}126127$onDidDispose(handle: number): void {128const value = this._insets.get(handle);129if (value) {130value.inset.dispose();131}132}133134$onDidReceiveMessage(handle: number, message: any): void {135const value = this._insets.get(handle);136value?.onDidReceiveMessage.fire(message);137}138}139140141