Change:
Issue Type: <bBug</bIf you try to open the release notes while offline, then if a release notes url is configured then vscode will open it in a browser, otherwise it will do nothing, not even show an error. Later, if you go online and try opening the release notes again, the same will happen - vscode will never attempt to open the release notes webview again. This state is preserved until you reload the window. Steps to Reproduce: offline (you can also open devtools in vscode and go to the network tab and change the "online" at the top to "offline") to open the release notes using from the command palette. on whether you are on an official vscode build or a local build, the release notes page will be opened in your default browser. On a local build nothing happens. back online to open the release notes again same thing will happen the window using from the command palette to open the release notes again release notes open in a webview inside vscode VS Code version: Code - Insiders 1.47.0-insider (, 2020-06-26T06:20:06.931Z) OS version: Windows_NT x64 10.0. Does this issue occur when all extensions are disabled?: Yes

Discussion:
setRequestHeaders(xhr, options); xhr.responseType = 'arraybuffer'; <del> xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText))); </del> <ins> xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText) || 'XHR failed')); </ins> xhr.onload = (e) => { resolve({ res: {

return true; } <del> private loadReleaseNotes(version: string): Promise<string> { </del> <ins> private async loadReleaseNotes(version: string): Promise<string> { </ins> const match = /^(d+.d+)./.exec(version); if (!match) { <del> return Promise.reject(new Error('not found')); </del> <ins> throw new Error('not found'); </ins> } const versionLabel = match[1].replace(/./g, '_');

.replace(/kbstyle(([^)]+))/gi, kbstyle); }; <del> if (!this._releaseNotesCache.has(version)) { this._releaseNotesCache.set(version, this._requestService.request({ url }, CancellationToken.None) .then(asText) .then(text => { if (!text || !/^#s/.test(text)) { // release notes always starts with `#` followed by whitespace return Promise.reject(new Error('Invalid release notes')); } </del> <ins> const fetchReleaseNotes = async () => { let text; try { text = await asText(await this._requestService.request({ url }, CancellationToken.None)); } catch { throw new Error('Failed to fetch release notes'); } if (!text || !/^#s/.test(text)) { // release notes always starts with `#` followed by whitespace throw new Error('Invalid release notes'); } </ins> <del> return Promise.resolve(text); }) .then(text => patchKeybindings(text))); </del> <ins> return patchKeybindings(text); }; if (!this._releaseNotesCache.has(version)) { this._releaseNotesCache.set(version, (async () => { try { return await fetchReleaseNotes(); } catch (err) { this._releaseNotesCache.delete(version); throw err; } })()); </ins> } return this._releaseNotesCache.get(version)!;

super('update.openLatestReleaseNotes', nls.localize('releaseNotes', "Release Notes"), undefined, true); } <del> run(): Promise<any> { </del> <ins> async run(): Promise<void> { </ins> if (this.productService.releaseNotesUrl) { const uri = URI.parse(this.productService.releaseNotesUrl); <del> return this.openerService.open(uri); </del> <ins> await this.openerService.open(uri); </ins> } <del> return Promise.resolve(false); </del> <ins> throw new Error('This version of Visual Studio Code does not have release notes online'); </ins> } }

super(id, label, undefined, true); } <del> run(): Promise<boolean> { </del> <ins> async run(): Promise<void> { </ins> if (!this.enabled) { <del> return Promise.resolve(false); </del> <ins> return; </ins> } this.enabled = false; <del> return showReleaseNotes(this.instantiationService, this.version) .then(undefined, () => { const action = this.instantiationService.createInstance(OpenLatestReleaseNotesInBrowserAction); return action.run().then(() => false); }); </del> <ins> try { await showReleaseNotes(this.instantiationService, this.version); } catch (err) { const action = this.instantiationService.createInstance(OpenLatestReleaseNotesInBrowserAction); try { await action.run(); } catch (err2) { throw new Error(`${err.message} and ${err2.message}`); } } </ins> } }