vscode
vscode copied to clipboard
webview keep loading when postmeessage to it
Does this issue occur when all extensions are disabled?: Yes
版本: 1.68.1 (Universal) 提交: 30d9c6cd9483b2cc586687151bcbcd635f373630 日期: 2022-06-14T12:52:13.188Z Electron: 17.4.7 Chromium: 98.0.4758.141 Node.js: 16.13.0 V8: 9.8.177.13-electron.0 OS: Darwin x64 21.6.0
Steps to Reproduce:
-
registerCustomEditorProvider
- In
resolveCustomEditor
, enableenableScripts
and sethtml
ofwebview
. -
postMessage
towebview
Then webview keep loading. By skip step3, webview show normally
Please share a minimal example extension that demonstrates the issue
Also make sure to test on the latest VS Code
For some reason, I can't upload files or share link directly. Here are some information you may need.
const LockViewEditorViewType = "xieyuchao.lockViewer";
export function activate(context: ExtensionContext) {
context.subscriptions.push(
window.registerCustomEditorProvider(
LockViewEditorViewType,
new LockViewerEditor(),
{
supportsMultipleEditorsPerDocument: true,
}
)
);
}
class NpmDocument implements CustomDocument {
uri: Uri;
constructor(uri: Uri) {
this.uri = uri;
}
dispose(): void {
// TODO
}
}
class LockViewerEditor implements CustomReadonlyEditorProvider {
openCustomDocument(
uri: Uri,
openContext: CustomDocumentOpenContext,
token: CancellationToken
): CustomDocument | Thenable<CustomDocument> {
return new NpmDocument(uri);
}
async resolveCustomEditor(
document: NpmDocument,
webviewPanel: WebviewPanel,
token: CancellationToken
): Promise<void> {
webviewPanel.webview.options = {
enableScripts: true,
};
webviewPanel.webview.html = "test webview";
console.log("ready to postMessage");
const result = await webviewPanel.webview.postMessage({
type: "lock",
data: [],
});
console.log(`result: ${result}`);
}
}
And
webpack
config
// Base.ts
export default {
target: "node",
entry: {
index: resolve(__dirname, "../extension/index.ts"),
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-typescript"],
},
},
],
},
],
},
externals: {
vscode: "commonjs vscode",
},
resolve: {
extensions: [".ts", ".js"],
},
output: {
filename: "[name].js",
path: resolve(__dirname, "../dist"),
libraryTarget: "commonjs2",
devtoolModuleFilenameTemplate: "../[resource-path]",
},
} as Configuration;
// Dev.ts
const config = {
mode: "development",
devtool: "cheap-module-source-map",
} as Configuration;
export default Merge(Base, config);
If I remove codes about postMessage
, it seems to be ok;
I tried to update version, but the problem still exists 版本: 1.71.2 (Universal) 提交: 74b1f979648cc44d385a2286793c226e611f59e7 日期: 2022-09-14T21:05:37.721Z Electron: 19.0.12 Chromium: 102.0.5005.167 Node.js: 16.14.2 V8: 10.2.154.15-electron.0 OS: Darwin x64 21.6.0
Thanks!
This is expected. You should not be awaiting on posting a message to the webview in resolveCustomEditor
. resolveCustomEditor
sets up the custom editor's webview. However the webview element itself (the iframe) is only created and shown to users after resolveCustomEditor
returns
This means that the promise returned by the call to postMessage
inside of resolveCustomEditor
will not resolve until resolveCustomEditor
returns. But resolveCustomEditor
will never return until the awaited call to postMessage
resolves. So you get a deadlock
The fix is not await any calls to postMessage
inside resolveCustomEditor