diff --git a/package.json b/package.json index 5d810c2fd188e..81ba528c3d3af 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta11", "tas-client-umd": "0.1.8", - "v8-inspect-profiler": "^0.1.0", + "v8-inspect-profiler": "^0.1.1", "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "9.0.0", diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 578bf1a282c44..211d1dbf3e535 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -324,6 +324,7 @@ export async function main(argv: string[]): Promise { // to get better profile traces. Last, we listen on stdout for a signal that tells us to // stop profiling. if (args['prof-startup']) { + const profileHost = '127.0.0.1'; const portMain = await findFreePort(randomPort(), 10, 3000); const portRenderer = await findFreePort(portMain + 1, 10, 3000); const portExthost = await findFreePort(portRenderer + 1, 10, 3000); @@ -335,9 +336,9 @@ export async function main(argv: string[]): Promise { const filenamePrefix = randomPath(homedir(), 'prof'); - addArg(argv, `--inspect-brk=${portMain}`); - addArg(argv, `--remote-debugging-port=${portRenderer}`); - addArg(argv, `--inspect-brk-extensions=${portExthost}`); + addArg(argv, `--inspect-brk=${profileHost}:${portMain}`); + addArg(argv, `--remote-debugging-port=${profileHost}:${portRenderer}`); + addArg(argv, `--inspect-brk-extensions=${profileHost}:${portExthost}`); addArg(argv, `--prof-startup-prefix`, filenamePrefix); addArg(argv, `--no-cached-data`); @@ -351,7 +352,7 @@ export async function main(argv: string[]): Promise { let session: ProfilingSession; try { - session = await profiler.startProfiling(opts); + session = await profiler.startProfiling({ ...opts, host: profileHost }); } catch (err) { console.error(`FAILED to start profiling for '${name}' on port '${opts.port}'`); } diff --git a/src/vs/platform/profiling/common/profiling.ts b/src/vs/platform/profiling/common/profiling.ts index c4bfe9ddd24d1..f4b4a302750dc 100644 --- a/src/vs/platform/profiling/common/profiling.ts +++ b/src/vs/platform/profiling/common/profiling.ts @@ -37,7 +37,7 @@ export interface IV8InspectProfilingService { _serviceBrand: undefined; - startProfiling(options: { port: number }): Promise; + startProfiling(options: { host: string; port: number }): Promise; stopProfiling(sessionId: string): Promise; } diff --git a/src/vs/platform/profiling/node/profilingService.ts b/src/vs/platform/profiling/node/profilingService.ts index 6187edd76c3c6..c3f218d047ce3 100644 --- a/src/vs/platform/profiling/node/profilingService.ts +++ b/src/vs/platform/profiling/node/profilingService.ts @@ -13,9 +13,9 @@ export class InspectProfilingService implements IV8InspectProfilingService { private readonly _sessions = new Map(); - async startProfiling(options: { port: number }): Promise { + async startProfiling(options: { host: string; port: number }): Promise { const prof = await import('v8-inspect-profiler'); - const session = await prof.startProfiling({ port: options.port, checkForPaused: true }); + const session = await prof.startProfiling({ host: options.host, port: options.port, checkForPaused: true }); const id = generateUuid(); this._sessions.set(id, session); return id; diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction.ts index e724779a5c0c6..4ba4300bff2a0 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction.ts @@ -53,7 +53,7 @@ export class DebugExtensionHostAction extends Action { type: 'node', name: nls.localize('debugExtensionHost.launch.name', "Attach Extension Host"), request: 'attach', - port: inspectPorts[0] + port: inspectPorts[0].port, }); } } diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts index bd147b70b7ebe..0ba85727065fb 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts @@ -139,7 +139,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio this._setState(ProfileSessionState.Starting); - return this._instantiationService.createInstance(ExtensionHostProfiler, inspectPorts[0]).start().then((value) => { + return this._instantiationService.createInstance(ExtensionHostProfiler, inspectPorts[0].host, inspectPorts[0].port).start().then((value) => { this._profileSession = value; this._setState(ProfileSessionState.Running); }, (err) => { diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsAutoProfiler.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsAutoProfiler.ts index 8c8124a413f8f..a5ce0e4238a0a 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsAutoProfiler.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionsAutoProfiler.ts @@ -75,9 +75,9 @@ export class ExtensionsAutoProfiler implements IWorkbenchContribution { return; } - const port = await event.getInspectPort(true); + const listener = await event.getInspectListener(true); - if (!port) { + if (!listener) { return; } @@ -95,7 +95,7 @@ export class ExtensionsAutoProfiler implements IWorkbenchContribution { let session: ProfileSession; try { - session = await this._instantiationService.createInstance(ExtensionHostProfiler, port).start(); + session = await this._instantiationService.createInstance(ExtensionHostProfiler, listener.host, listener.port).start(); } catch (err) { this._session = undefined; diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index b6d4f0f383114..77969d88de9a5 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -257,7 +257,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost super.dispose(); } - getInspectPort(): number | undefined { + getInspectPort(): undefined { return undefined; } diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 5dd9f3e9180cc..124b22f400b5b 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -13,6 +13,7 @@ import * as perf from 'vs/base/common/performance'; import { isCI } from 'vs/base/common/platform'; import { isEqualOrParent } from 'vs/base/common/resources'; import { StopWatch } from 'vs/base/common/stopwatch'; +import { isDefined } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -767,7 +768,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx this._onDidChangeResponsiveChange.fire({ extensionHostKind: processManager.kind, isResponsive: responsiveState === ResponsiveState.Responsive, - getInspectPort: (tryEnableInspector: boolean) => { + getInspectListener: (tryEnableInspector: boolean) => { return processManager.getInspectPort(tryEnableInspector); } }); @@ -1001,12 +1002,12 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return result; } - public async getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise { + public async getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise<{ port: number; host: string }[]> { const result = await Promise.all( this._getExtensionHostManagers(extensionHostKind).map(extHost => extHost.getInspectPort(tryEnableInspector)) ); // remove 0s: - return result.filter(element => Boolean(element)); + return result.filter(isDefined); } public async setRemoteEnvironment(env: { [key: string]: string | null }): Promise { diff --git a/src/vs/workbench/services/extensions/common/extensionHostManager.ts b/src/vs/workbench/services/extensions/common/extensionHostManager.ts index 79616e04b7de0..f7765f748cd05 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManager.ts @@ -354,7 +354,7 @@ export class ExtensionHostManager extends Disposable implements IExtensionHostMa this._resolvedActivationEvents.add(activationEvent); } - public async getInspectPort(tryEnableInspector: boolean): Promise { + public async getInspectPort(tryEnableInspector: boolean): Promise<{ port: number; host: string } | undefined> { if (this._extensionHost) { if (tryEnableInspector) { await this._extensionHost.enableInspectPort(); @@ -364,7 +364,8 @@ export class ExtensionHostManager extends Disposable implements IExtensionHostMa return port; } } - return 0; + + return undefined; } public async resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise { diff --git a/src/vs/workbench/services/extensions/common/extensionHostManagers.ts b/src/vs/workbench/services/extensions/common/extensionHostManagers.ts index 8f094a1044f6d..1b3b491ccd618 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostManagers.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostManagers.ts @@ -28,7 +28,7 @@ export interface IExtensionHostManager { activate(extension: ExtensionIdentifier, reason: ExtensionActivationReason): Promise; activateByEvent(activationEvent: string, activationKind: ActivationKind): Promise; activationEventIsDone(activationEvent: string): boolean; - getInspectPort(tryEnableInspector: boolean): Promise; + getInspectPort(tryEnableInspector: boolean): Promise<{ port: number; host: string } | undefined>; resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise; /** * Returns `null` if no resolver for `remoteAuthority` is found. diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 1b9f047f5c085..be8892975822e 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -125,7 +125,7 @@ export interface IExtensionHost { readonly onExit: Event<[number, string | null]>; start(): Promise; - getInspectPort(): number | undefined; + getInspectPort(): { port: number; host: string } | undefined; enableInspectPort(): Promise; dispose(): void; } @@ -367,7 +367,7 @@ export interface IResponsiveStateChangeEvent { /** * Return the inspect port or `0`. `0` means inspection is not possible. */ - getInspectPort(tryEnableInspector: boolean): Promise; + getInspectListener(tryEnableInspector: boolean): Promise<{ port: number; host: string } | undefined>; } export const enum ActivationKind { @@ -505,7 +505,7 @@ export interface IExtensionService { /** * Return the inspect ports (if inspection is possible) for extension hosts of kind `extensionHostKind`. */ - getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise; + getInspectPorts(extensionHostKind: ExtensionHostKind, tryEnableInspector: boolean): Promise<{ port: number; host: string }[]>; /** * Stops the extension hosts. @@ -585,7 +585,7 @@ export class NullExtensionService implements IExtensionService { getExtension() { return Promise.resolve(undefined); } readExtensionPointContributions(_extPoint: IExtensionPoint): Promise[]> { return Promise.resolve(Object.create(null)); } getExtensionsStatus(): { [id: string]: IExtensionsStatus } { return Object.create(null); } - getInspectPorts(_extensionHostKind: ExtensionHostKind, _tryEnableInspector: boolean): Promise { return Promise.resolve([]); } + getInspectPorts(_extensionHostKind: ExtensionHostKind, _tryEnableInspector: boolean): Promise<{ port: number; host: string }[]> { return Promise.resolve([]); } stopExtensionHosts(): any { } async startExtensionHosts(): Promise { } async setRemoteEnvironment(_env: { [key: string]: string | null }): Promise { } diff --git a/src/vs/workbench/services/extensions/common/lazyCreateExtensionHostManager.ts b/src/vs/workbench/services/extensions/common/lazyCreateExtensionHostManager.ts index eb23d8d45c9be..f279e796d1328 100644 --- a/src/vs/workbench/services/extensions/common/lazyCreateExtensionHostManager.ts +++ b/src/vs/workbench/services/extensions/common/lazyCreateExtensionHostManager.ts @@ -137,12 +137,9 @@ export class LazyCreateExtensionHostManager extends Disposable implements IExten } return true; } - public async getInspectPort(tryEnableInspector: boolean): Promise { + public async getInspectPort(tryEnableInspector: boolean): Promise<{ port: number; host: string } | undefined> { await this._startCalled.wait(); - if (this._actual) { - return this._actual.getInspectPort(tryEnableInspector); - } - return 0; + return this._actual?.getInspectPort(tryEnableInspector); } public async resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise { await this._startCalled.wait(); diff --git a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts index 69184c22b2ec7..5148918bbbbb9 100644 --- a/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts +++ b/src/vs/workbench/services/extensions/common/remoteExtensionHost.ts @@ -255,7 +255,7 @@ export class RemoteExtensionHost extends Disposable implements IExtensionHost { }; } - getInspectPort(): number | undefined { + getInspectPort(): undefined { return undefined; } diff --git a/src/vs/workbench/services/extensions/electron-sandbox/extensionHostProfiler.ts b/src/vs/workbench/services/extensions/electron-sandbox/extensionHostProfiler.ts index a5907cf52d0d2..f771fb4912975 100644 --- a/src/vs/workbench/services/extensions/electron-sandbox/extensionHostProfiler.ts +++ b/src/vs/workbench/services/extensions/electron-sandbox/extensionHostProfiler.ts @@ -14,6 +14,7 @@ import { createSingleCallFunction } from 'vs/base/common/functional'; export class ExtensionHostProfiler { constructor( + private readonly _host: string, private readonly _port: number, @IExtensionService private readonly _extensionService: IExtensionService, @IV8InspectProfilingService private readonly _profilingService: IV8InspectProfilingService, @@ -22,7 +23,7 @@ export class ExtensionHostProfiler { public async start(): Promise { - const id = await this._profilingService.startProfiling({ port: this._port }); + const id = await this._profilingService.startProfiling({ host: this._host, port: this._port }); return { stop: createSingleCallFunction(async () => { diff --git a/src/vs/workbench/services/extensions/electron-sandbox/localProcessExtensionHost.ts b/src/vs/workbench/services/extensions/electron-sandbox/localProcessExtensionHost.ts index ea4330739f560..49a9a69a671ba 100644 --- a/src/vs/workbench/services/extensions/electron-sandbox/localProcessExtensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-sandbox/localProcessExtensionHost.ts @@ -109,7 +109,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost { private _terminating: boolean; // Resources, in order they get acquired/created when .start() is called: - private _inspectPort: number | null; + private _inspectListener: { port: number; host: string } | null; private _extensionHostProcess: ExtensionHostProcess | null; private _messageProtocol: Promise | null; @@ -141,7 +141,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost { this._terminating = false; - this._inspectPort = null; + this._inspectListener = null; this._extensionHostProcess = null; this._messageProtocol = null; @@ -221,10 +221,11 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost { silent: true }; + const inspectHost = '127.0.0.1'; if (portNumber !== 0) { opts.execArgv = [ '--nolazy', - (this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + portNumber + (this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + `${inspectHost}:${portNumber}` ]; } else { opts.execArgv = ['--inspect-port=0']; @@ -259,13 +260,14 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost { // Print out extension host output this._toDispose.add(onDebouncedOutput(output => { - const inspectorUrlMatch = output.data && output.data.match(/ws:\/\/([^\s]+:(\d+)\/[^\s]+)/); + const inspectorUrlMatch = output.data && output.data.match(/ws:\/\/([^\s]+):(\d+)\/[^\s]+/); if (inspectorUrlMatch) { + const [, host, port] = inspectorUrlMatch; if (!this._environmentService.isBuilt && !this._isExtensionDevTestFromCli) { console.log(`%c[Extension Host] %cdebugger inspector at devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=${inspectorUrlMatch[1]}`, 'color: blue', 'color:'); } - if (!this._inspectPort) { - this._inspectPort = Number(inspectorUrlMatch[2]); + if (!this._inspectListener) { + this._inspectListener = { host, port: Number(port) }; this._onDidSetInspectPort.fire(); } } else { @@ -283,10 +285,10 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost { // Notify debugger that we are ready to attach to the process if we run a development extension if (portNumber) { - if (this._isExtensionDevHost && portNumber && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) { + if (this._isExtensionDevHost && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) { this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, portNumber); } - this._inspectPort = portNumber; + this._inspectListener = { port: portNumber, host: inspectHost }; this._onDidSetInspectPort.fire(); } @@ -555,7 +557,7 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost { } public async enableInspectPort(): Promise { - if (typeof this._inspectPort === 'number') { + if (!!this._inspectListener) { return true; } @@ -569,11 +571,11 @@ export class NativeLocalProcessExtensionHost implements IExtensionHost { } await Promise.race([Event.toPromise(this._onDidSetInspectPort.event), timeout(1000)]); - return typeof this._inspectPort === 'number'; + return !!this._inspectListener; } - public getInspectPort(): number | undefined { - return this._inspectPort ?? undefined; + public getInspectPort(): { port: number; host: string } | undefined { + return this._inspectListener ?? undefined; } private _onWillShutdown(event: WillShutdownEvent): void { diff --git a/yarn.lock b/yarn.lock index 8a28cf43776e9..245a211ddde4c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2614,10 +2614,10 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== -chrome-remote-interface@0.28.2: - version "0.28.2" - resolved "https://registry.yarnpkg.com/chrome-remote-interface/-/chrome-remote-interface-0.28.2.tgz#6be3554d2c227ff07eb74baa7e5d4911da12a5a6" - integrity sha512-F7mjof7rWvRNsJqhVXuiFU/HWySCxTA9tzpLxUJxVfdLkljwFJ1aMp08AnwXRmmP7r12/doTDOMwaNhFCJsacw== +chrome-remote-interface@^0.33.0: + version "0.33.0" + resolved "https://registry.yarnpkg.com/chrome-remote-interface/-/chrome-remote-interface-0.33.0.tgz#9140b5612ee5cdc39212cd0296d3b61ea881c47a" + integrity sha512-tv/SgeBfShXk43fwFpQ9wnS7mOCPzETnzDXTNxCb6TqKOiOeIfbrJz+2NAp8GmzwizpKa058wnU1Te7apONaYg== dependencies: commander "2.11.x" ws "^7.2.0" @@ -9768,12 +9768,12 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -v8-inspect-profiler@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/v8-inspect-profiler/-/v8-inspect-profiler-0.1.0.tgz#0d3f80e2dc878f737c31ae7ff4c033425a33a724" - integrity sha512-K7RyY4p59+rIPvgcTN/Oo7VU9cJ68LOl+dz8RCh/M4VwbZ9yS3Ci+qajbMDojW207anNn7CehkLvqpSIrNT9oA== +v8-inspect-profiler@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/v8-inspect-profiler/-/v8-inspect-profiler-0.1.1.tgz#52fd9f1234dca2f650063c6cd39bdaef47b49396" + integrity sha512-GB3X9w7w+y9v4gq85olmf/bM3F2hj2DjjwvVpDXIziW5JBy8cDcIQ/K7m8xJVDWiFemxRX2Dxoo1k6JDvLMTig== dependencies: - chrome-remote-interface "0.28.2" + chrome-remote-interface "^0.33.0" v8-to-istanbul@^9.0.0: version "9.2.0"