Skip to content

Commit

Permalink
chore: move network view behind a setting (#2059)
Browse files Browse the repository at this point in the history
We don't want it to appear for everyone quite yet: move it behind an
experimental setting.

Swaps the controls around from the session enabling networking eagerly
to being a call from the extension side to do so.
  • Loading branch information
connor4312 authored Aug 28, 2024
1 parent 34348f2 commit ab03c68
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 68 deletions.
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"configuration.resourceRequestOptions": "Request options to use when loading resources, such as source maps, in the debugger. You may need to configure this if your sourcemaps require authentication or use a self-signed certificate, for instance. Options are used to create a request using the [`got`](https://github.com/sindresorhus/got) library.\n\nA common case to disable certificate verification can be done by passing `{ \"https\": { \"rejectUnauthorized\": false } }`.",
"configuration.terminalOptions": "Default launch options for the JavaScript debug terminal and npm scripts.",
"configuration.unmapMissingSources": "Configures whether sourcemapped file where the original file can't be read will automatically be unmapped. If this is false (default), a prompt is shown.",
"configuration.enableNetworkView": "Enables the experimental network view for targets that support it.",
"createDiagnostics.label": "Diagnose Breakpoint Problems",
"customDescriptionGenerator.description": "Customize the textual description the debugger shows for objects (local variables, etc...). Samples:\n 1. this.toString() // will call toString to print all objects\n 2. this.customDescription ? this.customDescription() : defaultValue // Use customDescription method if available, if not return defaultValue\n 3. function (def) { return this.customDescription ? this.customDescription() : def } // Use customDescription method if available, if not return defaultValue\n ",
"customPropertiesGenerator.description": "Customize the properties shown for an object in the debugger (local variables, etc...). Samples:\n 1. { ...this, extraProperty: '12345' } // Add an extraProperty 12345 to all objects\n 2. this.customProperties ? this.customProperties() : this // Use customProperties method if available, if not use the properties in this (the default properties)\n 3. function () { return this.customProperties ? this.customProperties() : this } // Use customDescription method if available, if not return the default properties\n\n Deprecated: This is a temporary implementation of this feature until we have time to implement it in the way described here: https://github.com/microsoft/vscode/issues/102181",
Expand Down
1 change: 1 addition & 0 deletions src/adapter/debugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export class DebugAdapter implements IDisposable {
this.dap.on('setDebuggerProperty', params => this._setDebuggerProperty(params));
this.dap.on('setSymbolOptions', params => this._setSymbolOptions(params));
this.dap.on('networkCall', params => this._doNetworkCall(params));
this.dap.on('enableNetworking', params => this._withThread(t => t.enableNetworking(params)));
}

private async _doNetworkCall({ method, params }: Dap.NetworkCallParams) {
Expand Down
44 changes: 23 additions & 21 deletions src/adapter/threads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { DebugType } from '../common/contributionUtils';
import { EventEmitter } from '../common/events';
import { HrTime } from '../common/hrnow';
import { ILogger, LogTag } from '../common/logging';
import { mirroredNetworkEvents } from '../common/networkEvents';
import { isInstanceOf, truthy } from '../common/objUtils';
import { Base0Position, Base1Position, Range } from '../common/positions';
import { IDeferred, delay, getDeferred } from '../common/promiseUtil';
Expand Down Expand Up @@ -741,26 +740,6 @@ export class Thread implements IVariableStoreLocationProvider {
} else this._revealObject(event.object);
});

if (!this.launchConfig.noDebug) {
// Use whether we can make a cookies request to feature-request the
// availability of networking.
this._cdp.Network.enable({}).then(r => {
if (!r) {
return;
}

this._dap.with(dap => {
dap.networkAvailable({});
for (const event of mirroredNetworkEvents) {
// the types don't work well with the overloads on Network.on, a cast is needed:
(this._cdp.Network.on as (ev: string, fn: (d: object) => void) => void)(event, data =>
dap.networkEvent({ data, event }),
);
}
});
});
}

this._cdp.Debugger.on('paused', async event => this._onPaused(event));
this._cdp.Debugger.on('resumed', () => this.onResumed());
this._cdp.Debugger.on('scriptParsed', event => this._onScriptParsed(event));
Expand Down Expand Up @@ -791,6 +770,29 @@ export class Thread implements IVariableStoreLocationProvider {
this._dap.resolve();
}

/**
* Tries to enable networking for the target
*/
async enableNetworking({
mirrorEvents,
}: Dap.EnableNetworkingParams): Promise<Dap.EnableNetworkingResult> {
const ok = await this._cdp.Network.enable({});
if (!ok) {
throw errors.networkingNotAvailable();
}

this._dap.with(dap => {
for (const event of mirrorEvents) {
// the types don't work well with the overloads on Network.on, a cast is needed:
(this._cdp.Network.on as (ev: string, fn: (d: object) => void) => void)(event, data =>
dap.networkEvent({ data, event }),
);
}
});

return {};
}

