From 39b6d1aaf267243fd77d9fea3e5b629ee63d8282 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 17 Oct 2018 17:01:06 -0700 Subject: [PATCH] Add guards for webview deserialization possibly failing Fixes #60960 Adds two fixes for #60960 - Don't convert uris to strings for serialization but instead leave them as their components. This lets us avoid having to call `parse` in `deserialize` - Add try catches around operations like `parse` that may throw --- .../webviewEditorInputFactory.ts | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory.ts b/src/vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory.ts index 8cc701c66d8..56342f9fb07 100644 --- a/src/vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory.ts +++ b/src/vs/workbench/parts/webview/electron-browser/webviewEditorInputFactory.ts @@ -7,16 +7,21 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IEditorInputFactory } from 'vs/workbench/common/editor'; import { WebviewEditorInput } from './webviewEditorInput'; import { IWebviewEditorService, WebviewInputOptions } from './webviewEditorService'; -import { URI } from 'vs/base/common/uri'; +import { URI, UriComponents } from 'vs/base/common/uri'; + +interface SerializedIconPath { + light: string | UriComponents; + dark: string | UriComponents; +} interface SerializedWebview { readonly viewType: string; readonly id: number; readonly title: string; readonly options: WebviewInputOptions; - readonly extensionLocation: string; + readonly extensionLocation: string | UriComponents; readonly state: any; - readonly iconPath: { light: string, dark: string } | undefined; + readonly iconPath: SerializedIconPath | undefined; } export class WebviewEditorInputFactory implements IEditorInputFactory { @@ -45,11 +50,16 @@ export class WebviewEditorInputFactory implements IEditorInputFactory { id: input.getId(), title: input.getName(), options: input.options, - extensionLocation: input.extensionLocation.toString(), + extensionLocation: input.extensionLocation, state: input.state, - iconPath: input.iconPath ? { light: input.iconPath.light.toString(), dark: input.iconPath.dark.toString(), } : undefined, + iconPath: input.iconPath ? { light: input.iconPath.light, dark: input.iconPath.dark, } : undefined, }; - return JSON.stringify(data); + + try { + return JSON.stringify(data); + } catch { + return null; + } } public deserialize( @@ -57,8 +67,28 @@ export class WebviewEditorInputFactory implements IEditorInputFactory { serializedEditorInput: string ): WebviewEditorInput { const data: SerializedWebview = JSON.parse(serializedEditorInput); - const extensionLocation = URI.parse(data.extensionLocation); - const iconPath = data.iconPath ? { light: URI.parse(data.iconPath.light), dark: URI.parse(data.iconPath.dark) } : undefined; + const extensionLocation = reviveUri(data.extensionLocation); + const iconPath = reviveIconPath(data.iconPath); return this._webviewService.reviveWebview(data.viewType, data.id, data.title, iconPath, data.state, data.options, extensionLocation); } } +function reviveIconPath(data: SerializedIconPath) { + const light = reviveUri(data.light); + const dark = reviveUri(data.dark); + return light && dark ? { light, dark } : undefined; +} + +function reviveUri(data: string | UriComponents | undefined): URI | undefined { + if (!data) { + return undefined; + } + + try { + if (typeof data === 'string') { + return URI.parse(data); + } + return URI.from(data); + } catch { + return undefined; + } +} -- GitLab