Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/nodeDebugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import * as wsl from './wslSupport';

import * as nls from 'vscode-nls';
import { FinishedStartingUpEventArguments } from 'vscode-chrome-debug-core/lib/src/executionTimingsReporter';

import * as NiMS from './nodeInspectMetadataServer';

let localize = nls.loadMessageBundle();

const DefaultSourceMapPathOverrides: ISourceMapPathOverrides = {
Expand Down Expand Up @@ -387,6 +390,9 @@ export class NodeDebugAdapter extends ChromeDebugAdapter {
}
}

NiMS.addSession(launchArgs);
logger.warn('NiMS listening on ' + NiMS.getSocket());

this.logLaunchCommand(runtimeExecutable, launchArgs);
spawnOpts.detached = this.supportsTerminateRequest; // https://github.com/Microsoft/vscode/issues/57018
const nodeProcess = cp.spawn(runtimeExecutable, launchArgs, spawnOpts);
Expand All @@ -397,20 +403,23 @@ export class NodeDebugAdapter extends ChromeDebugAdapter {
const msg = `Node process error: ${error}`;
logger.error(msg);
this.terminateSession(msg);
NiMS.removeSession(launchArgs);
});
nodeProcess.on('exit', () => {
const msg = 'Target exited';
logger.log(msg);
if (!this.isExtensionHost()) {
this.terminateSession(msg);
}
NiMS.removeSession(launchArgs);
});
nodeProcess.on('close', (code) => {
const msg = 'Target closed';
logger.log(msg);
if (!this.isExtensionHost()) {
this.terminateSession(msg);
}
NiMS.removeSession(launchArgs);
});

const noDebugMode = (<ILaunchRequestArguments>this._launchAttachArgs).noDebug;
Expand Down Expand Up @@ -492,7 +501,7 @@ export class NodeDebugAdapter extends ChromeDebugAdapter {
const r = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
if (r !== null) {
const key = r[1];
if (!process.env[key]) { // .env variables never overwrite existing variables (see #21169)
if (!process.env[key]) { // .env variables never overwrite existing variables (see #21169)
let value = r[2] || '';
if (value.length > 0 && value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
value = value.replace(/\\n/gm, '\n');
Expand Down
116 changes: 116 additions & 0 deletions src/nodeInspectMetadataServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { logger } from 'vscode-chrome-debug-core';
const http = require('http'),
os = require('os'),
HOST = '127.0.0.1',
PORT = 6607;

class NodeInspectMetaServer {
sessions: any[];

constructor() {
let self = this;
self.sessions = [];

const socketStatusServer = http.createServer((req, res) => {
let out = '',
contentType = 'text/html';

if (req.url === '/json') {
contentType = 'application/json';
out = JSON.stringify(self.sessions);
} else {
let json = JSON.stringify(self.sessions);
out = `
<html>
<head>
<title>Node.js --inspect Metadata Server</title>
</head>
<body>
<pre style="word-wrap: break-word; white-space: pre-wrap;">${ (self.sessions.length == 0) ? json :
json.replace(/\[/g, '[' + os.EOL)
.replace(/\]/g, os.EOL + ']')
.replace(/\]/g, os.EOL + ']')
.replace(/\{/g, ' {' + os.EOL + ' ')
.replace(/\}/g, os.EOL + ' }')
.replace(/,/g, ',' + os.EOL + ' ')
}
</pre>
</body>
</html>
`;
}
res.writeHead(200, { 'Content-Type': contentType + '; charset=UTF-8' });
res.end(out);
});
socketStatusServer.listen(PORT, HOST, () => {
logger.log('Node --inspect Metadata Server listening on ' + HOST + ':' + PORT);
});
}
getSessionMeta(inspectPort) {
return new Promise((resolve, reject) => {
http.get('http://127.0.0.1:' + inspectPort + '/json', (res) => {
const { statusCode } = res;
const contentType = res.headers['content-type'];

let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) {
logger.error(error.message);
// consume response data to free up memory
res.resume();
return;
}

res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
resolve(parsedData[0]);
} catch (e) {
reject(e.message);
}
});
}).on('error', (e) => {
reject(`Got error: ${e.message}`);
});
});
}
getSocket() {
return HOST + ':' + PORT;
}
getInspectPort(launchArgs) {
return launchArgs.find(arg => arg.includes('--inspect')).split('=')[1];
}
addSession(launchArgs) {
let self = this;

let inspectPort = self.getInspectPort(launchArgs);
self.getSessionMeta(inspectPort)
.then((meta:any) => {
Object.assign(meta, {
inspectSocket: '127.0.0.1:' + inspectPort,
nodeExeRunner: 'vscode'
});
let index = self.sessions.findIndex(session => session.id === meta.id);
if (index == -1) self.sessions.push(meta);
else self.sessions[index] = meta;
});
}
removeSession(launchArgs) {
let self = this;
let inspectPort = self.getInspectPort(launchArgs);
let index = self.sessions.findIndex(session => session.inspectSocket === '127.0.0.1:' + inspectPort);
self.sessions.splice(index, 1);
}
}

let NiMS = new NodeInspectMetaServer();
export = NiMS;