From 993c36c9205f156c1246f65161fa4796d460502f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Fri, 20 May 2022 09:17:57 -0700 Subject: [PATCH] Fix markdown ext errors accessing disposed webview (#149960) When reloading windows that need to restore a markdown preview, sometimes I'll see an error when the markdown preview tries accessing a disposed of webview. This seems to be cause caused by `provideTextDocumentContent`, where we end up disposing of the webview before an `await` resumes execution --- .../markdown-language-features/src/preview/preview.ts | 10 ++++++++-- .../src/preview/previewContentProvider.ts | 7 ++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/extensions/markdown-language-features/src/preview/preview.ts b/extensions/markdown-language-features/src/preview/preview.ts index f598dd62fa3..dd3c310a194 100644 --- a/extensions/markdown-language-features/src/preview/preview.ts +++ b/extensions/markdown-language-features/src/preview/preview.ts @@ -109,6 +109,8 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { private readonly _onScrollEmitter = this._register(new vscode.EventEmitter()); public readonly onScroll = this._onScrollEmitter.event; + private readonly _disposeCts = this._register(new vscode.CancellationTokenSource()); + constructor( webview: vscode.WebviewPanel, resource: vscode.Uri, @@ -202,6 +204,8 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { } override dispose() { + this._disposeCts.cancel(); + super.dispose(); this._disposed = true; @@ -286,7 +290,9 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { try { document = await vscode.workspace.openTextDocument(this._resource); } catch { - await this.showFileNotFoundError(); + if (!this._disposed) { + await this.showFileNotFoundError(); + } return; } @@ -306,7 +312,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { this.currentVersion = pendingVersion; const content = await (shouldReloadPage - ? this._contentProvider.provideTextDocumentContent(document, this, this._previewConfigurations, this.line, this.state) + ? this._contentProvider.provideTextDocumentContent(document, this, this._previewConfigurations, this.line, this.state, this._disposeCts.token) : this._contentProvider.markdownBody(document, this)); // Another call to `doUpdate` may have happened. diff --git a/extensions/markdown-language-features/src/preview/previewContentProvider.ts b/extensions/markdown-language-features/src/preview/previewContentProvider.ts index b7ff739ce91..8437017dc4f 100644 --- a/extensions/markdown-language-features/src/preview/previewContentProvider.ts +++ b/extensions/markdown-language-features/src/preview/previewContentProvider.ts @@ -66,7 +66,8 @@ export class MarkdownContentProvider { resourceProvider: WebviewResourceProvider, previewConfigurations: MarkdownPreviewConfigurationManager, initialLine: number | undefined = undefined, - state?: any + state: any | undefined, + token: vscode.CancellationToken ): Promise { const sourceUri = markdownDocument.uri; const config = previewConfigurations.loadAndCacheConfiguration(sourceUri); @@ -89,6 +90,10 @@ export class MarkdownContentProvider { const csp = this.getCsp(resourceProvider, sourceUri, nonce); const body = await this.markdownBody(markdownDocument, resourceProvider); + if (token.isCancellationRequested) { + return { html: '', containingImages: [] }; + } + const html = `