diff --git a/packages/plugin-ext/src/main/browser/webview/pre/host.js b/packages/plugin-ext/src/main/browser/webview/pre/host.js index 399070fdce43f..7ef317406d393 100644 --- a/packages/plugin-ext/src/main/browser/webview/pre/host.js +++ b/packages/plugin-ext/src/main/browser/webview/pre/host.js @@ -36,7 +36,7 @@ break; } } - if (sourceIsChildFrame && e.data && (e.data.command === 'onmessage' || e.data.command === 'do-update-state')) { + if (sourceIsChildFrame && e.data && (e.data.command === 'onmessage' || e.data.command === 'do-update-state' || e.data.command === 'onconsole')) { this.postMessage(e.data.command, e.data.data); } else if (sourceIsChildFrame || sourceIsSelfOrParentFrame) { const channel = e.data.channel; diff --git a/packages/plugin-ext/src/main/browser/webview/pre/main.js b/packages/plugin-ext/src/main/browser/webview/pre/main.js index 402124a328720..a6c4f654412a0 100644 --- a/packages/plugin-ext/src/main/browser/webview/pre/main.js +++ b/packages/plugin-ext/src/main/browser/webview/pre/main.js @@ -144,15 +144,40 @@ * @param {*} [state] * @return {string} */ - function getVsCodeApiScript(state) { + function getDefaultScript(state) { return ` const acquireVsCodeApi = (function() { const originalPostMessage = window.parent.postMessage.bind(window.parent); + const originalConsole = {...console}; const targetOrigin = '*'; let acquired = false; let state = ${state ? `JSON.parse(${JSON.stringify(state)})` : undefined}; + const forwardConsoleLog= (level,msg,args)=> { + let message, optionalParams; + try{ + if (msg) { + message= JSON.stringify(msg) ?? null; + } + if (args){ + optionalParams= JSON.stringify(args) ?? null; + } + } catch(e){ + // Log non serializable objects inside of view + originalConsole[level](msg,args); + return; + } + originalPostMessage({ command: 'onconsole', data: { level, message,optionalParams} }, targetOrigin); + }; + + console.log= (message,args)=> forwardConsoleLog('log',message,args); + console.info= (message,args)=> forwardConsoleLog('info',message,args); + console.warn= (message,args)=> forwardConsoleLog('warn',message,args); + console.error= (message,args)=> forwardConsoleLog('error',message,args); + console.debug= (message,args)=> forwardConsoleLog('debug',message,args); + console.trace= (message,args)=> forwardConsoleLog('trace',message,args); + return () => { if (acquired) { throw new Error('An instance of the VS Code API has already been acquired'); @@ -369,7 +394,7 @@ // apply default script if (options.allowScripts) { const defaultScript = newDocument.createElement('script'); - defaultScript.textContent = getVsCodeApiScript(data.state); + defaultScript.textContent = getDefaultScript(data.state); newDocument.head.prepend(defaultScript); } diff --git a/packages/plugin-ext/src/main/browser/webview/webview.ts b/packages/plugin-ext/src/main/browser/webview/webview.ts index ac6f7310adee1..f7956a6ee1e71 100644 --- a/packages/plugin-ext/src/main/browser/webview/webview.ts +++ b/packages/plugin-ext/src/main/browser/webview/webview.ts @@ -69,7 +69,8 @@ export const enum WebviewMessageChannels { webviewReady = 'webview-ready', didKeydown = 'did-keydown', didMouseDown = 'did-mousedown', - didMouseUp = 'did-mouseup' + didMouseUp = 'did-mouseup', + onconsole = 'onconsole' } export interface WebviewContentOptions { @@ -80,6 +81,12 @@ export interface WebviewContentOptions { readonly enableCommandUris?: boolean | readonly string[]; } +export interface WebviewConsoleLog { + level: Extract; + message?: string; + optionalParams?: string; +} + @injectable() export class WebviewWidgetIdentifier { id: string; @@ -318,6 +325,7 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract this.toHide.push(subscription); this.toHide.push(this.on(WebviewMessageChannels.onmessage, (data: any) => this.onMessageEmitter.fire(data))); + this.toHide.push(this.on(WebviewMessageChannels.onconsole, (data: WebviewConsoleLog) => this.forwardConsoleLog(data))); this.toHide.push(this.on(WebviewMessageChannels.didClickLink, (uri: string) => this.openLink(new URI(uri)))); this.toHide.push(this.on(WebviewMessageChannels.doUpdateState, (state: any) => { this._state = state; @@ -462,6 +470,15 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract this.doUpdateContent(); } + protected forwardConsoleLog(log: WebviewConsoleLog): void { + const message = `[webview: ${this.identifier.id}] ${log.message ? JSON.parse(log.message) : undefined}`; + if (log.optionalParams !== undefined) { + console[log.level](message, JSON.parse(log.optionalParams)); + } else { + console[log.level](message); + } + } + protected style(): void { const { styles, activeThemeType, activeThemeName } = this.themeDataProvider.getThemeData(); this.doSend('styles', { styles, activeThemeType, activeThemeName });