mirror of https://github.com/nodejs/node.git
added comments, spawn child process automatically at debugger's start
parent
4ff15512f5
commit
c8ffbcd9f1
|
@ -697,19 +697,22 @@ function Interface() {
|
|||
var self = this,
|
||||
child;
|
||||
|
||||
process.on('exit', function() {
|
||||
self.killChild();
|
||||
});
|
||||
|
||||
// Two eval modes are available: controlEval and debugEval
|
||||
// But controlEval is used by default
|
||||
this.repl = new repl.REPLServer('debug> ', null,
|
||||
this.controlEval.bind(this));
|
||||
|
||||
// Kill child process when repl closed or main process is dead
|
||||
this.repl.rli.addListener('close', function() {
|
||||
self.killed = true;
|
||||
self.killChild();
|
||||
});
|
||||
|
||||
// Lift all instance methods to repl context
|
||||
process.on('exit', function() {
|
||||
self.killChild();
|
||||
});
|
||||
|
||||
|
||||
var proto = Interface.prototype,
|
||||
ignored = ['pause', 'resume', 'exitRepl', 'handleBreak',
|
||||
'requireConnection', 'killChild', 'trySpawn',
|
||||
|
@ -737,6 +740,8 @@ function Interface() {
|
|||
}
|
||||
};
|
||||
|
||||
// Copy all prototype methods in repl context
|
||||
// Setup them as getters if possible
|
||||
for (var i in proto) {
|
||||
if (proto.hasOwnProperty(i) && ignored.indexOf(i) === -1) {
|
||||
defineProperty(i, i);
|
||||
|
@ -753,6 +758,9 @@ function Interface() {
|
|||
control: []
|
||||
};
|
||||
this.breakpoints = [];
|
||||
|
||||
// Run script automatically
|
||||
this.run();
|
||||
};
|
||||
|
||||
|
||||
|
@ -780,7 +788,7 @@ Interface.prototype.resume = function(silent) {
|
|||
};
|
||||
|
||||
|
||||
// Output
|
||||
// Print text to output stream
|
||||
Interface.prototype.print = function(text) {
|
||||
if (this.killed) return;
|
||||
if (process.stdout.isTTY) {
|
||||
|
@ -791,6 +799,7 @@ Interface.prototype.print = function(text) {
|
|||
process.stdout.write('\n');
|
||||
};
|
||||
|
||||
// Format and print text from child process
|
||||
Interface.prototype.childPrint = function(text) {
|
||||
this.print(text.toString().split(/\r\n|\r|\n/g).filter(function(chunk) {
|
||||
return chunk;
|
||||
|
@ -800,26 +809,35 @@ Interface.prototype.childPrint = function(text) {
|
|||
this.repl.displayPrompt();
|
||||
};
|
||||
|
||||
// Errors formatting
|
||||
Interface.prototype.error = function(text) {
|
||||
this.print(text);
|
||||
this.resume();
|
||||
};
|
||||
|
||||
|
||||
// Debugger's `break` event handler
|
||||
Interface.prototype.handleBreak = function(r) {
|
||||
this.pause();
|
||||
|
||||
// Save execution context's data
|
||||
this.client.currentSourceLine = r.sourceLine;
|
||||
this.client.currentSourceLineText = r.sourceLineText;
|
||||
this.client.currentSourceColumn = r.sourceColumn;
|
||||
this.client.currentFrame = 0;
|
||||
this.client.currentScript = r.script.name;
|
||||
|
||||
// Print break data
|
||||
this.print(SourceInfo(r));
|
||||
|
||||
// And list source
|
||||
this.list(2);
|
||||
|
||||
this.resume();
|
||||
};
|
||||
|
||||
|
||||
// Internal method for checking connection state
|
||||
Interface.prototype.requireConnection = function() {
|
||||
if (!this.client) {
|
||||
this.error('App isn\'t running... Try `run` instead');
|
||||
|
@ -828,11 +846,20 @@ Interface.prototype.requireConnection = function() {
|
|||
return true;
|
||||
};
|
||||
|
||||
|
||||
// Evals
|
||||
|
||||
// Used for debugger's commands evaluation and execution
|
||||
Interface.prototype.controlEval = function(code, context, filename, callback) {
|
||||
try {
|
||||
var result = vm.runInContext(code, context, filename);
|
||||
|
||||
// Repl should not ask for next command
|
||||
// if current one was asynchronous.
|
||||
if (this.paused === 0) return callback(null, result);
|
||||
|
||||
// Add a callback for asynchronous command
|
||||
// (it will be automatically invoked by .resume() method
|
||||
this.waiting = function() {
|
||||
callback(null, result);
|
||||
};
|
||||
|
@ -841,22 +868,22 @@ Interface.prototype.controlEval = function(code, context, filename, callback) {
|
|||
}
|
||||
};
|
||||
|
||||
// Used for debugger's remote evaluation (`repl`) commands
|
||||
Interface.prototype.debugEval = function(code, context, filename, callback) {
|
||||
var self = this,
|
||||
client = this.client;
|
||||
|
||||
// Repl asked for scope variables
|
||||
if (code === '.scope') {
|
||||
client.reqScopes(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
var frame;
|
||||
|
||||
if (client.currentFrame === NO_FRAME) {
|
||||
frame = NO_FRAME;
|
||||
};
|
||||
var frame = client.currentFrame === NO_FRAME ? frame : undefined;
|
||||
|
||||
self.pause();
|
||||
|
||||
// Request remote evaluation globally or in current frame
|
||||
client.reqFrameEval(code, frame, function(res) {
|
||||
if (!res.success) {
|
||||
if (res.message) {
|
||||
|
@ -868,6 +895,7 @@ Interface.prototype.debugEval = function(code, context, filename, callback) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Request object by handles (and it's sub-properties)
|
||||
client.mirrorObject(res.body, 3, function(mirror) {
|
||||
callback(null, mirror);
|
||||
self.resume(true);
|
||||
|
@ -876,8 +904,9 @@ Interface.prototype.debugEval = function(code, context, filename, callback) {
|
|||
};
|
||||
|
||||
|
||||
// Commands
|
||||
// Utils
|
||||
|
||||
// Returns number of digits (+1)
|
||||
function intChars(n) {
|
||||
// TODO dumb:
|
||||
if (n < 50) {
|
||||
|
@ -891,7 +920,7 @@ function intChars(n) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Adds spaces and prefix to number
|
||||
function leftPad(n, prefix) {
|
||||
var s = n.toString();
|
||||
var nchars = intChars(n);
|
||||
|
@ -903,6 +932,9 @@ function leftPad(n, prefix) {
|
|||
}
|
||||
|
||||
|
||||
// Commands
|
||||
|
||||
|
||||
// Print help message
|
||||
Interface.prototype.help = function() {
|
||||
this.print(helpMessage);
|
||||
|
@ -1028,7 +1060,8 @@ Interface.prototype.backtrace = function() {
|
|||
};
|
||||
|
||||
|
||||
// argument full tells if it should display internal node scripts or not
|
||||
// First argument tells if it should display internal node scripts or not
|
||||
// (available only for internal debugger's functions)
|
||||
Interface.prototype.scripts = function() {
|
||||
if (!this.requireConnection()) return;
|
||||
|
||||
|
@ -1281,6 +1314,7 @@ Interface.prototype.exitRepl = function() {
|
|||
};
|
||||
|
||||
|
||||
// Kills child process
|
||||
Interface.prototype.killChild = function() {
|
||||
if (this.child) {
|
||||
this.child.kill();
|
||||
|
@ -1297,6 +1331,7 @@ Interface.prototype.killChild = function() {
|
|||
};
|
||||
|
||||
|
||||
// Spawns child process (and restores breakpoints)
|
||||
Interface.prototype.trySpawn = function(cb) {
|
||||
var self = this,
|
||||
breakpoints = this.breakpoints || [];
|
||||
|
|
Loading…
Reference in New Issue