From 4c59042cf1331fea3fa4bbef86824df7ad90ecb5 Mon Sep 17 00:00:00 2001 From: Sasha Joseph Date: Tue, 4 Sep 2018 18:21:50 -0700 Subject: [PATCH] Use nullable `targetTypes` property for advanced debugging configurations. --- README.md | 1 + package.json | 5 +++++ package.nls.json | 1 + src/chromeDebug.ts | 4 ++-- src/chromeDebugAdapter.ts | 6 ++++++ src/chromeDebugInterfaces.d.ts | 2 ++ src/extension.ts | 8 ++++---- src/utils.ts | 13 ++++++++++--- test/chromeDebugAdapter.test.ts | 3 +++ test/utils.test.ts | 20 +++++++++++++++++++- 10 files changed, 53 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4ead912..886b070 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,7 @@ See our wiki page for some configured example apps: [Examples](https://github.co * `userDataDir`: Normally, if Chrome is already running when you start debugging with a launch config, then the new instance won't start in remote debugging mode. So by default, the extension launches Chrome with a separate user profile in a temp folder. Use this option to set a different path to use, or set to false to launch with your default user profile. * `url`: On a 'launch' config, it will launch Chrome at this URL. * `urlFilter`: On an 'attach' config, or a 'launch' config with no 'url' set, search for a page with this url and attach to it. It can also contain wildcards, for example, `"localhost:*/app"` will match either `"http://localhost:123/app"` or `"http://localhost:456/app"`, but not `"https://stackoverflow.com"`. +* `targetTypes`: On an 'attach' config, or a 'launch' config with no 'url' set, set a list of acceptable target types from the default `["page"]`. For example, if you are attaching to an Electron app, you might want to set this to `["page", "webview"]`. A value of `null` disables filtering by target type. * `sourceMaps`: By default, the adapter will use sourcemaps and your original sources whenever possible. You can disable this by setting `sourceMaps` to false. * `pathMapping`: This property takes a mapping of URL paths to local paths, to give you more flexibility in how URLs are resolved to local files. `"webRoot": "${workspaceFolder}"` is just shorthand for a pathMapping like `{ "/": "${workspaceFolder}" }`. * `smartStep`: Automatically steps over code that doesn't map to source files. Especially useful for debugging with async/await. diff --git a/package.json b/package.json index 4626161..369489c 100644 --- a/package.json +++ b/package.json @@ -381,6 +381,11 @@ "description": "%chrome.urlFilter.description%", "default": "" }, + "targetTypes": { + "type": ["array", "null"], + "description": "%chrome.targetTypes.description%", + "default": ["page"] + }, "showAsyncStacks": { "type": "boolean", "description": "%chrome.showAsyncStacks.description%", diff --git a/package.nls.json b/package.nls.json index 19b758d..a1e7212 100644 --- a/package.nls.json +++ b/package.nls.json @@ -25,6 +25,7 @@ "chrome.timeout.description": "Retry for this number of milliseconds to connect to Chrome. Default is 10000 ms.", "chrome.disableNetworkCache.description": "Controls whether to skip the network cache for each request", "chrome.urlFilter.description": "Will search for a page with this url and attach to it, if found. Can have * wildcards.", + "chrome.targetTypes.description": "An array of acceptable target types. The default is `[\"page\"]`.", "chrome.showAsyncStacks.description": "Show the async calls that led to the current call stack", "chrome.breakOnLoad.description": "Experimental feature - If true, the debug adapter will attempt to set breakpoints in scripts before they are loaded, so it can hit breakpoints at the beginnings of those scripts. Has a perf impact.", "chrome.breakOnLoadStrategy.description": "The strategy to use for breakOnLoad.", diff --git a/src/chromeDebug.ts b/src/chromeDebug.ts index 2d73680..374a06e 100644 --- a/src/chromeDebug.ts +++ b/src/chromeDebug.ts @@ -5,7 +5,7 @@ import { ChromeDebugSession, logger, UrlPathTransformer, BaseSourceMapTransformer, telemetry } from 'vscode-chrome-debug-core'; import * as path from 'path'; import * as os from 'os'; -import { targetFilter } from './utils'; +import { defaultTargetFilter } from './utils'; import { ChromeDebugAdapter } from './chromeDebugAdapter'; @@ -18,7 +18,7 @@ ChromeDebugSession.run(ChromeDebugSession.getSession( adapter: ChromeDebugAdapter, extensionName: EXTENSION_NAME, logFilePath: path.resolve(os.tmpdir(), 'vscode-chrome-debug.txt'), - targetFilter, + targetFilter: defaultTargetFilter, pathTransformer: UrlPathTransformer, sourceMapTransformer: BaseSourceMapTransformer, diff --git a/src/chromeDebugAdapter.ts b/src/chromeDebugAdapter.ts index 0151cd8..91130a7 100644 --- a/src/chromeDebugAdapter.ts +++ b/src/chromeDebugAdapter.ts @@ -206,6 +206,12 @@ export class ChromeDebugAdapter extends CoreDebugAdapter { args.sourceMapPathOverrides = getSourceMapPathOverrides(args.webRoot, args.sourceMapPathOverrides); args.skipFileRegExps = ['^chrome-extension:.*']; + if (args.targetTypes === undefined) { + args.targetFilter = utils.defaultTargetFilter; + } else { + args.targetFilter = utils.getTargetFilter(args.targetTypes); + } + super.commonArgs(args); } diff --git a/src/chromeDebugInterfaces.d.ts b/src/chromeDebugInterfaces.d.ts index 048b82c..72f18a2 100644 --- a/src/chromeDebugInterfaces.d.ts +++ b/src/chromeDebugInterfaces.d.ts @@ -8,6 +8,8 @@ import { DebugProtocol } from 'vscode-debugprotocol'; export interface ICommonRequestArgs extends Core.ICommonRequestArgs { webRoot?: string; disableNetworkCache?: boolean; + targetTypes?: string[]; + targetFilter?: Core.chromeConnection.ITargetFilter; urlFilter?: string; } diff --git a/src/extension.ts b/src/extension.ts index 4fa891e..dee175e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -4,10 +4,10 @@ import * as vscode from 'vscode'; import * as Core from 'vscode-chrome-debug-core'; - -import { targetFilter } from './utils'; - import * as nls from 'vscode-nls'; + +import { defaultTargetFilter } from './utils'; + const localize = nls.loadMessageBundle(); export function activate(context: vscode.ExtensionContext) { @@ -50,7 +50,7 @@ export class ChromeConfigurationProvider implements vscode.DebugConfigurationPro let targets; try { - targets = await discovery.getAllTargets(config.address || '127.0.0.1', config.port, targetFilter, config.url || config.urlFilter); + targets = await discovery.getAllTargets(config.address || '127.0.0.1', config.port, defaultTargetFilter, config.url || config.urlFilter); } catch (e) { // Target not running? } diff --git a/src/utils.ts b/src/utils.ts index f7aa7e9..262c3cb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -3,7 +3,7 @@ *--------------------------------------------------------*/ import * as path from 'path'; -import {utils as coreUtils, chromeConnection } from 'vscode-chrome-debug-core'; +import { utils as coreUtils, chromeConnection } from 'vscode-chrome-debug-core'; const WIN_APPDATA = process.env.LOCALAPPDATA || '/'; const DEFAULT_CHROME_PATH = { @@ -64,5 +64,12 @@ export class DebounceHelper { } } -export const targetFilter: chromeConnection.ITargetFilter = - target => target && (!target.type || target.type === 'page'); +export const getTargetFilter = (targetTypes?: string[]): chromeConnection.ITargetFilter => { + if (targetTypes) { + return target => target && (!target.type || targetTypes.indexOf(target.type) !== -1); + } + + return () => true; +}; + +export const defaultTargetFilter = getTargetFilter(['page']); diff --git a/test/chromeDebugAdapter.test.ts b/test/chromeDebugAdapter.test.ts index c770f28..490ce99 100644 --- a/test/chromeDebugAdapter.test.ts +++ b/test/chromeDebugAdapter.test.ts @@ -46,6 +46,9 @@ suite('ChromeDebugAdapter', () => { .setup(x => x.sendRequest(It.isAnyString(), It.isAny(), It.isAnyNumber(), It.isAny())) .verifiable(Times.atLeast(0)); + mockChromeConnection + .setup(x => x.setTargetFilter(It.isAny())) + .verifiable(Times.atLeast(0)); mockChromeConnection .setup(x => x.api) .returns(() => mockChrome.apiObjects) diff --git a/test/utils.test.ts b/test/utils.test.ts index 35b0e28..afe54c4 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -79,4 +79,22 @@ suite('Utils', () => { '/usr/bin/google-chrome'); }); }); -}); \ No newline at end of file + + suite('getTargetFilter()', () => { + test('defaultTargetFilter', () => { + const {defaultTargetFilter} = getUtils(); + const targets = [{type: 'page'}, {type: 'webview'}]; + assert.deepEqual(targets.filter(defaultTargetFilter), [{type: 'page'}]); + }); + + test('getTargetFilter', () => { + const {getTargetFilter} = getUtils(); + const targets = [{type: 'page'}, {type: 'webview'}]; + assert.deepEqual(targets.filter(getTargetFilter(['page'])), [{type: 'page'}]); + assert.deepEqual(targets.filter(getTargetFilter(['webview'])), [{type: 'webview'}]); + assert.deepEqual(targets.filter(getTargetFilter(['page', 'webview'])), targets); + // Falsy targetTypes should effectively disable filtering. + assert.deepEqual(targets.filter(getTargetFilter()), targets); + }); + }); +});