[debugger] setBreakpoint, clearBreakpoint, fix reqSource error handling, show breakpoints in list()

pull/22966/head
Fedor Indutny 2011-09-14 16:24:46 +07:00
parent 3a7713ff10
commit 19194f87c5
1 changed files with 114 additions and 19 deletions

View File

@ -149,6 +149,7 @@ function Client() {
this.currentSource = null;
this.handles = {};
this.scripts = {};
this.breakpoints = [];
// Note that 'Protocol' requires strings instead of Buffers.
socket.setEncoding('utf8');
@ -432,6 +433,17 @@ Client.prototype.setBreakpoint = function(req, cb) {
});
};
Client.prototype.clearBreakpoint = function(req, cb) {
var req = {
command: 'clearbreakpoint',
arguments: req
};
this.req(req, function(res) {
if (cb) cb(res);
});
};
Client.prototype.reqSource = function(from, to, cb) {
var req = {
command: 'source',
@ -440,7 +452,7 @@ Client.prototype.reqSource = function(from, to, cb) {
};
this.req(req, function(res) {
if (cb) cb(res.body);
if (cb) cb(!res.success && (res.message || true), res.body);
});
};
@ -695,7 +707,9 @@ function Interface() {
'next': 'n',
'step': 's',
'out': 'o',
'backtrace': 'bt'
'backtrace': 'bt',
'setBreakpoint': 'sb',
'clearBreakpoint': 'cb'
};
function defineProperty(key, protoKey) {
@ -860,12 +874,12 @@ function intChars(n) {
}
function leftPad(n) {
function leftPad(n, prefix) {
var s = n.toString();
var nchars = intChars(n);
var nspaces = nchars - s.length;
for (var i = 0; i < nspaces; i++) {
s = ' ' + s;
s = (prefix || ' ') + s;
}
return s;
}
@ -926,8 +940,10 @@ Interface.prototype.list = function() {
to = client.currentSourceLine + delta + 1;
self.pause();
client.reqSource(from, to, function(res) {
if (!res.source) return self.error('You can\'t list source code right now');
client.reqSource(from, to, function(err, res) {
if (err || !res) {
return self.error('You can\'t list source code right now');
}
var lines = res.source.split('\n');
for (var i = 0; i < lines.length; i++) {
@ -941,17 +957,22 @@ Interface.prototype.list = function() {
lines[i] = lines[i].slice(wrapper.length);
}
var breakpoint = client.breakpoints.some(function(bp) {
return bp.script === client.currentScript &&
bp.line == lineno;
});
if (lineno == 1 + client.currentSourceLine) {
var nchars = intChars(lineno);
var pointer = '';
for (var j = 0; j < nchars - 1; j++) {
var nchars = intChars(lineno),
pointer = breakpoint ? '*' : '=';
for (var j = 1; j < nchars - 1; j++) {
pointer += '=';
}
pointer += '>';
self.print(pointer + ' ' + SourceUnderline(lines[i],
client.currentSourceColumn));
self.print(pointer + ' ' +
SourceUnderline(lines[i], client.currentSourceColumn));
} else {
self.print(leftPad(lineno) + ' ' + lines[i]);
self.print(leftPad(lineno, breakpoint && '*') + ' ' + lines[i]);
}
}
self.resume();
@ -1009,6 +1030,7 @@ Interface.prototype.scripts = function(displayNatives) {
!script.isNative) {
scripts.push(
(script.name == client.currentScript ? '* ' : ' ') +
id + ': ' +
require('path').basename(script.name)
);
}
@ -1060,18 +1082,91 @@ Interface.prototype.out = Interface.stepGenerator('out', 1);
// Add breakpoint
Interface.prototype.setBreakpoint = function(script, line, condition) {
if (!this.requireConnection()) return;
var self = this,
req = {
type: 'script',
target: script,
line: line,
condition: condition
};
scriptId,
ambiguous;
if (!this.client.scripts[script]) {
Object.keys(this.client.scripts).forEach(function(id) {
if (self.client.scripts[id].name.indexOf(script) !== -1) {
if (scriptId) {
ambiguous = true;
}
scriptId = id;
}
});
} else {
scriptId = script;
}
if (!scriptId) return this.error('Script : ' + script + ' not found');
if (ambiguous) return this.error('Script name is ambiguous');
if (line <= 0) return this.error('Line should be a positive value');
var req = {
type: 'scriptId',
target: scriptId,
line: line - 1,
condition: condition
};
self.pause();
self.client.setBreakpoint(req, function(res) {
if (res.success) {
self.print('ok');
self.list(5);
self.client.breakpoints.push({
id: res.body.breakpoint,
scriptId: scriptId,
script: self.client.scripts[scriptId].name,
line: line
});
} else {
self.print(req.message || 'error!');
}
self.resume();
});
};
// Clear breakpoint
Interface.prototype.clearBreakpoint = function(script, line) {
if (!this.requireConnection()) return;
var ambiguous,
breakpoint,
index;
this.client.breakpoints.some(function(bp, i) {
if (bp.scriptId === script || bp.script.indexOf(script) !== -1) {
if (index !== undefined) {
ambiguous = true;
}
if (bp.line === line) {
index = i;
breakpoint = bp.id;
return true;
}
}
});
if (ambiguous) return this.error('Script name is ambiguous');
if (breakpoint === undefined) {
return this.error('Script : ' + script + ' not found');
}
var self = this,
req = {
breakpoint: breakpoint
};
self.pause();
self.client.clearBreakpoint(req, function(res) {
if (res.success) {
self.client.breakpoints = self.client.breakpoints.splice(index, -1);
self.list(5);
} else {
self.print(req.message || 'error!');
}