build_and_puplish.yml / build_and_publish (release) Successful in 35s
Embed the NX Tcl Remote Debugger into the NX Postprocessor extension. Add a new debugging client, protocol, and adapter logic to drive attach/launch, breakpoints, stepping, and evaluation via the runtime adapter. - Introduced a client debugger with a new adapter and protocol - Wired attach/launch, breakpoints, stepping, and evaluation - Updated docs and licensing to reflect the embedded debugger
69 lines
2.2 KiB
JavaScript
69 lines
2.2 KiB
JavaScript
'use strict';
|
|
|
|
const { PassThrough } = require('node:stream');
|
|
const { NxDebugAdapter } = require('./debugAdapter');
|
|
|
|
function frameMessage(message) {
|
|
const json = JSON.stringify(message);
|
|
return `Content-Length: ${Buffer.byteLength(json, 'utf8')}\r\n\r\n${json}`;
|
|
}
|
|
|
|
class NxInlineDebugAdapter {
|
|
constructor() {
|
|
this.input = new PassThrough();
|
|
this.output = new PassThrough();
|
|
this.outputBuffer = Buffer.alloc(0);
|
|
this.listeners = new Set();
|
|
this.disposed = false;
|
|
|
|
this.onDidSendMessage = (listener, thisArgs, disposables) => {
|
|
const registration = { listener, thisArgs };
|
|
this.listeners.add(registration);
|
|
const disposable = {
|
|
dispose: () => this.listeners.delete(registration),
|
|
};
|
|
if (Array.isArray(disposables)) disposables.push(disposable);
|
|
return disposable;
|
|
};
|
|
|
|
this.output.on('data', (chunk) => this.onOutput(chunk));
|
|
this.adapter = new NxDebugAdapter(this.input, this.output);
|
|
}
|
|
|
|
handleMessage(message) {
|
|
if (!this.disposed) this.input.write(frameMessage(message));
|
|
}
|
|
|
|
onOutput(chunk) {
|
|
this.outputBuffer = Buffer.concat([this.outputBuffer, chunk]);
|
|
while (true) {
|
|
const headerEnd = this.outputBuffer.indexOf('\r\n\r\n');
|
|
if (headerEnd < 0) return;
|
|
const header = this.outputBuffer.subarray(0, headerEnd).toString('ascii');
|
|
const match = /Content-Length:\s*(\d+)/i.exec(header);
|
|
if (!match) throw new Error('missing DAP Content-Length header from NX adapter');
|
|
const contentLength = Number(match[1]);
|
|
const messageEnd = headerEnd + 4 + contentLength;
|
|
if (this.outputBuffer.length < messageEnd) return;
|
|
|
|
const payload = this.outputBuffer.subarray(headerEnd + 4, messageEnd).toString('utf8');
|
|
this.outputBuffer = this.outputBuffer.subarray(messageEnd);
|
|
const message = JSON.parse(payload);
|
|
for (const { listener, thisArgs } of [...this.listeners]) {
|
|
listener.call(thisArgs, message);
|
|
}
|
|
}
|
|
}
|
|
|
|
dispose() {
|
|
if (this.disposed) return;
|
|
this.disposed = true;
|
|
this.adapter.dispose();
|
|
this.input.end();
|
|
this.output.destroy();
|
|
this.listeners.clear();
|
|
}
|
|
}
|
|
|
|
module.exports = { NxInlineDebugAdapter, frameMessage };
|