From 88e4fad546381157c40d3d54ae0d90224d0b0718 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Sat, 9 May 2020 20:50:11 -0700 Subject: [PATCH 01/13] Add support for one-step debugging for Blazor --- .../package.json | 42 ++++++++++++ .../package.json | 1 + .../src/BlazorDebugConfigurationProvider.ts | 64 +++++++++++++++++++ .../src/extension.ts | 30 +++++++++ .../yarn.lock | 5 ++ 5 files changed, 142 insertions(+) create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json index fde24627e65..b214f706d1c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json @@ -18,6 +18,7 @@ "activationEvents": [ "onWebviewPanel:razorReportIssue", "onDebugInitialConfigurations", + "onDebug", "onDebugResolve:coreclr", "onDebugResolve:clr", "onLanguage:csharp", @@ -46,6 +47,47 @@ ], "main": "./dist/extension", "contributes": { + "breakpoints": [ + { + "language": "aspnetcorerazor" + }, + { + "language": "csharp" + } + ], + "debuggers": [ + { + "type": "blazor", + "label": "Blazor WebAssembly Debug", + "initialConfigurations": [ + { + "type": "blazor", + "name": "Launch and Debug Blazor Application", + "request": "launch" + } + ], + "configurationAttributes": { + "launch": { + "properties": { + "env": { + "type": "object", + "description": "Environment variables passed to dotnet" + }, + "url": { + "type": "string", + "description": "The URL of the application", + "default": "https://localhost:5001" + }, + "browser": { + "type": "string", + "description": "The debugging browser to launch (Edge or Chrome)", + "default": "chrome" + } + } + } + } + } + ], "semanticTokenTypes": [ { "id": "razorTagHelperElement", diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/package.json b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/package.json index aaf2a5202f4..87f55f60fb2 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/package.json +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/package.json @@ -15,6 +15,7 @@ "typescript": "3.3.4000" }, "dependencies": { + "ps-list": "^7.0.0", "vscode-html-languageservice": "2.1.7", "vscode-languageclient": "5.2.1" }, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts new file mode 100644 index 00000000000..930b477cb5c --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts @@ -0,0 +1,64 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as vscode from 'vscode'; + +import { RazorLogger } from './RazorLogger'; + +export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurationProvider { + private logger: RazorLogger; + private vscodeType: typeof vscode; + + constructor(logger: RazorLogger, vscodeType: typeof vscode) { + this.logger = logger; + this.vscodeType = vscodeType; + } + + public resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, configuration: vscode.DebugConfiguration): vscode.ProviderResult { + const app = { + name: '.NET Core Launch (Blazor Standalone)', + type: 'coreclr', + request: 'launch', + program: 'dotnet', + args: ['run'], + cwd: '${workspaceFolder}', + env: { + ASPNETCORE_ENVIRONMENT: 'Development', + ...configuration.env, + }, + }; + const browser = { + name: '.NET Core Debug Blazor Web Assembly in Browser', + type: configuration.browser === 'edge' ? 'edge' : 'pwa-chrome', + request: 'launch', + timeout: 30000, + url: configuration.url || 'https://localhost:5001', + webRoot: '${workspaceFolder}', + inspectUri: '{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}', + }; + + this.vscodeType.debug.startDebugging(folder, app).then( + appStartFulfilled => { + if (appStartFulfilled) { + this.vscodeType.debug.startDebugging(folder, browser).then( + debugStartFulfilled => { + if (debugStartFulfilled) { + this.logger.logVerbose('Launching JavaScript debugger...'); + } + }, + error => { + this.logger.logError('Error when launching Chrome debugger: ', error); + }, + ); + } + }, + error => { + this.logger.logError('Error when launching application: ', error); + }, + ); + + return undefined; + } +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts index defdb8cbec4..2b1487cf676 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts @@ -3,9 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ +import { exec } from 'child_process'; +import * as psList from 'ps-list'; import * as vscode from 'vscode'; import * as vscodeapi from 'vscode'; import { ExtensionContext } from 'vscode'; +import { BlazorDebugConfigurationProvider } from './BlazorDebugConfigurationProvider'; import { CompositeCodeActionTranslator } from './CodeActions/CompositeRazorCodeActionTranslator'; import { RazorCodeActionProvider } from './CodeActions/RazorCodeActionProvider'; import { RazorFullyQualifiedCodeActionTranslator } from './CodeActions/RazorFullyQualifiedCodeActionTranslator'; @@ -182,6 +185,33 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC localRegistrations.length = 0; }); + const provider = new BlazorDebugConfigurationProvider(logger, vscodeType); + context.subscriptions.push(vscodeType.debug.registerDebugConfigurationProvider('blazor', provider)); + + /** + * On non-Windows platforms, we need to terminate the Blazor + * dev server and its child processes. + */ + vscodeType.debug.onDidTerminateDebugSession(event => { + logger.logVerbose('Terminating debugging session...'); + if (process.platform !== 'win32') { + psList().then(processes => { + const devserver = processes.find( + (process: psList.ProcessDescriptor) => !!(process && process.cmd && process.cmd.includes('blazor-devserver')), + ); + if (devserver) { + const command = `kill ${devserver.pid}`; + exec(command, (error, stdout, stderr) => { + if (error) { + logger.logError('Error during debug process clean-up: ', error); + } + return logger.logMessage('Debug process clean-up complete.'); + }); + } + }).catch(error => logger.logError('Error retrieving processes to clean-up: ', error)); + } + }); + languageServerClient.onStarted(async () => { await documentManager.initialize(); }); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/yarn.lock b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/yarn.lock index e0c5fe3ae57..0dfeceaf968 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/yarn.lock +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/yarn.lock @@ -195,6 +195,11 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +ps-list@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ps-list/-/ps-list-7.0.0.tgz#fd740a839786605d257117b899031db9b34b8b4b" + integrity sha512-ZDhdxqb+kE895BAvqIdGnWwfvB43h7KHMIcJC0hw7xLbbiJoprS+bqZxuGZ0jWdDxZEvB3jpnfgJyOn3lmsH+Q== + resolve@^1.3.2: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" From 6757fcaee9c3253729d937fccd019e357dc25404 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Mon, 11 May 2020 14:47:06 -0700 Subject: [PATCH 02/13] Resolve first round of issues from peer review --- .../package.json | 25 +++++++-- .../src/BlazorDebugConfigurationProvider.ts | 54 +++++++++---------- .../src/extension.ts | 27 +++++++--- 3 files changed, 65 insertions(+), 41 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json index b214f706d1c..57727b24d4d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json @@ -57,12 +57,12 @@ ], "debuggers": [ { - "type": "blazor", + "type": "blazorwasm", "label": "Blazor WebAssembly Debug", "initialConfigurations": [ { - "type": "blazor", - "name": "Launch and Debug Blazor Application", + "type": "blazorwasm", + "name": "Launch and Debug Blazor WebAssembly Application", "request": "launch" } ], @@ -81,7 +81,24 @@ "browser": { "type": "string", "description": "The debugging browser to launch (Edge or Chrome)", - "default": "chrome" + "default": "chrome", + "enum": ["chrome", "edge"] + }, + "trace": { + "type": ["boolean", "string"], + "default": "true", + "enum": ["verbose", true], + "description": "If true, verbose logs sent to log file. If 'verbose', send logs to console." + }, + "webRoot": { + "type": "string", + "default": "${workspaceFolder}", + "description": "Specifies the absolute path to the webserver root." + }, + "timeout": { + "type": "number", + "default": 30000, + "description": "Retry for this number of milliseconds to connect to browser." } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts index 930b477cb5c..ca2b2e4f933 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts @@ -8,15 +8,10 @@ import * as vscode from 'vscode'; import { RazorLogger } from './RazorLogger'; export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurationProvider { - private logger: RazorLogger; - private vscodeType: typeof vscode; - constructor(logger: RazorLogger, vscodeType: typeof vscode) { - this.logger = logger; - this.vscodeType = vscodeType; - } + constructor(private readonly logger: RazorLogger, private readonly vscodeType: typeof vscode) {} - public resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, configuration: vscode.DebugConfiguration): vscode.ProviderResult { + public async resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, configuration: vscode.DebugConfiguration): Promise { const app = { name: '.NET Core Launch (Blazor Standalone)', type: 'coreclr', @@ -31,33 +26,32 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati }; const browser = { name: '.NET Core Debug Blazor Web Assembly in Browser', - type: configuration.browser === 'edge' ? 'edge' : 'pwa-chrome', + type: configuration.browser === 'edge' ? 'pwa-msedge' : 'pwa-chrome', request: 'launch', - timeout: 30000, - url: configuration.url || 'https://localhost:5001', - webRoot: '${workspaceFolder}', + timeout: configuration.timeout, + url: configuration.url, + webRoot: configuration.webRoot, inspectUri: '{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}', + trace: configuration.trace || false, }; - this.vscodeType.debug.startDebugging(folder, app).then( - appStartFulfilled => { - if (appStartFulfilled) { - this.vscodeType.debug.startDebugging(folder, browser).then( - debugStartFulfilled => { - if (debugStartFulfilled) { - this.logger.logVerbose('Launching JavaScript debugger...'); - } - }, - error => { - this.logger.logError('Error when launching Chrome debugger: ', error); - }, - ); - } - }, - error => { - this.logger.logError('Error when launching application: ', error); - }, - ); + try { + await this.vscodeType.debug.startDebugging(folder, app); + try { + await this.vscodeType.debug.startDebugging(folder, browser); + this.logger.logVerbose('[DEBUGGER] Launching JavaScript debugger...'); + } catch (error) { + this.logger.logError( + '[DEBUGGER] Error when launching browser debugger: ', + error, + ); + } + } catch (error) { + this.logger.logError( + '[DEBUGGER] Error when launching application: ', + error, + ); + } return undefined; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts index 2b1487cf676..c7d26f274eb 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts @@ -192,23 +192,36 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC * On non-Windows platforms, we need to terminate the Blazor * dev server and its child processes. */ - vscodeType.debug.onDidTerminateDebugSession(event => { + vscodeType.debug.onDidTerminateDebugSession(async (event) => { logger.logVerbose('Terminating debugging session...'); if (process.platform !== 'win32') { - psList().then(processes => { + try { + const processes = await psList(); const devserver = processes.find( - (process: psList.ProcessDescriptor) => !!(process && process.cmd && process.cmd.includes('blazor-devserver')), + (process: psList.ProcessDescriptor) => + !!( + process && + process.cmd && + process.cmd.includes('blazor-devserver') + ), ); if (devserver) { const command = `kill ${devserver.pid}`; - exec(command, (error, stdout, stderr) => { + exec(command, (error) => { if (error) { - logger.logError('Error during debug process clean-up: ', error); + logger.logError( + '[DEBUGGER] Error during debug process clean-up: ', + error, + ); } - return logger.logMessage('Debug process clean-up complete.'); + return logger.logVerbose( + '[DEBUGGER] Debug process clean-up complete.', + ); }); } - }).catch(error => logger.logError('Error retrieving processes to clean-up: ', error)); + } catch (error) { + logger.logError('Error retrieving processes to clean-up: ', error); + } } }); From ce06cf1166b1a2cb1600f677638d7e2ff9d9f553 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Mon, 11 May 2020 16:50:32 -0700 Subject: [PATCH 03/13] Respond to more peer review --- .../package.json | 5 +++ .../BlazorDebugConfigurationProvider.ts | 14 +++++-- .../src/BlazorDebug/Events.ts | 42 +++++++++++++++++++ .../src/extension.ts | 38 ++--------------- 4 files changed, 61 insertions(+), 38 deletions(-) rename src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/{ => BlazorDebug}/BlazorDebugConfigurationProvider.ts (77%) create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json index 57727b24d4d..83ab4789c2a 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json @@ -69,6 +69,11 @@ "configurationAttributes": { "launch": { "properties": { + "cwd": { + "type": "string", + "description": "The directory of the Blazor WASM app, defaults to the workspace folder.", + "default": "${workspaceFolder}" + }, "env": { "type": "object", "description": "Environment variables passed to dotnet" diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts similarity index 77% rename from src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts rename to src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index ca2b2e4f933..6a3f1b4e5c7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; -import { RazorLogger } from './RazorLogger'; +import { RazorLogger } from '../RazorLogger'; export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurationProvider { @@ -18,7 +18,7 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati request: 'launch', program: 'dotnet', args: ['run'], - cwd: '${workspaceFolder}', + cwd: configuration.cwd, env: { ASPNETCORE_ENVIRONMENT: 'Development', ...configuration.env, @@ -34,23 +34,31 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati inspectUri: '{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}', trace: configuration.trace || false, }; + let showErrorInfo = false; try { await this.vscodeType.debug.startDebugging(folder, app); try { await this.vscodeType.debug.startDebugging(folder, browser); - this.logger.logVerbose('[DEBUGGER] Launching JavaScript debugger...'); + this.logger.logVerbose('[DEBUGGER] Launching browser debugger...'); } catch (error) { this.logger.logError( '[DEBUGGER] Error when launching browser debugger: ', error, ); + showErrorInfo = true; } } catch (error) { this.logger.logError( '[DEBUGGER] Error when launching application: ', error, ); + showErrorInfo = true; + } + + if (showErrorInfo) { + const message = `There was an unexpected error while launching your debugging session. Check the console for helpful logs and visit https://aka.ms/blazorwasmcodedebug for more info.`; + this.vscodeType.window.showErrorMessage(message); } return undefined; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts new file mode 100644 index 00000000000..9d80688bd72 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts @@ -0,0 +1,42 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import { exec } from 'child_process'; +import * as psList from 'ps-list'; +import { DebugSession } from 'vscode'; + +import { RazorLogger } from '../RazorLogger'; + +export async function onDidTerminateDebugSession( + event: DebugSession, + logger: RazorLogger, +) { + logger.logVerbose('Terminating debugging session...'); + if (process.platform !== 'win32') { + try { + const processes = await psList(); + const devserver = processes.find( + (process: psList.ProcessDescriptor) => + !!(process && process.cmd && process.cmd.includes('blazor-devserver')), + ); + if (devserver) { + const command = `kill ${devserver.pid}`; + exec(command, (error) => { + if (error) { + logger.logError( + '[DEBUGGER] Error during debug process clean-up: ', + error, + ); + } + return logger.logVerbose( + '[DEBUGGER] Debug process clean-up complete.', + ); + }); + } + } catch (error) { + logger.logError('Error retrieving processes to clean-up: ', error); + } + } +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts index c7d26f274eb..ab74c6cfaad 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts @@ -3,12 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -import { exec } from 'child_process'; -import * as psList from 'ps-list'; import * as vscode from 'vscode'; import * as vscodeapi from 'vscode'; import { ExtensionContext } from 'vscode'; -import { BlazorDebugConfigurationProvider } from './BlazorDebugConfigurationProvider'; +import { BlazorDebugConfigurationProvider } from './BlazorDebug/BlazorDebugConfigurationProvider'; +import { onDidTerminateDebugSession } from './BlazorDebug/Events'; import { CompositeCodeActionTranslator } from './CodeActions/CompositeRazorCodeActionTranslator'; import { RazorCodeActionProvider } from './CodeActions/RazorCodeActionProvider'; import { RazorFullyQualifiedCodeActionTranslator } from './CodeActions/RazorFullyQualifiedCodeActionTranslator'; @@ -192,38 +191,7 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC * On non-Windows platforms, we need to terminate the Blazor * dev server and its child processes. */ - vscodeType.debug.onDidTerminateDebugSession(async (event) => { - logger.logVerbose('Terminating debugging session...'); - if (process.platform !== 'win32') { - try { - const processes = await psList(); - const devserver = processes.find( - (process: psList.ProcessDescriptor) => - !!( - process && - process.cmd && - process.cmd.includes('blazor-devserver') - ), - ); - if (devserver) { - const command = `kill ${devserver.pid}`; - exec(command, (error) => { - if (error) { - logger.logError( - '[DEBUGGER] Error during debug process clean-up: ', - error, - ); - } - return logger.logVerbose( - '[DEBUGGER] Debug process clean-up complete.', - ); - }); - } - } catch (error) { - logger.logError('Error retrieving processes to clean-up: ', error); - } - } - }); + vscodeType.debug.onDidTerminateDebugSession(async event => onDidTerminateDebugSession(event, logger)); languageServerClient.onStarted(async () => { await documentManager.initialize(); From dbaabe5d52123ac992a4321f503294096ab2c4e8 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Mon, 11 May 2020 17:40:49 -0700 Subject: [PATCH 04/13] Clean up process termination logic --- .../src/BlazorDebug/Events.ts | 28 +++++++++---------- .../src/extension.ts | 2 +- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts index 9d80688bd72..d4510cfaca3 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -import { exec } from 'child_process'; import * as psList from 'ps-list'; import { DebugSession } from 'vscode'; @@ -18,22 +17,21 @@ export async function onDidTerminateDebugSession( try { const processes = await psList(); const devserver = processes.find( - (process: psList.ProcessDescriptor) => - !!(process && process.cmd && process.cmd.includes('blazor-devserver')), + (proc: psList.ProcessDescriptor) => + !!(proc && proc.cmd && proc.cmd.includes('blazor-devserver')), ); if (devserver) { - const command = `kill ${devserver.pid}`; - exec(command, (error) => { - if (error) { - logger.logError( - '[DEBUGGER] Error during debug process clean-up: ', - error, - ); - } - return logger.logVerbose( - '[DEBUGGER] Debug process clean-up complete.', - ); - }); + try { + process.kill(devserver.pid); + processes.map((proc) => { + if (process.ppid === devserver.pid) { + process.kill(proc.pid); + } + }); + logger.logVerbose('[DEBUGGER] Debug process clean-up complete.'); + } catch (error) { + logger.logError('Error terminating debug processes: ', error); + } } } catch (error) { logger.logError('Error retrieving processes to clean-up: ', error); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts index ab74c6cfaad..1318981f87d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts @@ -185,7 +185,7 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC }); const provider = new BlazorDebugConfigurationProvider(logger, vscodeType); - context.subscriptions.push(vscodeType.debug.registerDebugConfigurationProvider('blazor', provider)); + context.subscriptions.push(vscodeType.debug.registerDebugConfigurationProvider('blazorwasm', provider)); /** * On non-Windows platforms, we need to terminate the Blazor From 76fc7a948835bd4655fa9cbe6f9d7604032e284b Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Tue, 12 May 2020 12:31:59 -0700 Subject: [PATCH 05/13] Run Blazor app using spawn --- .../yarn.lock | 5 ++ .../BlazorDebugConfigurationProvider.ts | 50 +++++++++---------- .../yarn.lock | 5 ++ 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/yarn.lock b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/yarn.lock index f0d42f4315b..64b21132ae6 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/yarn.lock +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/yarn.lock @@ -257,6 +257,11 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +ps-list@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ps-list/-/ps-list-7.0.0.tgz#fd740a839786605d257117b899031db9b34b8b4b" + integrity sha512-ZDhdxqb+kE895BAvqIdGnWwfvB43h7KHMIcJC0hw7xLbbiJoprS+bqZxuGZ0jWdDxZEvB3jpnfgJyOn3lmsH+Q== + resolve@^1.3.2: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index 6a3f1b4e5c7..75019bcb1be 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -3,55 +3,55 @@ * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ +import { spawn } from 'child_process'; import * as vscode from 'vscode'; import { RazorLogger } from '../RazorLogger'; export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurationProvider { - constructor(private readonly logger: RazorLogger, private readonly vscodeType: typeof vscode) {} + constructor(private readonly logger: RazorLogger, private readonly vscodeType: typeof vscode) { } public async resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, configuration: vscode.DebugConfiguration): Promise { - const app = { - name: '.NET Core Launch (Blazor Standalone)', - type: 'coreclr', - request: 'launch', - program: 'dotnet', - args: ['run'], - cwd: configuration.cwd, + const output = this.vscodeType.window.createOutputChannel('Blazor WebAssembly App'); + const app = spawn('dotnet', ['run'], { + cwd: configuration.cwd || folder && folder.uri && folder.uri.fsPath, env: { + ...process.env, ASPNETCORE_ENVIRONMENT: 'Development', ...configuration.env, }, - }; + }); + + app.stdout.on('data', (data) => output.append(data.toString())); + app.stderr.on('data', (data) => output.append(data.toString())); + app.on('error', (error) => { + output.append(error.toString()); + this.logger.logError('[DEBUGGER] Error when launch app: ', error); + }); + + output.show(); + const browser = { name: '.NET Core Debug Blazor Web Assembly in Browser', type: configuration.browser === 'edge' ? 'pwa-msedge' : 'pwa-chrome', request: 'launch', - timeout: configuration.timeout, - url: configuration.url, - webRoot: configuration.webRoot, + timeout: configuration.timeout || 30000, + url: configuration.url || 'https://localhost:5001', + webRoot: configuration.webRoot || '${workspaceFolder}', inspectUri: '{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}', trace: configuration.trace || false, }; + let showErrorInfo = false; try { - await this.vscodeType.debug.startDebugging(folder, app); - try { - await this.vscodeType.debug.startDebugging(folder, browser); - this.logger.logVerbose('[DEBUGGER] Launching browser debugger...'); - } catch (error) { - this.logger.logError( - '[DEBUGGER] Error when launching browser debugger: ', - error, - ); - showErrorInfo = true; - } + await this.vscodeType.debug.startDebugging(folder, browser); + this.logger.logVerbose('[DEBUGGER] Launching browser debugger...'); } catch (error) { this.logger.logError( - '[DEBUGGER] Error when launching application: ', - error, + '[DEBUGGER] Error when launching browser debugger: ', + error, ); showErrorInfo = true; } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.VSCode.Test/yarn.lock b/src/Razor/test/Microsoft.AspNetCore.Razor.VSCode.Test/yarn.lock index 9f7ddf71141..00474d46974 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.VSCode.Test/yarn.lock +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.VSCode.Test/yarn.lock @@ -2606,6 +2606,11 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.3" +ps-list@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ps-list/-/ps-list-7.0.0.tgz#fd740a839786605d257117b899031db9b34b8b4b" + integrity sha512-ZDhdxqb+kE895BAvqIdGnWwfvB43h7KHMIcJC0hw7xLbbiJoprS+bqZxuGZ0jWdDxZEvB3jpnfgJyOn3lmsH+Q== + psl@^1.1.24, psl@^1.1.28: version "1.7.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" From d239662413931031d7e6b81f6a6852f1babdc98b Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Tue, 12 May 2020 14:55:03 -0700 Subject: [PATCH 06/13] Follow-ups to moving app launch to process spawn --- .../BlazorDebugConfigurationProvider.ts | 25 ++++++++++++ .../src/BlazorDebug/Events.ts | 39 +++++++++---------- .../src/extension.ts | 7 ---- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index 75019bcb1be..02dfb1bafff 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -7,6 +7,7 @@ import { spawn } from 'child_process'; import * as vscode from 'vscode'; import { RazorLogger } from '../RazorLogger'; +import { onDidTerminateDebugSession } from './Events'; export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurationProvider { @@ -29,6 +30,13 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati output.append(error.toString()); this.logger.logError('[DEBUGGER] Error when launch app: ', error); }); + app.on('exit', () => output.append('Blazor app terminated.')); + + /** + * On non-Windows platforms, we need to terminate the Blazor + * dev server and its child processes. + */ + this.vscodeType.debug.onDidTerminateDebugSession(event => onDidTerminateDebugSession(event, this.logger, app)); output.show(); @@ -41,11 +49,21 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati webRoot: configuration.webRoot || '${workspaceFolder}', inspectUri: '{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}', trace: configuration.trace || false, + noDebug: configuration.noDebug || false, }; let showErrorInfo = false; try { + /** + * The browser debugger will immediately launch after the + * application process is started. It waits a `timeout` + * interval before crashing after being unable to find the launched + * process. + * + * We do this to provide immediate visual feedback to the user + * that their debugger session has started. + */ await this.vscodeType.debug.startDebugging(folder, browser); this.logger.logVerbose('[DEBUGGER] Launching browser debugger...'); } catch (error) { @@ -61,6 +79,13 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati this.vscodeType.window.showErrorMessage(message); } + /** + * If `resolveDebugConfiguration` returns undefined, then the debugger + * launch is canceled. Here, we opt to manually launch the browser + * configruation using `startDebugging` above instead of returning + * the configuration to avoid a bug where VS Code is unable to resolve + * the debug adapter for the browser debugger. + */ return undefined; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts index d4510cfaca3..2e655c96a02 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ +import { ChildProcess } from 'child_process'; import * as psList from 'ps-list'; import { DebugSession } from 'vscode'; @@ -11,30 +12,26 @@ import { RazorLogger } from '../RazorLogger'; export async function onDidTerminateDebugSession( event: DebugSession, logger: RazorLogger, + devserver: ChildProcess, ) { logger.logVerbose('Terminating debugging session...'); - if (process.platform !== 'win32') { - try { - const processes = await psList(); - const devserver = processes.find( - (proc: psList.ProcessDescriptor) => - !!(proc && proc.cmd && proc.cmd.includes('blazor-devserver')), - ); - if (devserver) { - try { - process.kill(devserver.pid); - processes.map((proc) => { - if (process.ppid === devserver.pid) { - process.kill(proc.pid); - } - }); - logger.logVerbose('[DEBUGGER] Debug process clean-up complete.'); - } catch (error) { - logger.logError('Error terminating debug processes: ', error); - } + try { + const processes = await psList(); + if (devserver) { + try { + process.kill(devserver.pid); + processes.map((proc) => { + if (proc.ppid === devserver.pid) { + process.kill(proc.pid); + } + }); + logger.logVerbose('[DEBUGGER] Debug process clean-up complete.'); + } catch (error) { + logger.logError('Error terminating debug processes: ', error); } - } catch (error) { - logger.logError('Error retrieving processes to clean-up: ', error); } + } catch (error) { + logger.logError('Error retrieving processes to clean-up: ', error); } + } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts index 1318981f87d..23b1153e599 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/extension.ts @@ -7,7 +7,6 @@ import * as vscode from 'vscode'; import * as vscodeapi from 'vscode'; import { ExtensionContext } from 'vscode'; import { BlazorDebugConfigurationProvider } from './BlazorDebug/BlazorDebugConfigurationProvider'; -import { onDidTerminateDebugSession } from './BlazorDebug/Events'; import { CompositeCodeActionTranslator } from './CodeActions/CompositeRazorCodeActionTranslator'; import { RazorCodeActionProvider } from './CodeActions/RazorCodeActionProvider'; import { RazorFullyQualifiedCodeActionTranslator } from './CodeActions/RazorFullyQualifiedCodeActionTranslator'; @@ -187,12 +186,6 @@ export async function activate(vscodeType: typeof vscodeapi, context: ExtensionC const provider = new BlazorDebugConfigurationProvider(logger, vscodeType); context.subscriptions.push(vscodeType.debug.registerDebugConfigurationProvider('blazorwasm', provider)); - /** - * On non-Windows platforms, we need to terminate the Blazor - * dev server and its child processes. - */ - vscodeType.debug.onDidTerminateDebugSession(async event => onDidTerminateDebugSession(event, logger)); - languageServerClient.onStarted(async () => { await documentManager.initialize(); }); From ea2e7b48e08b89762e55ccfebd0fd54fca1eb86f Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Wed, 13 May 2020 11:43:13 -0700 Subject: [PATCH 07/13] Support unicode otuputs on Windows for spawned process --- .../package.json | 2 +- .../src/BlazorDebug/BlazorDebugConfigurationProvider.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json index 83ab4789c2a..a430c8c8a09 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json @@ -18,7 +18,7 @@ "activationEvents": [ "onWebviewPanel:razorReportIssue", "onDebugInitialConfigurations", - "onDebug", + "onDebugResolve:blazorwasm", "onDebugResolve:coreclr", "onDebugResolve:clr", "onLanguage:csharp", diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index 02dfb1bafff..82aa5686972 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -15,14 +15,19 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati public async resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, configuration: vscode.DebugConfiguration): Promise { const output = this.vscodeType.window.createOutputChannel('Blazor WebAssembly App'); - const app = spawn('dotnet', ['run'], { + + const command = process.platform === 'win32' ? 'cmd.exe' : 'sh'; + const args = process.platform === 'win32' ? ['/c', 'chcp 65001 >NUL & dotnet run'] : ['dotnet', 'run']; + const spawnOptions = { cwd: configuration.cwd || folder && folder.uri && folder.uri.fsPath, env: { ...process.env, ASPNETCORE_ENVIRONMENT: 'Development', ...configuration.env, }, - }); + }; + + const app = spawn(command, args, spawnOptions); app.stdout.on('data', (data) => output.append(data.toString())); app.stderr.on('data', (data) => output.append(data.toString())); From 79475e03b52273a148a04e0ed427d6132f23bad5 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Wed, 13 May 2020 12:02:29 -0700 Subject: [PATCH 08/13] Dispose terminate event listener on completion --- .../src/BlazorDebug/BlazorDebugConfigurationProvider.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index 82aa5686972..30fcaf25b04 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -41,7 +41,10 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati * On non-Windows platforms, we need to terminate the Blazor * dev server and its child processes. */ - this.vscodeType.debug.onDidTerminateDebugSession(event => onDidTerminateDebugSession(event, this.logger, app)); + const terminate = this.vscodeType.debug.onDidTerminateDebugSession(async event => { + await onDidTerminateDebugSession(event, this.logger, app); + terminate.dispose(); + }); output.show(); From b6795c757d9dde1c2b76ec13e07dc5f451b44df3 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Wed, 13 May 2020 14:26:49 -0700 Subject: [PATCH 09/13] Fix launch configuration for WSL --- .../src/BlazorDebug/BlazorDebugConfigurationProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index 30fcaf25b04..b52f966c6db 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -16,8 +16,8 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati public async resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, configuration: vscode.DebugConfiguration): Promise { const output = this.vscodeType.window.createOutputChannel('Blazor WebAssembly App'); - const command = process.platform === 'win32' ? 'cmd.exe' : 'sh'; - const args = process.platform === 'win32' ? ['/c', 'chcp 65001 >NUL & dotnet run'] : ['dotnet', 'run']; + const command = process.platform === 'win32' ? 'cmd.exe' : 'dotnet'; + const args = process.platform === 'win32' ? ['/c', 'chcp 65001 >NUL & dotnet run'] : ['run']; const spawnOptions = { cwd: configuration.cwd || folder && folder.uri && folder.uri.fsPath, env: { From 2ed3e9637fd3a02cb7b9128ba2451bb231fca5d6 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Wed, 13 May 2020 15:06:47 -0700 Subject: [PATCH 10/13] Use terminal as output to support colorized outputs --- .../BlazorDebugConfigurationProvider.ts | 23 ++++++++----------- .../src/BlazorDebug/Events.ts | 10 ++++---- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index b52f966c6db..9022ea6800b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -import { spawn } from 'child_process'; +// import { spawn } from 'child_process'; import * as vscode from 'vscode'; import { RazorLogger } from '../RazorLogger'; @@ -14,10 +14,8 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati constructor(private readonly logger: RazorLogger, private readonly vscodeType: typeof vscode) { } public async resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, configuration: vscode.DebugConfiguration): Promise { - const output = this.vscodeType.window.createOutputChannel('Blazor WebAssembly App'); - - const command = process.platform === 'win32' ? 'cmd.exe' : 'dotnet'; - const args = process.platform === 'win32' ? ['/c', 'chcp 65001 >NUL & dotnet run'] : ['run']; + const shellPath = process.platform === 'win32' ? 'cmd.exe' : 'dotnet'; + const shellArgs = process.platform === 'win32' ? ['/c', 'chcp 65001 >NUL & dotnet run'] : ['run']; const spawnOptions = { cwd: configuration.cwd || folder && folder.uri && folder.uri.fsPath, env: { @@ -27,22 +25,19 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati }, }; - const app = spawn(command, args, spawnOptions); - - app.stdout.on('data', (data) => output.append(data.toString())); - app.stderr.on('data', (data) => output.append(data.toString())); - app.on('error', (error) => { - output.append(error.toString()); - this.logger.logError('[DEBUGGER] Error when launch app: ', error); + const output = this.vscodeType.window.createTerminal({ + name: 'Blazor WebAssembly App', + shellPath, + shellArgs, + ...spawnOptions, }); - app.on('exit', () => output.append('Blazor app terminated.')); /** * On non-Windows platforms, we need to terminate the Blazor * dev server and its child processes. */ const terminate = this.vscodeType.debug.onDidTerminateDebugSession(async event => { - await onDidTerminateDebugSession(event, this.logger, app); + await onDidTerminateDebugSession(event, this.logger, await output.processId); terminate.dispose(); }); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts index 2e655c96a02..2454d0976dc 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -import { ChildProcess } from 'child_process'; import * as psList from 'ps-list'; import { DebugSession } from 'vscode'; @@ -12,16 +11,16 @@ import { RazorLogger } from '../RazorLogger'; export async function onDidTerminateDebugSession( event: DebugSession, logger: RazorLogger, - devserver: ChildProcess, + targetPid: number | undefined, ) { logger.logVerbose('Terminating debugging session...'); try { const processes = await psList(); - if (devserver) { + if (targetPid) { try { - process.kill(devserver.pid); + process.kill(targetPid); processes.map((proc) => { - if (proc.ppid === devserver.pid) { + if (proc.ppid === targetPid) { process.kill(proc.pid); } }); @@ -33,5 +32,4 @@ export async function onDidTerminateDebugSession( } catch (error) { logger.logError('Error retrieving processes to clean-up: ', error); } - } From 146d0dd6d3d7a687914c94ed8edc7bffd3ac1808 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Wed, 13 May 2020 21:09:48 -0700 Subject: [PATCH 11/13] Respond to peer review --- .../package.json | 8 +--- .../BlazorDebugConfigurationProvider.ts | 23 +++++------ .../src/BlazorDebug/Events.ts | 35 ---------------- .../src/BlazorDebug/TerminateDebugHandler.ts | 40 +++++++++++++++++++ 4 files changed, 52 insertions(+), 54 deletions(-) delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/TerminateDebugHandler.ts diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json index a430c8c8a09..ec22c996c2e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode.Extension/package.json @@ -71,13 +71,9 @@ "properties": { "cwd": { "type": "string", - "description": "The directory of the Blazor WASM app, defaults to the workspace folder.", + "description": "The directory of the Blazor WebAssembly app, defaults to the workspace folder.", "default": "${workspaceFolder}" }, - "env": { - "type": "object", - "description": "Environment variables passed to dotnet" - }, "url": { "type": "string", "description": "The URL of the application", @@ -93,7 +89,7 @@ "type": ["boolean", "string"], "default": "true", "enum": ["verbose", true], - "description": "If true, verbose logs sent to log file. If 'verbose', send logs to console." + "description": "If true, verbose logs from JS debugger are sent to log file. If 'verbose', send logs to console." }, "webRoot": { "type": "string", diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index 9022ea6800b..b96b327a7d6 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -3,11 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -// import { spawn } from 'child_process'; import * as vscode from 'vscode'; import { RazorLogger } from '../RazorLogger'; -import { onDidTerminateDebugSession } from './Events'; +import { onDidTerminateDebugSession } from './TerminateDebugHandler'; export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurationProvider { @@ -17,11 +16,10 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati const shellPath = process.platform === 'win32' ? 'cmd.exe' : 'dotnet'; const shellArgs = process.platform === 'win32' ? ['/c', 'chcp 65001 >NUL & dotnet run'] : ['run']; const spawnOptions = { - cwd: configuration.cwd || folder && folder.uri && folder.uri.fsPath, + cwd: configuration.cwd || (folder && folder.uri && folder.uri.fsPath), env: { ...process.env, ASPNETCORE_ENVIRONMENT: 'Development', - ...configuration.env, }, }; @@ -41,7 +39,7 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati terminate.dispose(); }); - output.show(); + output.show(/*preserveFocus*/true); const browser = { name: '.NET Core Debug Blazor Web Assembly in Browser', @@ -55,8 +53,6 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati noDebug: configuration.noDebug || false, }; - let showErrorInfo = false; - try { /** * The browser debugger will immediately launch after the @@ -74,12 +70,13 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati '[DEBUGGER] Error when launching browser debugger: ', error, ); - showErrorInfo = true; - } - - if (showErrorInfo) { - const message = `There was an unexpected error while launching your debugging session. Check the console for helpful logs and visit https://aka.ms/blazorwasmcodedebug for more info.`; - this.vscodeType.window.showErrorMessage(message); + const message = `There was an unexpected error while launching your debugging session. Check the console for helpful logs and visit the debugging docs for more info.`; + this.vscodeType.window.showErrorMessage(message, `View Debug Docs`, `Ignore`).then(async result => { + if (result === 'View Debug Docs') { + const debugDocsUri = 'https://aka.ms/blazorwasmcodedebug'; + await this.vscodeType.commands.executeCommand(`vcode.open`, debugDocsUri); + } + }); } /** diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts deleted file mode 100644 index 2454d0976dc..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/Events.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ - -import * as psList from 'ps-list'; -import { DebugSession } from 'vscode'; - -import { RazorLogger } from '../RazorLogger'; - -export async function onDidTerminateDebugSession( - event: DebugSession, - logger: RazorLogger, - targetPid: number | undefined, -) { - logger.logVerbose('Terminating debugging session...'); - try { - const processes = await psList(); - if (targetPid) { - try { - process.kill(targetPid); - processes.map((proc) => { - if (proc.ppid === targetPid) { - process.kill(proc.pid); - } - }); - logger.logVerbose('[DEBUGGER] Debug process clean-up complete.'); - } catch (error) { - logger.logError('Error terminating debug processes: ', error); - } - } - } catch (error) { - logger.logError('Error retrieving processes to clean-up: ', error); - } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/TerminateDebugHandler.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/TerminateDebugHandler.ts new file mode 100644 index 00000000000..500c42acd36 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/TerminateDebugHandler.ts @@ -0,0 +1,40 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as psList from 'ps-list'; +import { DebugSession } from 'vscode'; + +import { RazorLogger } from '../RazorLogger'; + +export async function onDidTerminateDebugSession( + event: DebugSession, + logger: RazorLogger, + targetPid: number | undefined, +) { + if (!targetPid) { + return; + } + + logger.logVerbose(`[DEBUGGER] Terminating debugging session with PID ${targetPid}...`); + + let processes: psList.ProcessDescriptor[] = []; + try { + processes = await psList(); + } catch (error) { + logger.logError(`Error retrieving processes under PID ${targetPid} to clean-up: `, error); + } + + try { + process.kill(targetPid); + processes.map((proc) => { + if (proc.ppid === targetPid) { + process.kill(proc.pid); + } + }); + logger.logVerbose(`[DEBUGGER] Debug process clean-up of PID ${targetPid} complete.`); + } catch (error) { + logger.logError(`[DEBUGGER] Error terminating debug processes with PID ${targetPid}: `, error); + } +} From 0fd5492b3bc2e049a8937a5162e6d24f613de392 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Thu, 14 May 2020 10:20:42 -0700 Subject: [PATCH 12/13] Remove ASPNETCORE_ENV variable from setting --- .../src/BlazorDebug/BlazorDebugConfigurationProvider.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts index b96b327a7d6..5058bdcc7a8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/BlazorDebugConfigurationProvider.ts @@ -17,10 +17,6 @@ export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurati const shellArgs = process.platform === 'win32' ? ['/c', 'chcp 65001 >NUL & dotnet run'] : ['run']; const spawnOptions = { cwd: configuration.cwd || (folder && folder.uri && folder.uri.fsPath), - env: { - ...process.env, - ASPNETCORE_ENVIRONMENT: 'Development', - }, }; const output = this.vscodeType.window.createTerminal({ From ea7b14457de90ba5b1671680419195d0d96ae08f Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Thu, 14 May 2020 12:16:43 -0700 Subject: [PATCH 13/13] Only stop devserver when JS debug sessions stop --- .../src/BlazorDebug/TerminateDebugHandler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/TerminateDebugHandler.ts b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/TerminateDebugHandler.ts index 500c42acd36..54467e1f729 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/TerminateDebugHandler.ts +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.VSCode/src/BlazorDebug/TerminateDebugHandler.ts @@ -13,6 +13,9 @@ export async function onDidTerminateDebugSession( logger: RazorLogger, targetPid: number | undefined, ) { + if (event.type !== 'pwa-chrome' && event.type !== 'pwa-msedge') { + return; + } if (!targetPid) { return; }