node-inspector/lib/debugger.js

162 строки
3.9 KiB
JavaScript
Исходник Обычный вид История

2010-11-07 03:36:45 +03:00
var Net = require('net'),
EventEmitter = require('events').EventEmitter,
Buffer = require('buffer').Buffer,
2010-11-07 03:36:45 +03:00
callbackHandler = require('./callback').create();
function makeMessage() {
return {
headersDone: false,
headers: null,
contentLength: 0
};
}
///////////////////////////////////////////////////////////
// exports
2010-12-08 09:41:06 +03:00
exports.attachDebugger = function(port) {
var connected = false,
2010-11-07 03:36:45 +03:00
debugBuffer = '',
msg = false,
2010-11-07 03:36:45 +03:00
conn = Net.createConnection(port),
debugr,
offset,
2010-11-07 03:36:45 +03:00
contentLengthMatch;
conn.setEncoding('utf8');
function parse() {
2010-11-07 03:36:45 +03:00
var b, obj;
if (msg && msg.headersDone) {
//parse body
2010-11-07 03:36:45 +03:00
if (Buffer.byteLength(debugBuffer) >= msg.contentLength) {
b = new Buffer(debugBuffer);
msg.body = b.toString('utf8', 0, msg.contentLength);
2010-11-07 03:36:45 +03:00
debugBuffer = b.toString('utf8', msg.contentLength, b.length);
if (msg.body.length > 0) {
2010-11-07 03:36:45 +03:00
obj = JSON.parse(msg.body);
if (typeof obj.running === 'boolean') {
debugr.isRunning = obj.running;
}
if (obj.type === 'response' && obj.request_seq > 0) {
2010-11-07 03:36:45 +03:00
callbackHandler.processResponse(obj.request_seq, [obj]);
}
2010-10-28 09:17:06 +04:00
else if (obj.type === 'event') {
debugr.emit(obj.event, obj);
}
}
msg = false;
parse();
}
return;
}
if (!msg) {
msg = makeMessage();
}
2010-11-07 03:36:45 +03:00
offset = debugBuffer.indexOf('\r\n\r\n');
if (offset > 0) {
msg.headersDone = true;
2010-11-07 03:36:45 +03:00
msg.headers = debugBuffer.substr(0, offset + 4);
contentLengthMatch = /Content-Length: (\d+)/.exec(msg.headers);
if (contentLengthMatch[1]) {
msg.contentLength = parseInt(contentLengthMatch[1], 10);
}
else {
2010-09-11 03:59:18 +04:00
console.warn('no Content-Length');
}
2010-11-07 03:36:45 +03:00
debugBuffer = debugBuffer.slice(offset + 4);
parse();
}
}
2010-11-07 03:36:45 +03:00
debugr = Object.create(EventEmitter.prototype, {
isRunning: { writable: true, value: true },
send: {
2010-12-08 09:41:06 +03:00
value: function(data)
{
if (connected) {
2010-11-07 03:36:45 +03:00
conn.write('Content-Length: ' + data.length + '\r\n\r\n' + data);
}
}
},
_request: {
2010-12-08 09:41:06 +03:00
value: function(command, params, callback) {
var msg = {
2010-12-08 09:41:06 +03:00
seq: 0,
type: 'request',
command: command
};
2010-11-07 03:36:45 +03:00
if (typeof callback == 'function') {
msg.seq = callbackHandler.wrap(callback);
}
if (params) {
Object.keys(params).forEach(function(key) {
msg[key] = params[key];
});
}
this.send(JSON.stringify(msg));
}
},
sendDebugRequest: {
value: function(command, args, callback) {
if (typeof callback !== 'function')
callback = function(error) {
if (!error) return;
console.log('Warning: ignored V8 debugger error. %s', error);
};
this._request(command, { arguments: args }, function(response) {
var refsLookup;
if (!response.success)
callback(response.message);
else {
refsLookup = {};
if (response.refs)
response.refs.forEach(function(r) { refsLookup[r.handle] = r; });
callback(null, response.body, refsLookup);
}
});
}
},
close: {
2010-12-08 09:41:06 +03:00
value: function()
{
conn.end();
}
2010-09-11 03:59:18 +04:00
},
connected: {
get: function() { return connected; }
}
});
2010-12-08 09:41:06 +03:00
conn.on('connect', function() {
connected = true;
debugr.emit('connect');
});
2010-12-08 09:41:06 +03:00
conn.on('data', function(data) {
2010-11-07 03:36:45 +03:00
debugBuffer += data;
parse();
});
2010-12-08 09:41:06 +03:00
conn.on('error', function(e) {
debugr.emit('error', e);
});
2010-12-08 09:41:06 +03:00
conn.on('end', function() {
debugr.close();
});
2010-12-08 09:41:06 +03:00
conn.on('close', function() {
connected = false;
debugr.emit('close');
});
return debugr;
};