Skip to content

Commit 590fea5

Browse files
authored
Refactor code to allow web extension (#328)
This commit restructures the code base to allow alternate launch methods for the gdb/gdbserver executables by implementing new interface IGDBBackendFactory and providing an alternate implementation. The major version number is bumped to indicate to API consumers that their may be significant API changes. While there are large API changes, there is no functionality change for the desktop flow, which continues to use node's child_process package to spawn subprocesses.
1 parent cd740cd commit 590fea5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+3184
-731
lines changed

build-web.js

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*********************************************************************
2+
* Copyright (c) 2024 Renesas Electronics Corporation and others
3+
*
4+
* This program and the accompanying materials are made
5+
* available under the terms of the Eclipse Public License 2.0
6+
* which is available at https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*********************************************************************/
10+
// @ts-check
11+
const esbuild = require('esbuild');
12+
const path = require('node:path');
13+
const { nodeExternalsPlugin } = require('esbuild-node-externals');
14+
15+
/** @typedef {import('esbuild').BuildOptions} BuildOptions */
16+
17+
const args = process.argv.slice(2);
18+
const optionWatch = args.includes('--watch');
19+
const optionNoMinify = args.includes('--no-minify');
20+
const sourceFolder = path.join(__dirname, 'src');
21+
const distFolder = path.join(__dirname, 'dist');
22+
23+
/** @type {BuildOptions[]} */
24+
const buildConfigurations = [
25+
{
26+
target: ['es2015'],
27+
platform: 'browser',
28+
format: 'cjs',
29+
minify: !optionNoMinify,
30+
bundle: true,
31+
sourcemap: true,
32+
entryPoints: [path.join(sourceFolder, 'web.ts')],
33+
outfile: path.join(distFolder, 'browser', 'web.js'),
34+
mainFields: ['browser', 'modules', 'main'],
35+
alias: {
36+
os: 'os-browserify',
37+
path: 'path-browserify',
38+
stream: 'stream-browserify',
39+
},
40+
plugins: [nodeExternalsPlugin()],
41+
},
42+
];
43+
44+
if (optionWatch) {
45+
(async function watch() {
46+
await Promise.all([
47+
...buildConfigurations.map((config) =>
48+
esbuild.context(config).then((context) => context.watch())
49+
),
50+
]);
51+
})();
52+
} else {
53+
(async function build() {
54+
await Promise.all([
55+
...buildConfigurations.map((config) => esbuild.build(config)),
56+
]);
57+
})();
58+
}

package.json

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
22
"name": "cdt-gdb-adapter",
3-
"version": "0.0.33-next",
3+
"version": "1.0.1-next",
44
"description": "gdb adapter implementing the debug adapter protocol",
55
"main": "dist/index.js",
6+
"browser": "dist/browser/web.js",
67
"types": "dist/index.d.ts",
78
"bin": {
89
"cdtDebugAdapter": "./dist/debugAdapter.js",
@@ -12,8 +13,12 @@
1213
"install": "node install.js",
1314
"nativebuild": "node-gyp rebuild",
1415
"prepublish": "yarn build",
15-
"build": "tsc",
16-
"watch": "tsc -w",
16+
"build-tsc": "tsc",
17+
"build-web": "node build-web.js",
18+
"build": "run-s build-tsc build-web",
19+
"watch-tsc": "tsc -w",
20+
"watch-web": "node build-web.js --watch",
21+
"watch": "run-p watch-tsc watch-web",
1722
"lint": "eslint . --ext .ts,.tsx",
1823
"format": "prettier --write .",
1924
"format-check": "prettier --check .",
@@ -77,18 +82,24 @@
7782
"@typescript-eslint/eslint-plugin": "^5.54.0",
7883
"@typescript-eslint/parser": "^5.54.0",
7984
"@vscode/debugadapter-testsupport": "^1.59.0",
85+
"browserify": "^17.0.0",
8086
"chai": "^4.3.7",
8187
"chai-string": "^1.5.0",
8288
"cross-env": "^7.0.3",
89+
"esbuild": "^0.21.5",
90+
"esbuild-node-externals": "^1.13.1",
8391
"eslint": "^8.35.0",
8492
"eslint-config-prettier": "^8.6.0",
8593
"mocha": "^10.2.0",
8694
"mocha-jenkins-reporter": "^0.4.8",
8795
"node-gyp": "^8.4.1",
8896
"npm-run-all": "^4.1.5",
8997
"nyc": "^15.1.0",
98+
"os-browserify": "^0.3.0",
99+
"path-browserify": "^1.0.1",
90100
"prettier": "2.8.4",
91101
"sinon": "^17.0.0",
102+
"stream-browserify": "^3.0.0",
92103
"tmp": "^0.2.1",
93104
"ts-node": "^10.9.1",
94105
"typescript": "^4.9.5"

src/MIParser.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*********************************************************************/
1010
import { Readable } from 'stream';
1111
import { logger } from '@vscode/debugadapter/lib/logger';
12-
import { GDBBackend } from './GDBBackend';
12+
import { IGDBBackend } from './types/gdb';
1313
import * as utf8 from 'utf8';
1414

1515
type CommandQueue = {
@@ -23,7 +23,7 @@ export class MIParser {
2323
protected commandQueue: CommandQueue = {};
2424
protected waitReady?: (value?: void | PromiseLike<void>) => void;
2525

26-
constructor(protected gdb: GDBBackend) {}
26+
constructor(protected gdb: IGDBBackend) {}
2727

2828
public parse(stream: Readable): Promise<void> {
2929
return new Promise((resolve) => {

src/debugAdapter.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@
1010
* SPDX-License-Identifier: EPL-2.0
1111
*********************************************************************/
1212
import { logger } from '@vscode/debugadapter/lib/logger';
13-
import { GDBDebugSession } from './GDBDebugSession';
13+
import { GDBDebugSession } from './desktop/GDBDebugSession';
1414

1515
process.on('uncaughtException', (err: any) => {
1616
logger.error(JSON.stringify(err));
1717
});
1818

19-
GDBDebugSession.run(GDBDebugSession);
19+
class GDBDebugSessionToRun extends GDBDebugSession {
20+
constructor() {
21+
super();
22+
}
23+
}
24+
25+
GDBDebugSessionToRun.run(GDBDebugSessionToRun);

src/debugTargetAdapter.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@
1010
* SPDX-License-Identifier: EPL-2.0
1111
*********************************************************************/
1212
import { logger } from '@vscode/debugadapter/lib/logger';
13-
import { GDBTargetDebugSession } from './GDBTargetDebugSession';
13+
import { GDBTargetDebugSession } from './desktop/GDBTargetDebugSession';
1414

1515
process.on('uncaughtException', (err: any) => {
1616
logger.error(JSON.stringify(err));
1717
});
1818

19-
GDBTargetDebugSession.run(GDBTargetDebugSession);
19+
class GDBTargetDebugSessionToRun extends GDBTargetDebugSession {
20+
constructor() {
21+
super();
22+
}
23+
}
24+
25+
GDBTargetDebugSessionToRun.run(GDBTargetDebugSessionToRun);

src/desktop/GDBDebugSession.ts

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*********************************************************************
2+
* Copyright (c) 2018 QNX Software Systems and others
3+
*
4+
* This program and the accompanying materials are made
5+
* available under the terms of the Eclipse Public License 2.0
6+
* which is available at https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*********************************************************************/
10+
import * as fs from 'fs';
11+
import { DebugSession, logger } from '@vscode/debugadapter';
12+
import {
13+
LaunchRequestArguments,
14+
AttachRequestArguments,
15+
} from '../types/session';
16+
import { GDBDebugSessionBase } from '../gdb/GDBDebugSessionBase';
17+
import { GDBBackendFactory } from './factories/GDBBackendFactory';
18+
import { IGDBBackendFactory } from '../types/gdb';
19+
20+
export class GDBDebugSession extends GDBDebugSessionBase {
21+
/**
22+
* Initial (aka default) configuration for launch/attach request
23+
* typically supplied with the --config command line argument.
24+
*/
25+
protected static defaultRequestArguments?: any;
26+
27+
/**
28+
* Frozen configuration for launch/attach request
29+
* typically supplied with the --config-frozen command line argument.
30+
*/
31+
protected static frozenRequestArguments?: { request?: string };
32+
constructor(backendFactory?: IGDBBackendFactory) {
33+
super(backendFactory || new GDBBackendFactory());
34+
this.logger = logger;
35+
}
36+
37+
/**
38+
* Main entry point
39+
*/
40+
public static run(debugSession: typeof DebugSession) {
41+
GDBDebugSession.processArgv(process.argv.slice(2));
42+
DebugSession.run(debugSession);
43+
}
44+
45+
/**
46+
* Parse an optional config file which is a JSON string of launch/attach request arguments.
47+
* The config can be a response file by starting with an @.
48+
*/
49+
public static processArgv(args: string[]) {
50+
args.forEach(function (val, _index, _array) {
51+
const configMatch = /^--config(-frozen)?=(.*)$/.exec(val);
52+
if (configMatch) {
53+
let configJson;
54+
const configStr = configMatch[2];
55+
if (configStr.startsWith('@')) {
56+
const configFile = configStr.slice(1);
57+
configJson = JSON.parse(
58+
fs.readFileSync(configFile).toString('utf8')
59+
);
60+
} else {
61+
configJson = JSON.parse(configStr);
62+
}
63+
if (configMatch[1]) {
64+
GDBDebugSession.frozenRequestArguments = configJson;
65+
} else {
66+
GDBDebugSession.defaultRequestArguments = configJson;
67+
}
68+
}
69+
});
70+
}
71+
72+
/**
73+
* Apply the initial and frozen launch/attach request arguments.
74+
* @param request the default request type to return if request type is not frozen
75+
* @param args the arguments from the user to apply initial and frozen arguments to.
76+
* @returns resolved request type and the resolved arguments
77+
*/
78+
protected applyRequestArguments(
79+
request: 'launch' | 'attach',
80+
args: LaunchRequestArguments | AttachRequestArguments
81+
): ['launch' | 'attach', LaunchRequestArguments | AttachRequestArguments] {
82+
const frozenRequest = GDBDebugSession.frozenRequestArguments?.request;
83+
if (frozenRequest === 'launch' || frozenRequest === 'attach') {
84+
request = frozenRequest;
85+
}
86+
87+
return [
88+
request,
89+
{
90+
...GDBDebugSession.defaultRequestArguments,
91+
...args,
92+
...GDBDebugSession.frozenRequestArguments,
93+
},
94+
];
95+
}
96+
}

0 commit comments

Comments
 (0)