From cd8433a63075b4aa355ea8639561b2c79291c994 Mon Sep 17 00:00:00 2001 From: Sami Vaarala Date: Sat, 14 Mar 2015 15:52:31 +0200 Subject: [PATCH] Add JSON proxy mode to duk_debug.js --- debugger/Makefile | 4 + debugger/duk_classnames.yaml | 20 ++ debugger/duk_debug.js | 561 +++++++++++++++++++++++++------- debugger/duk_debugcommands.yaml | 36 ++ debugger/package.json | 3 +- 5 files changed, 499 insertions(+), 125 deletions(-) create mode 100644 debugger/duk_classnames.yaml create mode 100644 debugger/duk_debugcommands.yaml diff --git a/debugger/Makefile b/debugger/Makefile index 438d1d9e..386cd5d9 100644 --- a/debugger/Makefile +++ b/debugger/Makefile @@ -16,6 +16,10 @@ all: run run: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images $(NODE) duk_debug.js --source-dirs=$(SOURCEDIRS) +.PHONY: runproxy +runproxy: node_modules static/socket.io-1.2.0.js static/jquery-1.11.1.min.js static/reset.css static/jquery-ui.min.js static/jquery-ui.min.css static/images + $(NODE) duk_debug.js --json-proxy + .PHONY: clean clean: @rm -f static/socket.io-1.2.0.js diff --git a/debugger/duk_classnames.yaml b/debugger/duk_classnames.yaml new file mode 100644 index 00000000..7c2ecb47 --- /dev/null +++ b/debugger/duk_classnames.yaml @@ -0,0 +1,20 @@ +# Must match C header +- unused +- Arguments +- Array +- Boolean +- Date +- Error +- Function +- JSON +- Math +- Number +- Object +- RegExp +- String +- global +- ObjEnv +- DecEnv +- Buffer +- Pointer +- Thread diff --git a/debugger/duk_debug.js b/debugger/duk_debug.js index 8b7e7bba..523fc7b5 100755 --- a/debugger/duk_debug.js +++ b/debugger/duk_debug.js @@ -23,6 +23,7 @@ var stream = require('stream'); var path = require('path'); var fs = require('fs'); var net = require('net'); +var byline = require('byline'); var util = require('util'); var readline = require('readline'); var sprintf = require('sprintf').sprintf; @@ -34,6 +35,8 @@ var yaml = require('yamljs'); var optTargetHost = '127.0.0.1'; var optTargetPort = 9091; var optHttpPort = 9092; +var optJsonProxyPort = 9093; +var optJsonProxy = false; var optSourceSearchDirs = [ '../ecmascript-testcases' ]; var optDumpDebugRead = null; var optDumpDebugWrite = null; @@ -79,38 +82,22 @@ var ERR_TOOMANY = 0x02; var ERR_NOTFOUND = 0x03; // Marker objects for special protocol values -var DVAL_EOM = { EOM: true }; -var DVAL_REQ = { REQ: true }; -var DVAL_REP = { REP: true }; -var DVAL_ERR = { ERR: true }; -var DVAL_NFY = { NFY: true }; +var DVAL_EOM = { type: 'eom' }; +var DVAL_REQ = { type: 'req' }; +var DVAL_REP = { type: 'rep' }; +var DVAL_ERR = { type: 'err' }; +var DVAL_NFY = { type: 'nfy' }; // String map for commands (debug dumping). A single map works (instead of // separate maps for each direction) because command numbers don't currently // overlap. -var debugCommandNames = {}; -debugCommandNames[0x01] = 'Status'; -debugCommandNames[0x02] = 'Print'; -debugCommandNames[0x03] = 'Alert'; -debugCommandNames[0x04] = 'Log'; -debugCommandNames[0x05] = 'Gc'; -debugCommandNames[0x10] = 'BasicInfo'; -debugCommandNames[0x11] = 'TriggerStatus'; -debugCommandNames[0x12] = 'Pause'; -debugCommandNames[0x13] = 'Resume'; -debugCommandNames[0x14] = 'StepInto'; -debugCommandNames[0x15] = 'StepOver'; -debugCommandNames[0x16] = 'StepOut'; -debugCommandNames[0x17] = 'ListBreak'; -debugCommandNames[0x18] = 'AddBreak'; -debugCommandNames[0x19] = 'DelBreak'; -debugCommandNames[0x1a] = 'GetVar'; -debugCommandNames[0x1b] = 'PutVar'; -debugCommandNames[0x1c] = 'GetCallStack'; -debugCommandNames[0x1d] = 'GetLocals'; -debugCommandNames[0x1e] = 'Eval'; -debugCommandNames[0x1f] = 'Detach'; -debugCommandNames[0x20] = 'DumpHeap'; +var debugCommandNames = yaml.load('duk_debugcommands.yaml'); + +// Map debug command names to numbers. +var debugCommandNumbers = {}; +debugCommandNames.forEach(function (k, i) { + debugCommandNumbers[k] = i; +}); // Duktape heaphdr type constants, must match C headers var DUK_HTYPE_STRING = 1; @@ -118,27 +105,7 @@ var DUK_HTYPE_OBJECT = 2; var DUK_HTYPE_BUFFER = 3; // Duktape internal class numbers, must match C headers -var dukClassNames = [ - 'unused', - 'Arguments', - 'Array', - 'Boolean', - 'Date', - 'Error', - 'Function', - 'JSON', - 'Math', - 'Number', - 'Object', - 'RegExp', - 'String', - 'global', - 'ObjEnv', - 'DecEnv', - 'Buffer', - 'Pointer', - 'Thread' -]; +var dukClassNames = yaml.load('duk_classnames.yaml'); // Bytecode opcode/extraop metadata var dukOpcodes = yaml.load('duk_opcodes.yaml') @@ -206,11 +173,19 @@ function stringToDebugString(str) { /* Pretty print a dvalue. Useful for dumping etc. */ function prettyDebugValue(x) { - if (x === DVAL_EOM) { return 'EOM'; } - if (x === DVAL_REQ) { return 'REQ'; } - if (x === DVAL_REP) { return 'REP'; } - if (x === DVAL_ERR) { return 'ERR'; } - if (x === DVAL_NFY) { return 'NFY'; } + if (typeof x === 'object' && x !== null) { + if (x.type === 'eom') { + return 'EOM'; + } else if (x.type === 'req') { + return 'REQ'; + } else if (x.type === 'rep') { + return 'REP'; + } else if (x.type === 'err') { + return 'ERR'; + } else if (x.type === 'nfy') { + return 'NFY'; + } + } return JSON.stringify(x); } @@ -300,50 +275,49 @@ function prettyUiStringUnquoted(x, cliplen) { * so that styling etc. could take typing into account. */ function prettyUiDebugValue(x, cliplen) { - var t; - - if (x === DVAL_EOM) { return 'EOM'; } - if (x === DVAL_REQ) { return 'REQ'; } - if (x === DVAL_REP) { return 'REP'; } - if (x === DVAL_ERR) { return 'ERR'; } - if (x === DVAL_NFY) { return 'NFY'; } - if (x === undefined) { return 'undefined'; } - if (x === null) { return 'null'; } - if (typeof x === 'boolean') { - return x ? 'true' : 'false'; - } - if (typeof x === 'string') { - return prettyUiString(x, cliplen); - } - if (typeof x === 'number') { - // Debug protocol integer - return prettyUiNumber(x); - } if (typeof x === 'object' && x !== null) { // Note: typeof null === 'object', so null special case explicitly - if (typeof x.UNUSED !== 'undefined') { + if (x.type === 'eom') { + return 'EOM'; + } else if (x.type === 'req') { + return 'REQ'; + } else if (x.type === 'rep') { + return 'REP'; + } else if (x.type === 'err') { + return 'ERR'; + } else if (x.type === 'nfy') { + return 'NFY'; + } else if (x.type === 'unused') { return 'unused'; - } - if (typeof x.BUF !== 'undefined') { - return '|' + x.BUF + '|'; - } - if (typeof x.OBJ !== 'undefined') { - return '[object ' + (dukClassNames[x.class] || ('class ' + x.class)) + ']'; - } - if (typeof x.PTR !== 'undefined') { - return ''; - } - if (typeof x.LFUNC !== 'undefined') { - return ''; - } - if (typeof x.NUM !== 'undefined') { + } else if (x.type === 'undefined') { + return 'undefined'; + } else if (x.type === 'buffer') { + return '|' + x.data + '|'; + } else if (x.type === 'object') { + return '[object ' + (dukClassNames[x.class] || ('class ' + x.class)) + ' ' + x.pointer + ']'; + } else if (x.type === 'pointer') { + return ''; + } else if (x.type === 'lightfunc') { + return ''; + } else if (x.type === 'number') { // duk_tval number, any IEEE double - return prettyUiNumber(x.value); + var tmp = new Buffer(x.data, 'hex'); // decode into hex + var val = tmp.readDoubleBE(0); // big endian ieee double + return prettyUiNumber(val); } + } else if (x === null) { + return 'null'; + } else if (typeof x === 'boolean') { + return x ? 'true' : 'false'; + } else if (typeof x === 'string') { + return prettyUiString(x, cliplen); + } else if (typeof x === 'number') { + // Debug protocol integer + return prettyUiNumber(x); } // We shouldn't come here, but if we do, JSON is a reasonable default. - return JSON.stringify(t); + return JSON.stringify(x); } /* Pretty print a debugger message given as an array of parsed dvalues. @@ -551,6 +525,7 @@ function DebugProtocolParser(inputStream, this.prevBytes = 0; this.bytesPerSec = 0; this.statsTimer = null; + this.readableNumberValue = true; events.EventEmitter.call(this); @@ -693,7 +668,7 @@ function DebugProtocolParser(inputStream, if (buf.length >= 5 + len) { v = new Buffer(len); buf.copy(v, 0, 5, 5 + len); - v = { BUF: v.toString('hex') }; + v = { type: 'buffer', data: v.toString('hex') }; consume(5 + len); // Value could be a Node.js buffer directly, but // we prefer all dvalues to be JSON compatible @@ -706,7 +681,7 @@ function DebugProtocolParser(inputStream, if (buf.length >= 3 + len) { v = new Buffer(len); buf.copy(v, 0, 3, 3 + len); - v = { BUF: v.toString('hex') }; + v = { type: 'buffer', data: v.toString('hex') }; consume(3 + len); // Value could be a Node.js buffer directly, but // we prefer all dvalues to be JSON compatible @@ -714,11 +689,11 @@ function DebugProtocolParser(inputStream, } break; case 0x15: // unused/none - v = { UNUSED: true }; + v = { type: 'unused' }; consume(1); break; case 0x16: // undefined - v = undefined; + v = { type: 'undefined' }; gotValue = true; // indicate 'v' is actually set consume(1); break; @@ -739,7 +714,13 @@ function DebugProtocolParser(inputStream, if (buf.length >= 9) { v = new Buffer(8); buf.copy(v, 0, 1, 9); - v = { NUM: v.toString('hex'), value: v.readDoubleBE(0) }; + v = { type: 'number', data: v.toString('hex') } + + if (_this.readableNumberValue) { + // The _value key should not be used programmatically, + // it is just there to make the dumps more readable. + v._value = buf.readDoubleBE(1); + } consume(9); } break; @@ -749,7 +730,7 @@ function DebugProtocolParser(inputStream, if (buf.length >= 3 + len) { v = new Buffer(len); buf.copy(v, 0, 3, 3 + len); - v = { OBJ: v.toString('hex'), class: buf[1] }; + v = { type: 'object', 'class': buf[1], pointer: v.toString('hex') }; consume(3 + len); } } @@ -760,7 +741,7 @@ function DebugProtocolParser(inputStream, if (buf.length >= 2 + len) { v = new Buffer(len); buf.copy(v, 0, 2, 2 + len); - v = { PTR: v.toString('hex') }; + v = { type: 'pointer', pointer: v.toString('hex') }; consume(2 + len); } } @@ -771,7 +752,7 @@ function DebugProtocolParser(inputStream, if (buf.length >= 4 + len) { v = new Buffer(len); buf.copy(v, 0, 4, 4 + len); - v = { LFUNC: v.toString('hex'), flags: buf.readUInt16BE(1) }; + v = { type: 'lightfunc', flags: buf.readUInt16BE(1), pointer: v.toString('hex') }; consume(4 + len); } } @@ -782,7 +763,7 @@ function DebugProtocolParser(inputStream, if (buf.length >= 2 + len) { v = new Buffer(len); buf.copy(v, 0, 2, 2 + len); - v = { HEAPPTR: v.toString('hex') }; + v = { type: 'heapptr', pointer: v.toString('hex') }; consume(2 + len); } } @@ -858,20 +839,94 @@ DebugProtocolParser.prototype.close = function () { */ function formatDebugValue(v) { - var buf; + var buf, dec, len; // See doc/debugger.rst for format description. - if (v === DVAL_EOM) { - return new Buffer([ 0x00 ]); - } else if (v === DVAL_REQ) { - return new Buffer([ 0x01 ]); - } else if (v === DVAL_REP) { - return new Buffer([ 0x02 ]); - } else if (v === DVAL_ERR) { - return new Buffer([ 0x03 ]); - } else if (v === DVAL_NFY) { - return new Buffer([ 0x04 ]); + if (typeof v === 'object' && v !== null) { + // Note: typeof null === 'object', so null special case explicitly + if (v.type === 'eom') { + return new Buffer([ 0x00 ]); + } else if (v.type === 'req') { + return new Buffer([ 0x01 ]); + } else if (v.type === 'rep') { + return new Buffer([ 0x02 ]); + } else if (v.type === 'err') { + return new Buffer([ 0x03 ]); + } else if (v.type === 'nfy') { + return new Buffer([ 0x04 ]); + } else if (v.type === 'unused') { + return new Buffer([ 0x15 ]); + } else if (v.type === 'undefined') { + return new Buffer([ 0x16 ]); + } else if (v.type === 'number') { + dec = new Buffer(v.data, 'hex'); + len = dec.length; + if (len !== 8) { + throw new TypeError('value cannot be converted to dvalue: ' + JSON.stringify(v)); + } + buf = new Buffer(1 + len); + buf[0] = 0x1a; + dec.copy(buf, 1); + return buf; + } else if (v.type === 'buffer') { + dec = new Buffer(v.data, 'hex'); + len = dec.length; + if (len <= 0xffff) { + buf = new Buffer(3 + len); + buf[0] = 0x14; + buf[1] = (len >> 8) & 0xff; + buf[2] = (len >> 0) & 0xff; + dec.copy(buf, 3); + return buf; + } else { + buf = new Buffer(5 + len); + buf[0] = 0x13; + buf[1] = (len >> 24) & 0xff; + buf[2] = (len >> 16) & 0xff; + buf[3] = (len >> 8) & 0xff; + buf[4] = (len >> 0) & 0xff; + dec.copy(buf, 5); + return buf; + } + } else if (v.type === 'object') { + dec = new Buffer(v.pointer, 'hex'); + len = dec.length; + buf = new Buffer(3 + len); + buf[0] = 0x1b; + buf[1] = v.class; + buf[2] = len; + dec.copy(buf, 3); + return buf; + } else if (v.type === 'pointer') { + dec = new Buffer(v.pointer, 'hex'); + len = dec.length; + buf = new Buffer(2 + len); + buf[0] = 0x1c; + buf[1] = len; + dec.copy(buf, 2); + return buf; + } else if (v.type === 'lightfunc') { + dec = new Buffer(v.pointer, 'hex'); + len = dec.length; + buf = new Buffer(4 + len); + buf[0] = 0x1d; + buf[1] = (v.flags >> 8) & 0xff; + buf[2] = v.flags & 0xff; + buf[3] = len; + dec.copy(buf, 4); + return buf; + } else if (v.type === 'heapptr') { + dec = new Buffer(v.pointer, 'hex'); + len = dec.length; + buf = new Buffer(2 + len); + buf[0] = 0x1e; + buf[1] = len; + dec.copy(buf, 2); + return buf; + } + } else if (v === null) { + return new Buffer([ 0x17 ]); } else if (typeof v === 'boolean') { return new Buffer([ v ? 0x18 : 0x19 ]); } else if (typeof v === 'number') { @@ -930,10 +985,8 @@ function formatDebugValue(v) { } } - // XXX: missing support for various types (pointer, object, lightfunc, buffer) - // as they're not needed right now. - - throw new TypeError('value cannot be converted to dvalue: ' + v); + // Shouldn't come here. + throw new TypeError('value cannot be converted to dvalue: ' + JSON.stringify(v)); } /* @@ -1386,10 +1439,10 @@ Debugger.prototype.sendGetBytecodeRequest = function () { preformatted = preformatted.join('\n') + '\n'; ret = { - "constants": consts, - "functions": funcs, - "bytecode": bcode, - "preformatted": preformatted + constants: consts, + functions: funcs, + bytecode: bcode, + preformatted: preformatted }; return ret; @@ -2073,6 +2126,251 @@ DebugWebServer.prototype.emitLocals = function () { this.socket.emit('locals', newMsg); }; +/* + * JSON debug proxy + */ + +function DebugProxy(serverPort) { + this.serverPort = serverPort; + this.server = null; + this.socket = null; + this.targetStream = null; + this.inputParser = null; + + // preformatted dvalues + this.dval_eom = formatDebugValue(DVAL_EOM); + this.dval_req = formatDebugValue(DVAL_REQ); + this.dval_rep = formatDebugValue(DVAL_REP); + this.dval_nfy = formatDebugValue(DVAL_NFY); + this.dval_err = formatDebugValue(DVAL_ERR); +} + +DebugProxy.prototype.determineCommandNumber = function (cmdString, cmdNumber) { + var ret; + if (typeof cmdString === 'string') { + ret = debugCommandNumbers[cmdString]; + } + ret = ret || cmdNumber; + if (typeof ret !== 'number') { + throw Error('cannot figure out command number for "' + cmdString + '" (' + cmdNumber + ')'); + } + return ret; +}; + +DebugProxy.prototype.commandNumberToString = function (id) { + return debugCommandNames[id] || String(id); +}; + +DebugProxy.prototype.formatDvalues = function (args) { + if (!args) { + return []; + } + return args.map(function (v) { + return formatDebugValue(v); + }); +}; + +DebugProxy.prototype.writeJson = function (val) { + this.socket.write(JSON.stringify(val) + '\n'); +}; + +DebugProxy.prototype.writeJsonSafe = function (val) { + try { + this.writeJson(val); + } catch (e) { + console.log('Failed to write JSON in writeJsonSafe, ignoring: ' + e); + } +}; + +DebugProxy.prototype.disconnectJsonClient = function () { + if (this.socket) { + this.socket.destroy(); + this.socket = null; + } +}; + +DebugProxy.prototype.disconnectTarget = function () { + if (this.inputParser) { + this.inputParser.close(); + this.inputParser = null; + } + if (this.targetStream) { + this.targetStream.destroy(); + this.targetStream = null; + } +}; + +DebugProxy.prototype.run = function () { + var _this = this; + + console.log('Waiting for client connections on port ' + this.serverPort); + this.server = net.createServer(function (socket) { + console.log('JSON proxy client connected'); + + _this.disconnectJsonClient(); + _this.disconnectTarget(); + + // A byline-parser is simple and good enough for now (assume + // compact JSON with no newlines). + var socketByline = byline(socket); + _this.socket = socket; + + socketByline.on('data', function (line) { + try { + // console.log('Received json proxy input line: ' + line.toString('utf8')); + var msg = JSON.parse(line.toString('utf8')); + var first_dval; + var args_dvalues = _this.formatDvalues(msg.args); + var last_dval = _this.dval_eom; + var cmd; + + if (msg.request) { + // "request" can be a string or "true" + first_dval = _this.dval_req; + cmd = _this.determineCommandNumber(msg.request, msg.command); + } else if (msg.reply) { + first_dval = _this.dval_rep; + } else if (msg.notify) { + // "notify" can be a string or "true" + first_dval = _this.dval_nfy; + cmd = _this.determineCommandNumber(msg.notify, msg.command); + } else if (msg.error) { + first_dval = _this.dval_err; + } else { + throw new Error('Invalid input JSON message: ' + JSON.stringify(msg)); + } + + _this.targetStream.write(first_dval); + if (cmd) { + _this.targetStream.write(formatDebugValue(cmd)); + } + args_dvalues.forEach(function (v) { + _this.targetStream.write(v); + }); + _this.targetStream.write(last_dval); + } catch (e) { + console.log(e); + + _this.writeJsonSafe({ + notify: '_Error', + args: [ 'Failed to handle input json message: ' + e ] + }); + + _this.disconnectJsonClient(); + _this.disconnectTarget(); + } + }); + + _this.connectToTarget(); + }).listen(this.serverPort); +}; + +DebugProxy.prototype.connectToTarget = function () { + var _this = this; + + console.log('Connecting to ' + optTargetHost + ':' + optTargetPort + '...'); + this.targetStream = new net.Socket(); + this.targetStream.connect(optTargetPort, optTargetHost, function () { + console.log('Debug transport connected'); + }); + + this.inputParser = new DebugProtocolParser( + this.targetStream, + null, + optDumpDebugRead, + optDumpDebugPretty, + optDumpDebugPretty ? 'Recv: ' : null, + null, + null // console logging is done at a higher level to match request/response + ); + + // Don't add a '_value' key to numbers. + this.inputParser.readableNumberValue = false; + + this.inputParser.on('transport-close', function () { + console.log('Debug transport closed'); + + _this.writeJsonSafe({ + notify: '_Disconnecting' + }); + + _this.disconnectJsonClient(); + _this.disconnectTarget(); + }); + + this.inputParser.on('transport-error', function (err) { + console.log('Debug transport error', err); + + _this.writeJsonSafe({ + notify: '_Error', + args: [ String(err) ] + }); + }); + + this.inputParser.on('protocol-version', function (msg) { + var ver = msg.protocolVersion; + console.log('Debug version identification:', msg.versionIdentification); + + _this.writeJson({ + notify: '_Connected', + args: [ msg.versionIdentification ] // raw identification string + }); + + if (ver !== 1) { + console.log('Protocol version ' + ver + ' unsupported, dropping connection'); + } + }); + + this.inputParser.on('debug-message', function (msg) { + var t; + + //console.log(msg); + + if (typeof msg[0] !== 'object' || msg[0] === null) { + throw new Error('unexpected initial dvalue: ' + msg[0]); + } else if (msg.type === 'eom') { + throw new Error('unexpected initial dvalue: ' + msg[0]); + } else if (msg.type === 'req') { + if (typeof msg[1] !== 'number') { + throw new Error('unexpected request command number: ' + msg[1]); + } + t = { + request: _this.commandNumberToString(msg[1]), + command: msg[1], + args: msg.slice(2, msg.length - 1) + } + _this.writeJson(t); + } else if (msg[0].type === 'rep') { + t = { + reply: true, + args: msg.slice(1, msg.length - 1) + } + _this.writeJson(t); + } else if (msg[0].type === 'err') { + t = { + error: true, + args: msg.slice(1, msg.length - 1) + } + _this.writeJson(t); + } else if (msg[0].type === 'nfy') { + if (typeof msg[1] !== 'number') { + throw new Error('unexpected notify command number: ' + msg[1]); + } + t = { + notify: _this.commandNumberToString(msg[1]), + command: msg[1], + args: msg.slice(2, msg.length - 1) + } + _this.writeJson(t); + } else { + throw new Error('unexpected initial dvalue: ' + msg[0]); + } + }); + + this.inputParser.on('stats-update', function () { + }); +}; + /* * Command line parsing and initialization */ @@ -2093,6 +2391,12 @@ function main() { if (argv['http-port']) { optHttpPort = argv['http-port']; } + if (argv['json-proxy-port']) { + optJsonProxyPort = argv['json-proxy-port']; + } + if (argv['json-proxy']) { + optJsonProxy = argv['json-proxy']; + } if (argv['source-dirs']) { optSourceSearchDirs = argv['source-dirs'].split(path.delimiter); } @@ -2116,6 +2420,8 @@ function main() { console.log(' --target-host: ' + optTargetHost); console.log(' --target-port: ' + optTargetPort); console.log(' --http-port: ' + optHttpPort); + console.log(' --json-proxy-port: ' + optJsonProxyPort); + console.log(' --json-proxy: ' + optJsonProxy); console.log(' --source-dirs: ' + optSourceSearchDirs.join(' ')); console.log(' --dump-debug-read: ' + optDumpDebugRead); console.log(' --dump-debug-write: ' + optDumpDebugWrite); @@ -2126,12 +2432,19 @@ function main() { // Create debugger and web UI singletons, tie them together and // start them. - var dbg = new Debugger(); - var web = new DebugWebServer(); - dbg.web = web; - web.dbg = dbg; - dbg.run(); - web.run(); + if (optJsonProxy) { + console.log('Starting in JSON proxy mode, JSON port: ' + optJsonProxyPort); + + var prx = new DebugProxy(optJsonProxyPort); + prx.run(); + } else { + var dbg = new Debugger(); + var web = new DebugWebServer(); + dbg.web = web; + web.dbg = dbg; + dbg.run(); + web.run(); + } } main(); diff --git a/debugger/duk_debugcommands.yaml b/debugger/duk_debugcommands.yaml new file mode 100644 index 00000000..0d4501c9 --- /dev/null +++ b/debugger/duk_debugcommands.yaml @@ -0,0 +1,36 @@ +# Debug command names. A single map works for now because command names +# provided by client/target don't overlap. +- Reserved_0 +- Status +- Print +- Alert +- Log +- Gc +- Reserved_6 +- Reserved_7 +- Reserved_8 +- Reserved_9 +- Reserved_10 +- Reserved_11 +- Reserved_12 +- Reserved_13 +- Reserved_14 +- Reserved_15 +- BasicInfo +- TriggerStatus +- Pause +- Resume +- StepInto +- StepOver +- StepOut +- ListBreak +- AddBreak +- DelBreak +- GetVar +- PutVar +- GetCallStack +- GetLocals +- Eval +- Detach +- DumpHeap +- GetBytecode diff --git a/debugger/package.json b/debugger/package.json index 8aab7751..96165744 100644 --- a/debugger/package.json +++ b/debugger/package.json @@ -20,7 +20,8 @@ "readline": "0.0.5", "util": "~0.10.3", "http": "0.0.0", - "yamljs": "~0.2.1" + "yamljs": "~0.2.1", + "byline": "~4.2.1" }, "main": "duk_debug.js" }