/**
* Implements DAP `stepInTargets` request.
*
Expand Down
24 changes: 18 additions & 6 deletions src/build/dapCustom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -730,12 +730,6 @@ const dapCustom: JSONSchema4 = {
'Arguments for "setSymbolOptions" request. Properties are determined by debugger.',
},

...makeEvent(
'networkAvailable',
'Fired when we successfully enable CDP networking on the session.',
{},
),

...makeEvent(
'networkEvent',
'A wrapped CDP network event. There is little abstraction here because UI interacts literally with CDP at the moment.',
Expand Down Expand Up @@ -774,6 +768,24 @@ const dapCustom: JSONSchema4 = {
type: 'object',
},
),

...makeRequest(
'enableNetworking',
'Attempts to enable networking on the target.',
{
properties: {
mirrorEvents: {
type: 'array',
items: { type: 'string' },
description: 'CDP network domain events to mirror (e.g. "requestWillBeSent")',
},
},
required: ['mirrorEvents'],
},
{
type: 'object',
},
),
},
};

Expand Down
5 changes: 5 additions & 0 deletions src/build/generate-contributions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,11 @@ const configurationSchema: ConfigurationAttributes<IConfigurationTypes> = {
default: {},
markdownDescription: refString('configuration.resourceRequestOptions'),
},
[Configuration.EnableNetworkView]: {
type: 'boolean',
default: false,
description: refString('configuration.enableNetworkView'),
},
};

const commands: ReadonlyArray<{
Expand Down
2 changes: 2 additions & 0 deletions src/common/contributionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export const enum Configuration {
UnmapMissingSources = 'debug.javascript.unmapMissingSources',
DefaultRuntimeExecutables = 'debug.javascript.defaultRuntimeExecutable',
ResourceRequestOptions = 'debug.javascript.resourceRequestOptions',
EnableNetworkView = 'debug.javascript.enableNetworkView',
}

export type DebugByLinkState = 'on' | 'off' | 'always';
Expand All @@ -193,6 +194,7 @@ export interface IConfigurationTypes {
[Configuration.UnmapMissingSources]: boolean;
[Configuration.DefaultRuntimeExecutables]: { [K in DebugType]?: string };
[Configuration.ResourceRequestOptions]: Partial<OptionsOfBufferResponseBody>;
[Configuration.EnableNetworkView]: boolean;
}

export interface IStackFrameContext {
Expand Down
43 changes: 26 additions & 17 deletions src/dap/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1157,11 +1157,6 @@ export namespace Dap {
*/
setSymbolOptionsRequest(params: SetSymbolOptionsParams): Promise<SetSymbolOptionsResult>;

/**
* Fired when we successfully enable CDP networking on the session.
*/
networkAvailable(params: NetworkAvailableEventParams): void;

/**
* A wrapped CDP network event. There is little abstraction here because UI interacts literally with CDP at the moment.
*/
Expand All @@ -1178,6 +1173,18 @@ export namespace Dap {
* Makes a network call. There is little abstraction here because UI interacts literally with CDP at the moment.
*/
networkCallRequest(params: NetworkCallParams): Promise<NetworkCallResult>;

/**
* Attempts to enable networking on the target.
*/
on(
request: 'enableNetworking',
handler: (params: EnableNetworkingParams) => Promise<EnableNetworkingResult | Error>,
): () => void;
/**
* Attempts to enable networking on the target.
*/
enableNetworkingRequest(params: EnableNetworkingParams): Promise<EnableNetworkingResult>;
}

