Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2010-12-30 22:17:11 +0300
committerRyan Dahl <ry@tinyclouds.org>2010-12-30 22:17:12 +0300
commitd4859a55bc8f18f1834546af12a8d8f6a8802ebd (patch)
tree876f6dc2c322991ed1ba302981d3b52e18d6bd21 /lib
parent109f845e4938ac7f213ebfb15f8d55c5135fc2ad (diff)
Wrap up debugger in one class
just for better readablity
Diffstat (limited to 'lib')
-rw-r--r--lib/_debugger.js526
1 files changed, 279 insertions, 247 deletions
diff --git a/lib/_debugger.js b/lib/_debugger.js
index 07a02cc8ce7..e0bd3e1c74e 100644
--- a/lib/_debugger.js
+++ b/lib/_debugger.js
@@ -6,96 +6,14 @@ var spawn = require('child_process').spawn;
exports.port = 5858;
exports.start = function () {
- startInterface();
-
- process.on('exit', function () {
- if (child) child.kill();
- });
+ var interface = new Interface();
};
-var child;
-var c;
-var term;
+
var args = process.argv.slice(2);
args.unshift('--debug-brk');
-function tryConnect(cb) {
- c = new Client();
-
- process.stdout.write("connecting...");
- c.connect(exports.port);
- c.once('ready', function () {
- process.stdout.write("ok\r\n");
- if (cb) cb();
- });
-
- c.on('close', function () {
- process.exit(0);
- });
-
- c.on('unhandledResponse', function (res) {
- console.log("\r\nunhandled res:");
- console.log(res);
- term.prompt();
- });
-
- c.on('break', function (res) {
- var result = '';
- if (res.body.breakpoints) {
- result += 'breakpoint';
- if (res.body.breakpoints.length > 1) {
- result += 's';
- }
- result += ' #';
- for (var i = 0; i < res.body.breakpoints.length; i++) {
- if (i > 0) {
- result += ', #';
- }
- result += res.body.breakpoints[i];
- }
- } else {
- result += 'break';
- }
- result += ' in ';
- result += res.body.invocationText;
- result += ', ';
- result += SourceInfo(res.body);
- result += '\n';
- result += SourceUnderline(res.body.sourceLineText, res.body.sourceColumn);
-
- c.currentSourceLine = res.body.sourceLine;
- c.currentFrame = 0;
- c.currentScript = res.body.script.name;
-
- console.log(result);
-
- term.prompt();
- });
-}
-
-
-function killChild() {
- if (c) {
- c.destroy();
- }
-
- if (child) {
- child.kill();
- child = null;
- }
-}
-
-
-function trySpawn(cb) {
- killChild();
-
- child = spawn(process.execPath, args, { customFds: [0, 1, 2] });
-
- setTimeout(function () {
- tryConnect(cb);
- }, 1000);
-}
//
// Parser/Serializer for V8 debugger protocol
@@ -185,7 +103,7 @@ var NO_FRAME = -1;
function Client() {
net.Stream.call(this);
- var protocol = this.protocol = new Protocol(c);
+ var protocol = this.protocol = new Protocol(this);
this._reqCallbacks = [];
var socket = this;
@@ -340,7 +258,7 @@ Client.prototype.listbreakpoints = function(cb) {
});
};
-// c.next(1, cb);
+// client.next(1, cb);
Client.prototype.step = function(action, count, cb) {
var req = {
command: 'continue',
@@ -394,202 +312,316 @@ function SourceInfo(body) {
}
-var restartQuestionPrompt = "The program being debugged has " +
- "been started already.\n" +
- "Start it from the beginning? (y or n): ";
+// This class is the readline-enabled debugger interface which is invoked on
+// "node debug"
+function Interface() {
+ var self = this;
+ var term = this.term = readline.createInterface(process.stdout);
+ var child;
+ var client;
+ var term;
-function restartQuestion (cb) {
- term.question(restartQuestionPrompt, function (answer) {
- if (/^y(es)?$/i.test(answer)) {
- cb(true);
- } else if (/^n(o)?$/i.test(answer)) {
- cb(false);
- } else {
- console.log("Please answer y or n.");
- restartQuestion(cb);
- }
+ process.on('exit', function () {
+ self.killChild();
});
-}
-
-
-function printScripts () {
- var text = '';
- for (var id in c.scripts) {
- var script = c.scripts[id];
- if (typeof script == 'object' && script.name) {
- text += script.name == c.currentScript ? '* ' : ' ';
- text += script.name + '\n';
- }
- }
- process.stdout.write(text);
-}
-
-
-function printNotConnected () {
- console.log("Program not running. Try 'run'.");
- term.prompt();
-}
-
-
-function startInterface() {
-
- term = readline.createInterface(process.stdout);
var stdin = process.openStdin();
stdin.addListener('data', function(chunk) {
term.write(chunk);
});
- var prompt = 'debug> ';
-
term.setPrompt('debug> ');
term.prompt();
- var quitTried = false;
+ this.quitTried = false;
+
+
+ term.on('SIGINT', function () {
+ self.tryQuit();
+ });
- function tryQuit() {
- if (quitTried) return;
- quitTried = true;
- killChild();
- term.close();
- process.exit(0);
- }
- term.on('SIGINT', tryQuit);
- term.on('close', tryQuit);
+ term.on('close', function () {
+ self.tryQuit();
+ });
term.on('line', function(cmd) {
+
// trim whitespace
cmd = cmd.replace(/^\s*/, '').replace(/\s*$/, '');
+ self.handleCommand(cmd);
+ });
+}
- if (cmd == 'quit' || cmd == 'q' || cmd == 'exit') {
- tryQuit();
-
- } else if (/^r(un)?/.test(cmd)) {
- if (child) {
- restartQuestion(function (yes) {
- if (!yes) {
- term.prompt();
- } else {
- console.log("restarting...");
- trySpawn(function () {
- c.reqContinue();
- });
- }
- });
- } else {
- trySpawn(function () {
- c.reqContinue();
- });
- }
- } else if (/^help/.test(cmd)) {
- console.log(helpMessage);
- term.prompt();
+Interface.prototype.tryQuit = function() {
+ if (this.quitTried) return;
+ this.quitTried = true;
+ this.killChild();
+ this.term.close();
+ process.exit(0);
+};
- } else if ('version' == cmd) {
- if (!c) {
- printNotConnected();
- return;
- }
- c.reqVersion(function (v) {
- console.log(v);
- term.prompt();
- });
- } else if (/info +breakpoints/.test(cmd)) {
- if (!c) {
- printNotConnected();
- return;
+Interface.prototype.handleBreak = function(r) {
+ var result = '';
+ if (r.breakpoints) {
+ result += 'breakpoint';
+ if (r.breakpoints.length > 1) {
+ result += 's';
+ }
+ result += ' #';
+ for (var i = 0; i < r.breakpoints.length; i++) {
+ if (i > 0) {
+ result += ', #';
}
- c.listbreakpoints(function (res) {
- console.log(res);
- term.prompt();
- });
+ result += r.breakpoints[i];
+ }
+ } else {
+ result += 'break';
+ }
+ result += ' in ';
+ result += r.invocationText;
+ result += ', ';
+ result += SourceInfo(r);
+ result += '\n';
+ result += SourceUnderline(r.sourceLineText, r.sourceColumn);
- } else if (/^backtrace/.test(cmd) || /^bt/.test(cmd)) {
- if (!c) {
- printNotConnected();
- return;
- }
- c.reqBacktrace(function (bt) {
- if (/full/.test(cmd)) {
- console.log(bt);
- } else if (bt.totalFrames == 0) {
- console.log('(empty stack)');
+ this.client.currentSourceLine = r.sourceLine;
+ this.client.currentFrame = 0;
+ this.client.currentScript = r.script.name;
+
+ console.log(result);
+
+ this.term.prompt();
+};
+
+
+Interface.prototype.handleCommand = function(cmd) {
+ var self = this;
+
+ var client = this.client;
+ var term = this.term;
+
+ if (cmd == 'quit' || cmd == 'q' || cmd == 'exit') {
+ self.tryQuit();
+
+ } else if (/^r(un)?/.test(cmd)) {
+ if (self.child) {
+ self.restartQuestion(function (yes) {
+ if (!yes) {
+ term.prompt();
} else {
- var result = '';
- for (j = 0; j < bt.frames.length; j++) {
- if (j != 0) result += '\n';
- result += bt.frames[j].text;
- }
- console.log(result);
+ console.log("restarting...");
+ self.trySpawn();
}
- term.prompt();
});
+ } else {
+ self.trySpawn();
+ }
- } else if (cmd == 'scripts' || cmd == 'scripts full') {
- if (!c) {
- printNotConnected();
- return;
- }
- printScripts();
+ } else if (/^help/.test(cmd)) {
+ console.log(helpMessage);
+ term.prompt();
+
+ } else if ('version' == cmd) {
+ if (!client) {
+ self.printNotConnected();
+ return;
+ }
+ client.reqVersion(function (v) {
+ console.log(v);
term.prompt();
+ });
- } else if (/^continue/.test(cmd) || /^c/.test(cmd)) {
- if (!c) {
- printNotConnected();
- return;
- }
- c.reqContinue(function (res) {
- // Wait for break point. (disable raw mode?)
- });
+ } else if (/info +breakpoints/.test(cmd)) {
+ if (!client) {
+ self.printNotConnected();
+ return;
+ }
+ client.listbreakpoints(function (res) {
+ console.log(res);
+ term.prompt();
+ });
- } else if (/^next/.test(cmd) || /^n/.test(cmd)) {
- if (!c) {
- printNotConnected();
- return;
+ } else if (/^backtrace/.test(cmd) || /^bt/.test(cmd)) {
+ if (!client) {
+ self.printNotConnected();
+ return;
+ }
+ client.reqBacktrace(function (bt) {
+ if (/full/.test(cmd)) {
+ console.log(bt);
+ } else if (bt.totalFrames == 0) {
+ console.log('(empty stack)');
+ } else {
+ var result = '';
+ for (j = 0; j < bt.frames.length; j++) {
+ if (j != 0) result += '\n';
+ result += bt.frames[j].text;
+ }
+ console.log(result);
}
- c.step('next', 1, function (res) {
- // Wait for break point. (disable raw mode?)
- });
+ term.prompt();
+ });
- } else if (/^step/.test(cmd) || /^s/.test(cmd)) {
- if (!c) {
- printNotConnected();
- return;
- }
- c.step('in', 1, function (res) {
- // Wait for break point. (disable raw mode?)
- });
+ } else if (cmd == 'scripts' || cmd == 'scripts full') {
+ if (!client) {
+ self.printNotConnected();
+ return;
+ }
+ self.printScripts();
+ term.prompt();
- } else if (/^print/.test(cmd) || /^p/.test(cmd)) {
- if (!c) {
- printNotConnected();
- return;
- }
- var i = cmd.indexOf(' ');
- if (i < 0) {
- console.log("print [expression]");
+ } else if (/^c(ontinue)?/.test(cmd)) {
+ if (!client) {
+ self.printNotConnected();
+ return;
+ }
+ client.reqContinue(function (res) {
+ // Wait for break point. (disable raw mode?)
+ });
+
+ } else if (/^next/.test(cmd) || /^n/.test(cmd)) {
+ if (!client) {
+ self.printNotConnected();
+ return;
+ }
+ client.step('next', 1, function (res) {
+ // Wait for break point. (disable raw mode?)
+ });
+
+ } else if (/^step/.test(cmd) || /^s/.test(cmd)) {
+ if (!client) {
+ self.printNotConnected();
+ return;
+ }
+ client.step('in', 1, function (res) {
+ // Wait for break point. (disable raw mode?)
+ });
+
+ } else if (/^print/.test(cmd) || /^p/.test(cmd)) {
+ if (!client) {
+ self.printNotConnected();
+ return;
+ }
+ var i = cmd.indexOf(' ');
+ if (i < 0) {
+ console.log("print [expression]");
+ term.prompt();
+ } else {
+ cmd = cmd.slice(i);
+ client.reqEval(cmd, function (res) {
+ if (res) {
+ console.log(res.text);
+ } else {
+ console.log(res);
+ }
term.prompt();
- } else {
- cmd = cmd.slice(i);
- c.reqEval(cmd, function (res) {
- if (res) {
- console.log(res.text);
- } else {
- console.log(res);
- }
- term.prompt();
- });
- }
+ });
+ }
+
+ } else {
+ if (!/^\s*$/.test(cmd)) {
+ // If it's not all white-space print this error message.
+ console.log('Unknown command "%s". Try "help"', cmd);
+ }
+ term.prompt();
+ }
+};
+
+
+var restartQuestionPrompt = "The program being debugged has " +
+ "been started already.\n" +
+ "Start it from the beginning? (y or n): ";
+Interface.prototype.restartQuestion = function(cb) {
+ var self = this;
+ this.term.question(restartQuestionPrompt, function (answer) {
+ if (/^y(es)?$/i.test(answer)) {
+ cb(true);
+ } else if (/^n(o)?$/i.test(answer)) {
+ cb(false);
} else {
- if (!/^\s*$/.test(cmd)) {
- // If it's not all white-space print this error message.
- console.log('Unknown command "%s". Try "help"', cmd);
- }
- term.prompt();
+ console.log("Please answer y or n.");
+ self.restartQuestion(cb);
}
});
-}
+};
+
+
+Interface.prototype.killChild = function() {
+ if (this.client) {
+ this.client.destroy();
+ this.client = null;
+ }
+
+ if (this.child) {
+ this.child.kill();
+ this.child = null;
+ }
+};
+
+
+Interface.prototype.trySpawn = function(cb) {
+ this.killChild();
+
+ this.child = spawn(process.execPath, args, { customFds: [0, 1, 2] });
+
+ var self = this;
+ setTimeout(function () {
+ process.stdout.write("connecting...");
+ var client = self.client = new Client();
+ client.connect(exports.port);
+
+ client.once('ready', function () {
+ process.stdout.write("ok\r\n");
+
+ // since we did debug-brk, we're hitting a break point immediately
+ // continue before anything else.
+ client.reqContinue();
+
+ if (cb) cb();
+ });
+
+ client.on('close', function () {
+ console.log("\nprogram terminated");
+ self.client = null;
+ self.killChild();
+ self.term.prompt();
+ });
+
+ client.on('unhandledResponse', function (res) {
+ console.log("\r\nunhandled res:");
+ console.log(res);
+ self.term.prompt();
+ });
+
+ client.on('break', function (res) {
+ self.handleBreak(res.body);
+ });
+ }, 100);
+};
+
+
+Interface.prototype.printNotConnected = function() {
+ console.log("Program not running. Try 'run'.");
+ this.term.prompt();
+};
+
+
+Interface.prototype.printScripts = function() {
+ var client = this.client;
+ var text = '';
+ for (var id in client.scripts) {
+ var script = client.scripts[id];
+ if (typeof script == 'object' && script.name) {
+ text += script.name == client.currentScript ? '* ' : ' ';
+ text += script.name + '\n';
+ }
+ }
+ process.stdout.write(text);
+};
+
+
+