diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index 5abdd9f3828..85a44d6bf94 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -11,7 +11,7 @@ import { ThrottledDelayer } from 'vs/base/common/async'; import { streamToBuffer } from 'vs/base/common/buffer'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { Emitter } from 'vs/base/common/event'; -import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; @@ -117,6 +117,8 @@ export class IFrameWebview extends Disposable implements Webview { private readonly _onDidHtmlChange: Emitter = this._register(new Emitter()); protected readonly onDidHtmlChange = this._onDidHtmlChange.event; + private readonly _messageHandlers = new Map void>>(); + constructor( public readonly id: string, private readonly options: WebviewOptions, @@ -288,6 +290,13 @@ export class IFrameWebview extends Disposable implements Webview { } })); + this._register(addDisposableListener(window, 'message', e => { + if (e?.data?.target === this.id) { + const handlers = this._messageHandlers.get(e.data.channel); + handlers?.forEach(handler => handler(e.data.data)); + } + })); + this.initElement(extension, options); } @@ -413,13 +422,15 @@ export class IFrameWebview extends Disposable implements Webview { } protected on(channel: WebviewMessageChannels, handler: (data: T) => void): IDisposable { - return addDisposableListener(window, 'message', e => { - if (!e || !e.data || e.data.target !== this.id) { - return; - } - if (e.data.channel === channel) { - handler(e.data.data); - } + let handlers = this._messageHandlers.get(channel); + if (!handlers) { + handlers = new Set(); + this._messageHandlers.set(channel, handlers); + } + + handlers.add(handler); + return toDisposable(() => { + this._messageHandlers.get(channel)?.delete(handler); }); }