export interface TestApi {
Expand Down Expand Up @@ -1939,16 +1946,6 @@ export namespace Dap {
*/
setSymbolOptions(params: SetSymbolOptionsParams): Promise<SetSymbolOptionsResult>;

/**
* Fired when we successfully enable CDP networking on the session.
*/
on(request: 'networkAvailable', handler: (params: NetworkAvailableEventParams) => void): void;
off(request: 'networkAvailable', handler: (params: NetworkAvailableEventParams) => void): void;
once(
request: 'networkAvailable',
filter?: (event: NetworkAvailableEventParams) => boolean,
): Promise<NetworkAvailableEventParams>;

/**
* A wrapped CDP network event. There is little abstraction here because UI interacts literally with CDP at the moment.
*/
Expand All @@ -1963,6 +1960,11 @@ export namespace Dap {
* Makes a network call. There is little abstraction here because UI interacts literally with CDP at the moment.
*/
networkCall(params: NetworkCallParams): Promise<NetworkCallResult>;

/**
* Attempts to enable networking on the target.
*/
enableNetworking(params: EnableNetworkingParams): Promise<EnableNetworkingResult>;
}

export interface AttachParams {
Expand Down Expand Up @@ -2263,6 +2265,15 @@ export namespace Dap {

export interface DisconnectResult {}

export interface EnableNetworkingParams {
/**
* CDP network domain events to mirror (e.g. "requestWillBeSent")
*/
mirrorEvents: string[];
}

export interface EnableNetworkingResult {}

export interface EvaluateParams {
/**
* The expression to evaluate.
Expand Down Expand Up @@ -2946,8 +2957,6 @@ export namespace Dap {
totalModules?: integer;
}

export interface NetworkAvailableEventParams {}

export interface NetworkCallParams {
/**
* The HTTP method
Expand Down
2 changes: 2 additions & 0 deletions src/dap/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ export const sourceMapParseFailed = (compiledUrl: string, message: string) =>
export const uwpPipeNotAvailable = () =>
createUserError(l10n.t('UWP webview debugging is not available on your platform.'));

export const networkingNotAvailable = () => createUserError(l10n.t('Networking not available.'));

export const noUwpPipeFound = () =>
createUserError(
l10n.t(
Expand Down
2 changes: 2 additions & 0 deletions src/dap/telemetryClassification.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,6 @@ interface IDAPOperationClassification {
'!setsymboloptions.errors': { classification: 'CallstackOrException'; purpose: 'PerformanceAndHealth' };
networkcall: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth' };
'!networkcall.errors': { classification: 'CallstackOrException'; purpose: 'PerformanceAndHealth' };
enablenetworking: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth' };
'!enablenetworking.errors': { classification: 'CallstackOrException'; purpose: 'PerformanceAndHealth' };
}
17 changes: 0 additions & 17 deletions src/ui/debugSessionTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,9 @@ export class DebugSessionTracker implements vscode.Disposable {

private _onSessionAddedEmitter = new vscode.EventEmitter<vscode.DebugSession>();
private _onSessionEndedEmitter = new vscode.EventEmitter<vscode.DebugSession>();
private _onNetworkAvailabilityChangeEmitter = new vscode.EventEmitter<vscode.DebugSession>();
private _disposables: vscode.Disposable[] = [];
private readonly networkAvailable = new WeakSet<vscode.DebugSession>();
private readonly sessions = new Map<string, vscode.DebugSession>();

/**
* Fired when networking becomes available for a debug session.
*/
public onNetworkAvailabilityChanged = this._onNetworkAvailabilityChangeEmitter.event;

/**
* Fires when any new js-debug session comes in.
*/
Expand All @@ -77,13 +70,6 @@ export class DebugSessionTracker implements vscode.Disposable {
return this.sessions.get(id);
}

/**
* Gets whether networkign is available in the session.
*/
public isNetworkAvailable(session: vscode.DebugSession) {
return this.networkAvailable.has(session);
}

/**
* Gets whether the js-debug session is still running.
*/
Expand Down Expand Up @@ -154,9 +140,6 @@ export class DebugSessionTracker implements vscode.Disposable {
} else if (event.event === 'copyRequested') {
const params = event.body as Dap.CopyRequestedEventParams;
vscode.env.clipboard.writeText(params.text);
} else if (event.event === 'networkAvailable') {
this.networkAvailable.add(event.session);
this._onNetworkAvailabilityChangeEmitter.fire(event.session);
}
},
undefined,
Expand Down
31 changes: 24 additions & 7 deletions src/ui/networkTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import * as vscode from 'vscode';
import Cdp from '../cdp/api';
import {
Commands,
Configuration,
ContextKey,
CustomViews,
DebugType,
networkFilesystemScheme,
readConfig,
registerCommand,
setContextKey,
} from '../common/contributionUtils';
import { DisposableList, noOpDisposable } from '../common/disposable';
import { IMirroredNetworkEvents } from '../common/networkEvents';
import { IMirroredNetworkEvents, mirroredNetworkEvents } from '../common/networkEvents';
import { assertNever, once } from '../common/objUtils';
import Dap from '../dap/api';
import { IExtensionContribution } from '../ioc-extras';
Expand All @@ -38,12 +40,6 @@ export class NetworkTree implements IExtensionContribution, vscode.TreeDataProvi
@inject(DebugSessionTracker) private readonly debugSessionTracker: DebugSessionTracker,
) {
this.disposables.push(
this.debugSessionTracker.onNetworkAvailabilityChanged(session => {
this.models.set(session.id, new NetworkModel(session));
if (session === vscode.debug.activeDebugSession) {
this.listenToActiveSession();
}
}),
vscode.debug.onDidChangeActiveDebugSession(() => {
this.listenToActiveSession();
}),
Expand All @@ -55,6 +51,23 @@ export class NetworkTree implements IExtensionContribution, vscode.TreeDataProvi
this.models.get(event.session.id)?.append([event.body.event, event.body.data]);
}
}),
this.debugSessionTracker.onSessionAdded(session => {
if (!this.isEnabled()) {
return;
}

session.customRequest('enableNetworking', { mirrorEvents: mirroredNetworkEvents }).then(
() => {
this.models.set(session.id, new NetworkModel(session));
if (session === vscode.debug.activeDebugSession) {
this.listenToActiveSession();
}
},
() => {
/* ignored */
},
);
}),

registerCommand(
vscode.commands,
Expand Down Expand Up @@ -130,6 +143,10 @@ export class NetworkTree implements IExtensionContribution, vscode.TreeDataProvi
);
}

private isEnabled() {
return readConfig(vscode.workspace, Configuration.EnableNetworkView);
}

private listenToActiveSession() {
this.activeListeners.clear();
const model = (this.current =
Expand Down

0 comments on commit ab03c68

Please sign in to comment.