Split out Webview from WebviewEditor in proposed API (#47370)

* Split out `Webview` from `WebviewEditor` in API

**Problem**
The current proposed `Webview` interface has a few methods and properties that are very editor specific, such as `.reveal` and `.onDidChangeViewState`. These properies will not make sense if we ever allow webview to be displayed in other locations, such as in widgets

**Proposal**
Split the concepts of a `Webview` and of a `WebveiwEditor`. A webview is the html content itself. A `WebviewEditor` is an editor that displays a `Webview`

This would allow us to easily add other types of `Webview` owning objects in the future without having to document that some methods only apply when a webview is used as an editor vs as a widget
This commit is contained in:
Matt Bierner 2018-04-11 11:49:02 -07:00 committed by GitHub
parent 485a469b94
commit 8cb7e80544
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 230 additions and 148 deletions

View file

@ -20,7 +20,7 @@ export class MarkdownPreview {
public static viewType = 'markdown.preview';
private readonly webview: vscode.Webview;
private readonly editor: vscode.WebviewEditor;
private throttleTimer: any;
private line: number | undefined = undefined;
private readonly disposables: vscode.Disposable[] = [];
@ -32,7 +32,7 @@ export class MarkdownPreview {
public static async revive(
webview: vscode.Webview,
webview: vscode.WebviewEditor,
state: any,
contentProvider: MarkdownContentProvider,
previewConfigurations: MarkdownPreviewConfigurationManager,
@ -69,7 +69,7 @@ export class MarkdownPreview {
topmostLineMonitor: MarkdownFileTopmostLineMonitor,
contributions: MarkdownContributions
): MarkdownPreview {
const webview = vscode.window.createWebview(
const webview = vscode.window.createWebviewEditor(
MarkdownPreview.viewType,
MarkdownPreview.getPreviewTitle(resource, locked),
previewColumn, {
@ -90,7 +90,7 @@ export class MarkdownPreview {
}
private constructor(
webview: vscode.Webview,
webview: vscode.WebviewEditor,
private _resource: vscode.Uri,
public locked: boolean,
private readonly contentProvider: MarkdownContentProvider,
@ -98,17 +98,17 @@ export class MarkdownPreview {
private readonly logger: Logger,
topmostLineMonitor: MarkdownFileTopmostLineMonitor
) {
this.webview = webview;
this.editor = webview;
this.webview.onDidDispose(() => {
this.editor.onDidDispose(() => {
this.dispose();
}, null, this.disposables);
this.webview.onDidChangeViewState(e => {
this.editor.onDidChangeViewState(e => {
this._onDidChangeViewStateEmitter.fire(e);
}, null, this.disposables);
this.webview.onDidReceiveMessage(e => {
this.editor.webview.onDidReceiveMessage(e => {
if (e.source !== this._resource.toString()) {
return;
}
@ -155,7 +155,7 @@ export class MarkdownPreview {
private readonly _onDisposeEmitter = new vscode.EventEmitter<void>();
public readonly onDispose = this._onDisposeEmitter.event;
private readonly _onDidChangeViewStateEmitter = new vscode.EventEmitter<vscode.WebviewOnDidChangeViewStateEvent>();
private readonly _onDidChangeViewStateEmitter = new vscode.EventEmitter<vscode.WebviewEditorOnDidChangeViewStateEvent>();
public readonly onDidChangeViewState = this._onDidChangeViewStateEmitter.event;
public get resource(): vscode.Uri {
@ -180,7 +180,7 @@ export class MarkdownPreview {
this._onDisposeEmitter.dispose();
this._onDidChangeViewStateEmitter.dispose();
this.webview.dispose();
this.editor.dispose();
disposeAll(this.disposables);
}
@ -224,15 +224,15 @@ export class MarkdownPreview {
}
public get viewColumn(): vscode.ViewColumn | undefined {
return this.webview.viewColumn;
return this.editor.viewColumn;
}
public isPreviewOf(resource: vscode.Uri): boolean {
return this._resource.fsPath === resource.fsPath;
}
public isWebviewOf(webview: vscode.Webview): boolean {
return this.webview === webview;
public isWebviewOf(webview: vscode.WebviewEditor): boolean {
return this.editor === webview;
}
public matchesResource(
@ -256,12 +256,12 @@ export class MarkdownPreview {
}
public reveal(viewColumn: vscode.ViewColumn) {
this.webview.reveal(viewColumn);
this.editor.reveal(viewColumn);
}
public toggleLock() {
this.locked = !this.locked;
this.webview.title = MarkdownPreview.getPreviewTitle(this._resource, this.locked);
this.editor.webview.title = MarkdownPreview.getPreviewTitle(this._resource, this.locked);
}
private static getPreviewTitle(resource: vscode.Uri, locked: boolean): string {
@ -293,7 +293,7 @@ export class MarkdownPreview {
private postMessage(msg: any) {
if (!this._disposed) {
this.webview.postMessage(msg);
this.editor.webview.postMessage(msg);
}
}
@ -315,8 +315,8 @@ export class MarkdownPreview {
this.currentVersion = { resource, version: document.version };
const content = await this.contentProvider.provideTextDocumentContent(document, this.previewConfigurations, this.line);
if (this._resource === resource) {
this.webview.title = MarkdownPreview.getPreviewTitle(this._resource, this.locked);
this.webview.html = content;
this.editor.webview.title = MarkdownPreview.getPreviewTitle(this._resource, this.locked);
this.editor.webview.html = content;
}
}

View file

@ -14,7 +14,7 @@ import { isMarkdownFile } from '../util/file';
import { MarkdownPreviewConfigurationManager } from './previewConfig';
import { MarkdownContributions } from '../markdownExtensions';
export class MarkdownPreviewManager implements vscode.WebviewSerializer {
export class MarkdownPreviewManager implements vscode.WebviewEditorSerializer {
private static readonly markdownPreviewActiveContextKey = 'markdownPreviewFocus';
private readonly topmostLineMonitor = new MarkdownFileTopmostLineMonitor();
@ -36,7 +36,7 @@ export class MarkdownPreviewManager implements vscode.WebviewSerializer {
}
}, null, this.disposables);
this.disposables.push(vscode.window.registerWebviewSerializer(MarkdownPreview.viewType, this));
this.disposables.push(vscode.window.registerWebviewEditorSerializer(MarkdownPreview.viewType, this));
}
public dispose(): void {
@ -88,8 +88,8 @@ export class MarkdownPreviewManager implements vscode.WebviewSerializer {
}
}
public async deserializeWebview(
webview: vscode.Webview,
public async deserializeWebviewEditor(
webview: vscode.WebviewEditor,
state: any
): Promise<void> {
const preview = await MarkdownPreview.revive(
@ -103,8 +103,8 @@ export class MarkdownPreviewManager implements vscode.WebviewSerializer {
this.registerPreview(preview);
}
public async serializeWebview(
webview: vscode.Webview,
public async serializeWebviewEditor(
webview: vscode.WebviewEditor,
): Promise<any> {
const preview = this.previews.find(preview => preview.isWebviewOf(webview));
return preview ? preview.state : undefined;

View file

@ -593,28 +593,6 @@ declare module 'vscode' {
*/
readonly enableCommandUris?: boolean;
/**
* Should the find widget be enabled in the webview?
*
* Defaults to false.
*/
readonly enableFindWidget?: boolean;
/**
* Should the webview's context be kept around even when the webview is no longer visible?
*
* Normally a webview's context is created when the webview becomes visible
* and destroyed when the webview is hidden. Apps that have complex state
* or UI can set the `retainContextWhenHidden` to make VS Code keep the webview
* context around, even when the webview moves to a background tab. When
* the webview becomes visible again, the context is automatically restored
* in the exact same state it was in originally.
*
* `retainContextWhenHidden` has a high memory overhead and should only be used if
* your webview's context cannot be quickly saved and restored.
*/
readonly retainContextWhenHidden?: boolean;
/**
* Root paths from which the webview can load local (filesystem) resources using the `vscode-resource:` scheme.
*
@ -625,20 +603,10 @@ declare module 'vscode' {
readonly localResourceRoots?: Uri[];
}
export interface WebviewOnDidChangeViewStateEvent {
readonly viewColumn: ViewColumn;
readonly active: boolean;
}
/**
* A webview displays html content, like an iframe.
*/
export interface Webview {
/**
* The type of the webview, such as `'markdown.preview'`
*/
readonly viewType: string;
/**
* Content settings for the webview.
*/
@ -656,26 +624,11 @@ declare module 'vscode' {
*/
html: string;
/**
* The column in which the webview is showing.
*/
readonly viewColumn?: ViewColumn;
/**
* Fired when the webview content posts a message.
*/
readonly onDidReceiveMessage: Event<any>;
/**
* Fired when the webview is disposed.
*/
readonly onDidDispose: Event<void>;
/**
* Fired when the webview's view state changes.
*/
readonly onDidChangeViewState: Event<WebviewOnDidChangeViewStateEvent>;
/**
* Post a message to the webview content.
*
@ -684,9 +637,77 @@ declare module 'vscode' {
* @param message Body of the message.
*/
postMessage(message: any): Thenable<boolean>;
}
/**
* Content settings for a webview editor.
*/
export interface WebviewEditorOptions {
/**
* Should the find widget be enabled in the editor?
*
* Defaults to false.
*/
readonly enableFindWidget?: boolean;
/**
* Shows the webview in a given column.
* Should the webview editor's content (iframe) be kept around even when the editor
* is no longer visible?
*
* Normally the editor's html context is created when the editor becomes visible
* and destroyed when it is is hidden. Apps that have complex state
* or UI can set the `retainContextWhenHidden` to make VS Code keep the webview
* context around, even when the webview moves to a background tab. When
* the editor becomes visible again, the context is automatically restored
* in the exact same state it was in originally.
*
* `retainContextWhenHidden` has a high memory overhead and should only be used if
* your editor's context cannot be quickly saved and restored.
*/
readonly retainContextWhenHidden?: boolean;
}
/**
* An editor that contains a webview.
*/
interface WebviewEditor {
/**
* The type of the webview editor, such as `'markdown.preview'`.
*/
readonly viewType: string;
/**
* The webview belonging to the editor.
*/
readonly webview: Webview;
/**
* Content settings for the webview editor.
*/
readonly options: WebviewEditorOptions;
/**
* The column in which the editor is showing.
*/
readonly viewColumn?: ViewColumn;
/**
* Fired when the editor's view state changes.
*/
readonly onDidChangeViewState: Event<WebviewEditorOnDidChangeViewStateEvent>;
/**
* Fired when the editor is disposed.
*
* This may be because the user closed the editor or because `.dispose()` was
* called on it.
*
* Trying to use the webview after it has been disposed throws an exception.
*/
readonly onDidDispose: Event<void>;
/**
* Shows the webview editor in a given column.
*
* A webview may only be in a single column at a time. If it is already showing, this
* command moves it to a new column.
@ -694,64 +715,69 @@ declare module 'vscode' {
reveal(viewColumn: ViewColumn): void;
/**
* Dispose of the the webview.
* Dispose of the webview editor.
*
* This closes the webview if it showing and disposes of the resources owned by the webview.
* Webview are also disposed when the user closes the webview editor. Both cases fire `onDispose`
* event. Trying to use the webview after it has been disposed throws an exception.
* event.
*/
dispose(): any;
}
export interface WebviewEditorOnDidChangeViewStateEvent {
readonly viewColumn: ViewColumn;
readonly active: boolean;
}
/**
* Save and restore webviews that have been persisted when vscode shuts down.
* Save and restore webview editors that have been persisted when vscode shuts down.
*/
interface WebviewSerializer {
interface WebviewEditorSerializer {
/**
* Save a webview's `state`.
* Save a webview editors's `state`.
*
* Called before shutdown. Webview may or may not be visible.
* Called before shutdown. Webview editor may or may not be visible.
*
* @param webview Webview to serialize.
* @param webviewEditor Webview editor to serialize.
*
* @returns JSON serializable state blob.
*/
serializeWebview(webview: Webview): Thenable<any>;
serializeWebviewEditor(webviewEditor: WebviewEditor): Thenable<any>;
/**
* Restore a webview from its `state`.
* Restore a webview editor from its `state`.
*
* Called when a serialized webview first becomes active.
*
* @param webview Webview to restore. The serializer should take ownership of this webview.
* @param webviewEditor Webview editor to restore. The serializer should take ownership of this editor.
* @param state Persisted state.
*/
deserializeWebview(webview: Webview, state: any): Thenable<void>;
deserializeWebviewEditor(webviewEditor: WebviewEditor, state: any): Thenable<void>;
}
namespace window {
/**
* Create and show a new webview.
* Create and show a new webview editor.
*
* @param viewType Identifies the type of the webview.
* @param viewType Identifies the type of the webview editor.
* @param title Title of the webview.
* @param column Editor column to show the new webview in.
* @param options Content settings for the webview.
* @param column Editor column to show the new webview editor in.
* @param editorOptions Settings for the webview editor.
*/
export function createWebview(viewType: string, title: string, column: ViewColumn, options: WebviewOptions): Webview;
export function createWebviewEditor(viewType: string, title: string, column: ViewColumn, options: WebviewEditorOptions & WebviewOptions): WebviewEditor;
/**
* Registers a webview serializer.
* Registers a webview editor serializer.
*
* Extensions that support reviving should have an `"onView:viewType"` activation method and
* make sure that `registerWebviewSerializer` is called during activation.
* make sure that `registerWebviewEditorSerializer` is called during activation.
*
* Only a single serializer may be registered at a time for a given `viewType`.
*
* @param viewType Type of the webview that can be serialized.
* @param viewType Type of the webview editor that can be serialized.
* @param reviver Webview serializer.
*/
export function registerWebviewSerializer(viewType: string, reviver: WebviewSerializer): Disposable;
export function registerWebviewEditorSerializer(viewType: string, reviver: WebviewEditorSerializer): Disposable;
}
//#endregion

View file

@ -129,7 +129,7 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
this._webviews.set(handle, webview);
webview._events = this.createWebviewEventDelegate(handle);
return this._proxy.$deserializeWebview(handle, webview.state.viewType, webview.state.state, webview.position, webview.options)
return this._proxy.$deserializeWebview(handle, webview.state.viewType, webview.getTitle(), webview.state.state, webview.position, webview.options)
.then(undefined, () => {
webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
});

View file

@ -416,11 +416,11 @@ export function createApiFactory(
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => {
return extHostDecorations.registerDecorationProvider(provider, extension.id);
}),
createWebview: proposedApiFunction(extension, (viewType: string, title: string, column: vscode.ViewColumn, options: vscode.WebviewOptions) => {
createWebviewEditor: proposedApiFunction(extension, (viewType: string, title: string, column: vscode.ViewColumn, options: vscode.WebviewEditorOptions & vscode.WebviewOptions) => {
return extHostWebviews.createWebview(viewType, title, column, options, extension.extensionFolderPath);
}),
registerWebviewSerializer: proposedApiFunction(extension, (viewType: string, serializer: vscode.WebviewSerializer) => {
return extHostWebviews.registerWebviewSerializer(viewType, serializer);
registerWebviewEditorSerializer: proposedApiFunction(extension, (viewType: string, serializer: vscode.WebviewEditorSerializer) => {
return extHostWebviews.registerWebviewEditorSerializer(viewType, serializer);
})
};

View file

@ -350,7 +350,7 @@ export interface MainThreadTelemetryShape extends IDisposable {
export type WebviewHandle = string;
export interface MainThreadWebviewsShape extends IDisposable {
$createWebview(handle: WebviewHandle, viewType: string, title: string, column: EditorPosition, options: vscode.WebviewOptions, extensionFolderPath: string): void;
$createWebview(handle: WebviewHandle, viewType: string, title: string, column: EditorPosition, options: vscode.WebviewEditorOptions & vscode.WebviewOptions, extensionFolderPath: string): void;
$disposeWebview(handle: WebviewHandle): void;
$reveal(handle: WebviewHandle, column: EditorPosition): void;
$setTitle(handle: WebviewHandle, value: string): void;
@ -365,7 +365,7 @@ export interface ExtHostWebviewsShape {
$onMessage(handle: WebviewHandle, message: any): void;
$onDidChangeWeviewViewState(handle: WebviewHandle, active: boolean, position: EditorPosition): void;
$onDidDisposeWeview(handle: WebviewHandle): Thenable<void>;
$deserializeWebview(newWebviewHandle: WebviewHandle, viewType: string, state: any, position: EditorPosition, options: vscode.WebviewOptions): Thenable<void>;
$deserializeWebview(newWebviewHandle: WebviewHandle, viewType: string, title: string, state: any, position: EditorPosition, options: vscode.WebviewOptions): Thenable<void>;
$serializeWebview(webviewHandle: WebviewHandle): Thenable<any>;
}

View file

@ -12,58 +12,35 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from './extHostTypes';
export class ExtHostWebview implements vscode.Webview {
private readonly _handle: WebviewHandle;
private readonly _viewType: string;
private readonly _proxy: MainThreadWebviewsShape;
private _title: string;
private _html: string;
private _options: vscode.WebviewOptions;
private _isDisposed: boolean = false;
private _viewColumn: vscode.ViewColumn;
private _active: boolean;
public readonly onMessageEmitter = new Emitter<any>();
public readonly onDidReceiveMessage: Event<any> = this.onMessageEmitter.event;
public readonly onDisposeEmitter = new Emitter<void>();
public readonly onDidDispose: Event<void> = this.onDisposeEmitter.event;
public readonly onDidChangeViewStateEmitter = new Emitter<vscode.WebviewOnDidChangeViewStateEvent>();
public readonly onDidChangeViewState: Event<vscode.WebviewOnDidChangeViewStateEvent> = this.onDidChangeViewStateEmitter.event;
public readonly onDidChangeViewStateEmitter = new Emitter<vscode.WebviewEditorOnDidChangeViewStateEvent>();
public readonly onDidChangeViewState: Event<vscode.WebviewEditorOnDidChangeViewStateEvent> = this.onDidChangeViewStateEmitter.event;
constructor(
handle: WebviewHandle,
proxy: MainThreadWebviewsShape,
viewType: string,
viewColumn: vscode.ViewColumn,
title: string,
options: vscode.WebviewOptions
) {
this._handle = handle;
this._proxy = proxy;
this._viewType = viewType;
this._viewColumn = viewColumn;
this._title = title;
this._options = options;
}
public dispose() {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
this._proxy.$disposeWebview(this._handle);
this.onDisposeEmitter.dispose();
this.onMessageEmitter.dispose();
dispose() {
this.onDidChangeViewStateEmitter.dispose();
}
get viewType(): string {
this.assertNotDisposed();
return this._viewType;
}
get title(): string {
this.assertNotDisposed();
return this._title;
@ -95,6 +72,84 @@ export class ExtHostWebview implements vscode.Webview {
return this._options;
}
public postMessage(message: any): Thenable<boolean> {
this.assertNotDisposed();
return this._proxy.$sendMessage(this._handle, message);
}
public reveal(viewColumn: vscode.ViewColumn): void {
this.assertNotDisposed();
this._proxy.$reveal(this._handle, typeConverters.fromViewColumn(viewColumn));
}
private assertNotDisposed() {
if (this._isDisposed) {
throw new Error('Webview is disposed');
}
}
}
export class ExtHostWebviewEditor implements vscode.WebviewEditor {
private readonly _handle: WebviewHandle;
private readonly _viewType: string;
private readonly _options: vscode.WebviewEditorOptions;
private readonly _proxy: MainThreadWebviewsShape;
private _isDisposed: boolean = false;
private _viewColumn: vscode.ViewColumn;
private _active: boolean;
public readonly onDisposeEmitter = new Emitter<void>();
public readonly onDidDispose: Event<void> = this.onDisposeEmitter.event;
public readonly onDidChangeViewStateEmitter = new Emitter<vscode.WebviewEditorOnDidChangeViewStateEvent>();
public readonly onDidChangeViewState: Event<vscode.WebviewEditorOnDidChangeViewStateEvent> = this.onDidChangeViewStateEmitter.event;
private _webview: ExtHostWebview;
constructor(
handle: WebviewHandle,
proxy: MainThreadWebviewsShape,
viewType: string,
title: string,
viewColumn: vscode.ViewColumn,
editorOptions: vscode.WebviewEditorOptions,
webviewOptions: vscode.WebviewOptions
) {
this._handle = handle;
this._proxy = proxy;
this._viewType = viewType;
this._options = editorOptions;
this._viewColumn = viewColumn;
this._webview = new ExtHostWebview(handle, proxy, title, webviewOptions);
}
public dispose() {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
this._proxy.$disposeWebview(this._handle);
this.onDisposeEmitter.dispose();
this.onDidChangeViewStateEmitter.dispose();
}
get webview() {
this.assertNotDisposed();
return this._webview;
}
get viewType(): string {
this.assertNotDisposed();
return this._viewType;
}
get options() {
return this._options;
}
get viewColumn(): vscode.ViewColumn {
this.assertNotDisposed();
return this._viewColumn;
@ -137,8 +192,8 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
private readonly _proxy: MainThreadWebviewsShape;
private readonly _webviews = new Map<WebviewHandle, ExtHostWebview>();
private readonly _serializers = new Map<string, vscode.WebviewSerializer>();
private readonly _webviews = new Map<WebviewHandle, ExtHostWebviewEditor>();
private readonly _serializers = new Map<string, vscode.WebviewEditorSerializer>();
constructor(
mainContext: IMainContext
@ -150,20 +205,20 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
viewType: string,
title: string,
viewColumn: vscode.ViewColumn,
options: vscode.WebviewOptions,
options: vscode.WebviewEditorOptions & vscode.WebviewOptions,
extensionFolderPath: string
): vscode.Webview {
): vscode.WebviewEditor {
const handle = ExtHostWebviews.webviewHandlePool++ + '';
this._proxy.$createWebview(handle, viewType, title, typeConverters.fromViewColumn(viewColumn), options, extensionFolderPath);
const webview = new ExtHostWebview(handle, this._proxy, viewType, viewColumn, options);
const webview = new ExtHostWebviewEditor(handle, this._proxy, viewType, title, viewColumn, options, options);
this._webviews.set(handle, webview);
return webview;
}
registerWebviewSerializer(
registerWebviewEditorSerializer(
viewType: string,
serializer: vscode.WebviewSerializer
serializer: vscode.WebviewEditorSerializer
): vscode.Disposable {
if (this._serializers.has(viewType)) {
throw new Error(`Serializer for '${viewType}' already registered`);
@ -181,7 +236,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
$onMessage(handle: WebviewHandle, message: any): void {
const webview = this.getWebview(handle);
if (webview) {
webview.onMessageEmitter.fire(message);
webview.webview.onMessageEmitter.fire(message);
}
}
@ -209,6 +264,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
$deserializeWebview(
webviewHandle: WebviewHandle,
viewType: string,
title: string,
state: any,
position: Position,
options: vscode.WebviewOptions
@ -218,9 +274,9 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
return TPromise.wrapError(new Error(`No serializer found for '${viewType}'`));
}
const revivedWebview = new ExtHostWebview(webviewHandle, this._proxy, viewType, typeConverters.toViewColumn(position), options);
const revivedWebview = new ExtHostWebviewEditor(webviewHandle, this._proxy, viewType, title, typeConverters.toViewColumn(position), options as vscode.WebviewEditorOptions, options as vscode.WebviewOptions);
this._webviews.set(webviewHandle, revivedWebview);
return serializer.deserializeWebview(revivedWebview, state);
return serializer.deserializeWebviewEditor(revivedWebview, state);
}
$serializeWebview(
@ -236,10 +292,10 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
return TPromise.as(undefined);
}
return serialzer.serializeWebview(webview);
return serialzer.serializeWebviewEditor(webview);
}
private getWebview(handle: WebviewHandle): ExtHostWebview | undefined {
private getWebview(handle: WebviewHandle): ExtHostWebviewEditor | undefined {
return this._webviews.get(handle);
}
}

View file

@ -67,7 +67,7 @@ export interface WebviewEvents {
onDidClickLink?(link: URI, options: vscode.WebviewOptions): void;
}
export interface WebviewInputOptions extends vscode.WebviewOptions {
export interface WebviewInputOptions extends vscode.WebviewOptions, vscode.WebviewEditorOptions {
tryRestoreScrollPosition?: boolean;
}

View file

@ -21,12 +21,12 @@ suite('ExtHostWebview', function () {
const shape = createNoopMainThreadWebviews();
const extHostWebviews = new ExtHostWebviews(SingleProxyRPCProtocol(shape));
let lastInvokedDeserializer: vscode.WebviewSerializer | undefined = undefined;
let lastInvokedDeserializer: vscode.WebviewEditorSerializer | undefined = undefined;
class NoopSerializer implements vscode.WebviewSerializer {
async serializeWebview(webview: vscode.Webview): Promise<any> { /* noop */ }
class NoopSerializer implements vscode.WebviewEditorSerializer {
async serializeWebviewEditor(webview: vscode.WebviewEditor): Promise<any> { /* noop */ }
async deserializeWebview(webview: vscode.Webview, state: any): Promise<void> {
async deserializeWebviewEditor(webview: vscode.WebviewEditor, state: any): Promise<void> {
lastInvokedDeserializer = this;
}
}
@ -34,20 +34,20 @@ suite('ExtHostWebview', function () {
const serializerA = new NoopSerializer();
const serializerB = new NoopSerializer();
const serializerARegistration = extHostWebviews.registerWebviewSerializer(viewType, serializerA);
const serializerARegistration = extHostWebviews.registerWebviewEditorSerializer(viewType, serializerA);
await extHostWebviews.$deserializeWebview('x', viewType, {}, EditorPosition.ONE, {});
await extHostWebviews.$deserializeWebview('x', viewType, 'title', {}, EditorPosition.ONE, {});
assert.strictEqual(lastInvokedDeserializer, serializerA);
assert.throws(
() => extHostWebviews.registerWebviewSerializer(viewType, serializerB),
() => extHostWebviews.registerWebviewEditorSerializer(viewType, serializerB),
'Should throw when registering two serializers for the same view');
serializerARegistration.dispose();
extHostWebviews.registerWebviewSerializer(viewType, serializerB);
extHostWebviews.registerWebviewEditorSerializer(viewType, serializerB);
await extHostWebviews.$deserializeWebview('x', viewType, {}, EditorPosition.ONE, {});
await extHostWebviews.$deserializeWebview('x', viewType, 'title', {}, EditorPosition.ONE, {});
assert.strictEqual(lastInvokedDeserializer, serializerB);
});
});