提交 5f3e2078 编写于 作者: M Matt Bierner

Add more explict message queue for webviews while they are loading

上级 4933ceed
......@@ -135,7 +135,7 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
async $postMessage(handle: number, value: any): Promise<boolean> {
const inset = this.getInset(handle);
inset.webview.sendMessage(value);
inset.webview.postMessage(value);
return true;
}
......
......@@ -252,7 +252,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
public async $postMessage(handle: extHostProtocol.WebviewPanelHandle, message: any): Promise<boolean> {
const webview = this.getWebviewInput(handle);
webview.webview.sendMessage(message);
webview.webview.postMessage(message);
return true;
}
......
......@@ -1193,7 +1193,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
}
postMessage(message: any) {
this.webview?.webview.sendMessage(message);
this.webview?.webview.postMessage(message);
}
//#endregion
......
......@@ -714,7 +714,7 @@ ${loaderJs}
}
private _sendMessageToWebview(message: ToWebviewMessage) {
this.webview.sendMessage(message);
this.webview.postMessage(message);
}
clearPreloadsCache() {
......
......@@ -48,6 +48,22 @@ interface WebviewContent {
readonly state: string | undefined;
}
namespace WebviewState {
export const enum Type { Initializing, Ready }
export class Initializing {
readonly type = Type.Initializing;
constructor(
public readonly pendingMessages: Array<{ readonly channel: string, readonly data?: any }>
) { }
}
export const Ready = { type: Type.Ready } as const;
export type State = typeof Ready | Initializing;
}
export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
private _element: T | undefined;
......@@ -56,11 +72,10 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
private _focused: boolean | undefined;
protected get focused(): boolean { return !!this._focused; }
private readonly _ready: Promise<void>;
private _state: WebviewState.State = new WebviewState.Initializing([]);
protected content: WebviewContent;
constructor(
// TODO: matb, this should not be protected. The only reason it needs to be is that the base class ends up using it in the call to createElement
protected readonly id: string,
......@@ -82,15 +97,18 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
this._element = this.createElement(options, contentOptions);
this._ready = new Promise(resolve => {
const subscription = this._register(this.on(WebviewMessageChannels.webviewReady, () => {
if (this.element) {
addClass(this.element, 'ready');
}
subscription.dispose();
resolve();
}));
});
const subscription = this._register(this.on(WebviewMessageChannels.webviewReady, () => {
if (this.element) {
addClass(this.element, 'ready');
}
if (this._state.type === WebviewState.Type.Initializing) {
this._state.pendingMessages.forEach(({ channel, data }) => this.doPostMessage(channel, data));
}
this._state = WebviewState.Ready;
subscription.dispose();
}));
this._register(this.on('no-csp-found', () => {
this.handleNoCspFound();
......@@ -176,14 +194,16 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
private readonly _onDidBlur = this._register(new Emitter<void>());
public readonly onDidBlur = this._onDidBlur.event;
public sendMessage(data: any): void {
public postMessage(data: any): void {
this._send('message', data);
}
protected _send(channel: string, data?: any): void {
this._ready
.then(() => this.postMessage(channel, data))
.catch(err => console.error(err));
if (this._state.type === WebviewState.Type.Initializing) {
this._state.pendingMessages.push({ channel, data });
} else {
this.doPostMessage(channel, data);
}
}
protected abstract readonly extraContentOptions: { readonly [key: string]: string };
......@@ -192,7 +212,7 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
protected abstract on<T = unknown>(channel: string, handler: (data: T) => void): IDisposable;
protected abstract postMessage(channel: string, data?: any): void;
protected abstract doPostMessage(channel: string, data?: any): void;
private _hasAlertedAboutMissingCsp = false;
private handleNoCspFound(): void {
......
......@@ -142,7 +142,7 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv
this._onDidUpdateState.fire(state);
}));
this._pendingMessages.forEach(msg => webview.sendMessage(msg));
this._pendingMessages.forEach(msg => webview.postMessage(msg));
this._pendingMessages.clear();
}
this.container.style.visibility = 'visible';
......@@ -203,9 +203,9 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv
private readonly _onMissingCsp = this._register(new Emitter<ExtensionIdentifier>());
public readonly onMissingCsp: Event<any> = this._onMissingCsp.event;
sendMessage(data: any): void {
postMessage(data: any): void {
if (this._webview.value) {
this._webview.value.sendMessage(data);
this._webview.value.postMessage(data);
} else {
this._pendingMessages.add(data);
}
......
......@@ -96,7 +96,7 @@ export interface Webview extends IDisposable {
readonly onMessage: Event<any>;
readonly onMissingCsp: Event<ExtensionIdentifier>;
sendMessage(data: any): void;
postMessage(data: any): void;
focus(): void;
reload(): void;
......
......@@ -163,7 +163,7 @@ export class IFrameWebview extends BaseWebview<HTMLIFrameElement> implements Web
});
}
protected postMessage(channel: string, data?: any): void {
protected doPostMessage(channel: string, data?: any): void {
if (this.element) {
this.element.contentWindow!.postMessage({ channel, args: data }, '*');
}
......
......@@ -434,7 +434,7 @@ export class ElectronWebviewBasedWebview extends BaseWebview<WebviewTag> impleme
parent.appendChild(this.element);
}
protected async postMessage(channel: string, data?: any): Promise<void> {
protected async doPostMessage(channel: string, data?: any): Promise<void> {
await Promise.all([
this._protocolProvider.synchronize(),
this._domReady,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册