|
@ -5,7 +5,7 @@ var spawn = require('child_process').spawn; |
|
|
|
|
|
|
|
|
exports.port = 5858; |
|
|
exports.port = 5858; |
|
|
|
|
|
|
|
|
exports.start = function () { |
|
|
exports.start = function() { |
|
|
var interface = new Interface(); |
|
|
var interface = new Interface(); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -22,12 +22,12 @@ args.unshift('--debug-brk'); |
|
|
// Usage:
|
|
|
// Usage:
|
|
|
// p = new Protocol();
|
|
|
// p = new Protocol();
|
|
|
//
|
|
|
//
|
|
|
// p.onResponse = function (res) {
|
|
|
// p.onResponse = function(res) {
|
|
|
// // do stuff with response from V8
|
|
|
// // do stuff with response from V8
|
|
|
// };
|
|
|
// };
|
|
|
//
|
|
|
//
|
|
|
// socket.setEncoding('utf8');
|
|
|
// socket.setEncoding('utf8');
|
|
|
// socket.on('data', function (s) {
|
|
|
// socket.on('data', function(s) {
|
|
|
// // Pass strings into the protocol
|
|
|
// // Pass strings into the protocol
|
|
|
// p.execute(s);
|
|
|
// p.execute(s);
|
|
|
// });
|
|
|
// });
|
|
@ -86,7 +86,7 @@ Protocol.prototype.execute = function(d) { |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
default: |
|
|
default: |
|
|
throw new Error("Unknown state"); |
|
|
throw new Error('Unknown state'); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
@ -121,13 +121,13 @@ function Client() { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
protocol.onResponse = this._onResponse.bind(this); |
|
|
protocol.onResponse = this._onResponse.bind(this); |
|
|
}; |
|
|
} |
|
|
inherits(Client, net.Stream); |
|
|
inherits(Client, net.Stream); |
|
|
exports.Client = Client; |
|
|
exports.Client = Client; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Client.prototype._addHandle = function(desc) { |
|
|
Client.prototype._addHandle = function(desc) { |
|
|
if (typeof desc != 'object' || !desc.handle) throw new Error("bad type"); |
|
|
if (typeof desc != 'object' || !desc.handle) throw new Error('bad type'); |
|
|
this.handles[desc.handle] = desc; |
|
|
this.handles[desc.handle] = desc; |
|
|
|
|
|
|
|
|
if (desc.type == 'script') { |
|
|
if (desc.type == 'script') { |
|
@ -201,7 +201,7 @@ Client.prototype.req = function(req, cb) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Client.prototype.reqVersion = function(cb) { |
|
|
Client.prototype.reqVersion = function(cb) { |
|
|
this.req({ command: 'version' } , function (res) { |
|
|
this.req({ command: 'version' } , function(res) { |
|
|
if (cb) cb(res.body.V8Version, res.running); |
|
|
if (cb) cb(res.body.V8Version, res.running); |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
@ -221,7 +221,7 @@ Client.prototype.reqEval = function(expression, cb) { |
|
|
req.arguments.frame = this.currentFrame; |
|
|
req.arguments.frame = this.currentFrame; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
this.req(req, function (res) { |
|
|
this.req(req, function(res) { |
|
|
console.error('reqEval res ', res.body); |
|
|
console.error('reqEval res ', res.body); |
|
|
self._addHandle(res.body); |
|
|
self._addHandle(res.body); |
|
|
if (cb) cb(res.body); |
|
|
if (cb) cb(res.body); |
|
@ -232,7 +232,7 @@ Client.prototype.reqEval = function(expression, cb) { |
|
|
// reqBacktrace(cb)
|
|
|
// reqBacktrace(cb)
|
|
|
// TODO: from, to, bottom
|
|
|
// TODO: from, to, bottom
|
|
|
Client.prototype.reqBacktrace = function(cb) { |
|
|
Client.prototype.reqBacktrace = function(cb) { |
|
|
this.req({ command: 'backtrace' } , function (res) { |
|
|
this.req({ command: 'backtrace' } , function(res) { |
|
|
if (cb) cb(res.body); |
|
|
if (cb) cb(res.body); |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
@ -256,7 +256,7 @@ Client.prototype.reqBacktrace = function(cb) { |
|
|
//
|
|
|
//
|
|
|
Client.prototype.reqScripts = function(cb) { |
|
|
Client.prototype.reqScripts = function(cb) { |
|
|
var self = this; |
|
|
var self = this; |
|
|
this.req({ command: 'scripts' } , function (res) { |
|
|
this.req({ command: 'scripts' } , function(res) { |
|
|
for (var i = 0; i < res.body.length; i++) { |
|
|
for (var i = 0; i < res.body.length; i++) { |
|
|
self._addHandle(res.body[i]); |
|
|
self._addHandle(res.body[i]); |
|
|
} |
|
|
} |
|
@ -266,13 +266,13 @@ Client.prototype.reqScripts = function(cb) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Client.prototype.reqContinue = function(cb) { |
|
|
Client.prototype.reqContinue = function(cb) { |
|
|
this.req({ command: 'continue' }, function (res) { |
|
|
this.req({ command: 'continue' }, function(res) { |
|
|
if (cb) cb(res); |
|
|
if (cb) cb(res); |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
Client.prototype.listbreakpoints = function(cb) { |
|
|
Client.prototype.listbreakpoints = function(cb) { |
|
|
this.req({ command: 'listbreakpoints' }, function (res) { |
|
|
this.req({ command: 'listbreakpoints' }, function(res) { |
|
|
if (cb) cb(res); |
|
|
if (cb) cb(res); |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
@ -284,7 +284,7 @@ Client.prototype.step = function(action, count, cb) { |
|
|
arguments: { stepaction: action, stepcount: count } |
|
|
arguments: { stepaction: action, stepcount: count } |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
this.req(req, function (res) { |
|
|
this.req(req, function(res) { |
|
|
if (cb) cb(res); |
|
|
if (cb) cb(res); |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
@ -292,8 +292,8 @@ Client.prototype.step = function(action, count, cb) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var helpMessage = "Commands: run, kill, print, step, next, " + |
|
|
var helpMessage = 'Commands: run, kill, print, step, next, ' + |
|
|
"continue, scripts, backtrace, version, quit"; |
|
|
'continue, scripts, backtrace, version, quit'; |
|
|
|
|
|
|
|
|
function SourceUnderline(sourceText, position) { |
|
|
function SourceUnderline(sourceText, position) { |
|
|
if (!sourceText) return; |
|
|
if (!sourceText) return; |
|
@ -342,7 +342,7 @@ function Interface() { |
|
|
var client; |
|
|
var client; |
|
|
var term; |
|
|
var term; |
|
|
|
|
|
|
|
|
process.on('exit', function () { |
|
|
process.on('exit', function() { |
|
|
self.killChild(); |
|
|
self.killChild(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
@ -356,15 +356,15 @@ function Interface() { |
|
|
|
|
|
|
|
|
this.quitting = false; |
|
|
this.quitting = false; |
|
|
|
|
|
|
|
|
process.on('SIGINT', function () { |
|
|
process.on('SIGINT', function() { |
|
|
self.handleSIGINT(); |
|
|
self.handleSIGINT(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
term.on('SIGINT', function () { |
|
|
term.on('SIGINT', function() { |
|
|
self.handleSIGINT(); |
|
|
self.handleSIGINT(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
term.on('close', function () { |
|
|
term.on('close', function() { |
|
|
self.tryQuit(); |
|
|
self.tryQuit(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
@ -404,7 +404,7 @@ Interface.prototype.tryQuit = function() { |
|
|
var self = this; |
|
|
var self = this; |
|
|
|
|
|
|
|
|
if (self.child) { |
|
|
if (self.child) { |
|
|
self.quitQuestion(function (yes) { |
|
|
self.quitQuestion(function(yes) { |
|
|
if (yes) { |
|
|
if (yes) { |
|
|
self.quit(); |
|
|
self.quit(); |
|
|
} else { |
|
|
} else { |
|
@ -425,7 +425,7 @@ Interface.prototype.pause = function() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Interface.prototype.resume = function() { |
|
|
Interface.prototype.resume = function() { |
|
|
if (!this.paused) return false |
|
|
if (!this.paused) return false; |
|
|
this.paused = false; |
|
|
this.paused = false; |
|
|
this.stdin.resume(); |
|
|
this.stdin.resume(); |
|
|
this.term.resume(); |
|
|
this.term.resume(); |
|
@ -464,7 +464,7 @@ Interface.prototype.handleBreak = function(r) { |
|
|
|
|
|
|
|
|
console.log(result); |
|
|
console.log(result); |
|
|
|
|
|
|
|
|
if(!this.resume()) this.term.prompt(); |
|
|
if (!this.resume()) this.term.prompt(); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -481,15 +481,15 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
} else if (/^r(un)?/.test(cmd)) { |
|
|
} else if (/^r(un)?/.test(cmd)) { |
|
|
self._lastCommand = null; |
|
|
self._lastCommand = null; |
|
|
if (self.child) { |
|
|
if (self.child) { |
|
|
self.restartQuestion(function (yes) { |
|
|
self.restartQuestion(function(yes) { |
|
|
if (!yes) { |
|
|
if (!yes) { |
|
|
self._lastCommand = null; |
|
|
self._lastCommand = null; |
|
|
term.prompt(); |
|
|
term.prompt(); |
|
|
} else { |
|
|
} else { |
|
|
console.log("restarting..."); |
|
|
console.log('restarting...'); |
|
|
self.killChild(); |
|
|
self.killChild(); |
|
|
// XXX need to wait a little bit for the restart to work?
|
|
|
// XXX need to wait a little bit for the restart to work?
|
|
|
setTimeout(function () { |
|
|
setTimeout(function() { |
|
|
self.trySpawn(); |
|
|
self.trySpawn(); |
|
|
}, 1000); |
|
|
}, 1000); |
|
|
} |
|
|
} |
|
@ -507,7 +507,7 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
self.printNotConnected(); |
|
|
self.printNotConnected(); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
client.reqVersion(function (v) { |
|
|
client.reqVersion(function(v) { |
|
|
console.log(v); |
|
|
console.log(v); |
|
|
term.prompt(); |
|
|
term.prompt(); |
|
|
}); |
|
|
}); |
|
@ -517,7 +517,7 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
self.printNotConnected(); |
|
|
self.printNotConnected(); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
client.listbreakpoints(function (res) { |
|
|
client.listbreakpoints(function(res) { |
|
|
console.log(res); |
|
|
console.log(res); |
|
|
term.prompt(); |
|
|
term.prompt(); |
|
|
}); |
|
|
}); |
|
@ -527,7 +527,7 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
self.printNotConnected(); |
|
|
self.printNotConnected(); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
client.reqBacktrace(function (bt) { |
|
|
client.reqBacktrace(function(bt) { |
|
|
if (/full/.test(cmd)) { |
|
|
if (/full/.test(cmd)) { |
|
|
console.log(bt); |
|
|
console.log(bt); |
|
|
} else if (bt.totalFrames == 0) { |
|
|
} else if (bt.totalFrames == 0) { |
|
@ -558,7 +558,7 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
self.pause(); |
|
|
self.pause(); |
|
|
client.reqContinue(function () { |
|
|
client.reqContinue(function() { |
|
|
self.resume(); |
|
|
self.resume(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
@ -569,7 +569,7 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
} |
|
|
} |
|
|
// kill
|
|
|
// kill
|
|
|
if (self.child) { |
|
|
if (self.child) { |
|
|
self.killQuestion(function (yes) { |
|
|
self.killQuestion(function(yes) { |
|
|
if (yes) { |
|
|
if (yes) { |
|
|
self.killChild(); |
|
|
self.killChild(); |
|
|
} else { |
|
|
} else { |
|
@ -585,7 +585,7 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
self.printNotConnected(); |
|
|
self.printNotConnected(); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
client.step('next', 1, function (res) { |
|
|
client.step('next', 1, function(res) { |
|
|
// Wait for break point. (disable raw mode?)
|
|
|
// Wait for break point. (disable raw mode?)
|
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
@ -594,7 +594,7 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
self.printNotConnected(); |
|
|
self.printNotConnected(); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
client.step('in', 1, function (res) { |
|
|
client.step('in', 1, function(res) { |
|
|
// Wait for break point. (disable raw mode?)
|
|
|
// Wait for break point. (disable raw mode?)
|
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
@ -605,11 +605,11 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
} |
|
|
} |
|
|
var i = cmd.indexOf(' '); |
|
|
var i = cmd.indexOf(' '); |
|
|
if (i < 0) { |
|
|
if (i < 0) { |
|
|
console.log("print [expression]"); |
|
|
console.log('print [expression]'); |
|
|
term.prompt(); |
|
|
term.prompt(); |
|
|
} else { |
|
|
} else { |
|
|
cmd = cmd.slice(i); |
|
|
cmd = cmd.slice(i); |
|
|
client.reqEval(cmd, function (res) { |
|
|
client.reqEval(cmd, function(res) { |
|
|
if (res) { |
|
|
if (res) { |
|
|
console.log(res.text); |
|
|
console.log(res.text); |
|
|
} else { |
|
|
} else { |
|
@ -633,13 +633,13 @@ Interface.prototype.handleCommand = function(cmd) { |
|
|
Interface.prototype.yesNoQuestion = function(prompt, cb) { |
|
|
Interface.prototype.yesNoQuestion = function(prompt, cb) { |
|
|
var self = this; |
|
|
var self = this; |
|
|
self.resume(); |
|
|
self.resume(); |
|
|
this.term.question(prompt, function (answer) { |
|
|
this.term.question(prompt, function(answer) { |
|
|
if (/^y(es)?$/i.test(answer)) { |
|
|
if (/^y(es)?$/i.test(answer)) { |
|
|
cb(true); |
|
|
cb(true); |
|
|
} else if (/^n(o)?$/i.test(answer)) { |
|
|
} else if (/^n(o)?$/i.test(answer)) { |
|
|
cb(false); |
|
|
cb(false); |
|
|
} else { |
|
|
} else { |
|
|
console.log("Please answer y or n."); |
|
|
console.log('Please answer y or n.'); |
|
|
self.restartQuestion(cb); |
|
|
self.restartQuestion(cb); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
@ -647,18 +647,18 @@ Interface.prototype.yesNoQuestion = function(prompt, cb) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Interface.prototype.restartQuestion = function(cb) { |
|
|
Interface.prototype.restartQuestion = function(cb) { |
|
|
this.yesNoQuestion("The program being debugged has been started already.\n" + |
|
|
this.yesNoQuestion('The program being debugged has been started already.\n' + |
|
|
"Start it from the beginning? (y or n) ", cb); |
|
|
'Start it from the beginning? (y or n) ', cb); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Interface.prototype.killQuestion = function(cb) { |
|
|
Interface.prototype.killQuestion = function(cb) { |
|
|
this.yesNoQuestion("Kill the program being debugged? (y or n) ", cb); |
|
|
this.yesNoQuestion('Kill the program being debugged? (y or n) ', cb); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Interface.prototype.quitQuestion = function(cb) { |
|
|
Interface.prototype.quitQuestion = function(cb) { |
|
|
this.yesNoQuestion("A debugging session is active. Quit anyway? (y or n) ", |
|
|
this.yesNoQuestion('A debugging session is active. Quit anyway? (y or n) ', |
|
|
cb); |
|
|
cb); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -688,35 +688,35 @@ Interface.prototype.trySpawn = function(cb) { |
|
|
|
|
|
|
|
|
this.pause(); |
|
|
this.pause(); |
|
|
|
|
|
|
|
|
setTimeout(function () { |
|
|
setTimeout(function() { |
|
|
process.stdout.write("connecting..."); |
|
|
process.stdout.write('connecting...'); |
|
|
var client = self.client = new Client(); |
|
|
var client = self.client = new Client(); |
|
|
client.connect(exports.port); |
|
|
client.connect(exports.port); |
|
|
|
|
|
|
|
|
client.once('ready', function () { |
|
|
client.once('ready', function() { |
|
|
process.stdout.write("ok\r\n"); |
|
|
process.stdout.write('ok\r\n'); |
|
|
|
|
|
|
|
|
// since we did debug-brk, we're hitting a break point immediately
|
|
|
// since we did debug-brk, we're hitting a break point immediately
|
|
|
// continue before anything else.
|
|
|
// continue before anything else.
|
|
|
client.reqContinue(function () { |
|
|
client.reqContinue(function() { |
|
|
if (cb) cb(); |
|
|
if (cb) cb(); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
client.on('close', function () { |
|
|
client.on('close', function() { |
|
|
console.log("\nprogram terminated"); |
|
|
console.log('\nprogram terminated'); |
|
|
self.client = null; |
|
|
self.client = null; |
|
|
self.killChild(); |
|
|
self.killChild(); |
|
|
if (!self.quitting) self.term.prompt(); |
|
|
if (!self.quitting) self.term.prompt(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
client.on('unhandledResponse', function (res) { |
|
|
client.on('unhandledResponse', function(res) { |
|
|
console.log("\r\nunhandled res:"); |
|
|
console.log('\r\nunhandled res:'); |
|
|
console.log(res); |
|
|
console.log(res); |
|
|
self.term.prompt(); |
|
|
self.term.prompt(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
client.on('break', function (res) { |
|
|
client.on('break', function(res) { |
|
|
self.handleBreak(res.body); |
|
|
self.handleBreak(res.body); |
|
|
}); |
|
|
}); |
|
|
}, 100); |
|
|
}, 100); |
|
@ -736,7 +736,9 @@ Interface.prototype.printScripts = function(displayNatives) { |
|
|
for (var id in client.scripts) { |
|
|
for (var id in client.scripts) { |
|
|
var script = client.scripts[id]; |
|
|
var script = client.scripts[id]; |
|
|
if (typeof script == 'object' && script.name) { |
|
|
if (typeof script == 'object' && script.name) { |
|
|
if (displayNatives || script.name == client.currentScript || !script.isNative) { |
|
|
if (displayNatives || |
|
|
|
|
|
script.name == client.currentScript || |
|
|
|
|
|
!script.isNative) { |
|
|
text += script.name == client.currentScript ? '* ' : ' '; |
|
|
text += script.name == client.currentScript ? '* ' : ' '; |
|
|
var n = require('path').split(script.name); |
|
|
var n = require('path').split(script.name); |
|
|
text += n[n.length - 1] + '\n'; |
|
|
text += n[n.length - 1] + '\n'; |
|
|