node-inspector/lib/debugger.js

151 строка
3.6 KiB
JavaScript

var Net = require('net'),
EventEmitter = require('events').EventEmitter,
Buffer = require('buffer').Buffer,
callbackHandler = require('./callback').create();
function makeMessage() {
return {
headersDone: false,
headers: null,
contentLength: 0
};
}
///////////////////////////////////////////////////////////
// exports
exports.attachDebugger = function(port) {
var connected = false,
debugBuffer = '',
msg = false,
conn = Net.createConnection(port),
debugr,
offset,
contentLengthMatch;
conn.setEncoding('utf8');
function parse() {
var b, obj;
if (msg && msg.headersDone) {
//parse body
if (Buffer.byteLength(debugBuffer) >= msg.contentLength) {
b = new Buffer(debugBuffer);
msg.body = b.toString('utf8', 0, msg.contentLength);
debugBuffer = b.toString('utf8', msg.contentLength, b.length);
if (msg.body.length > 0) {
obj = JSON.parse(msg.body);
if (obj.type === 'response' && obj.request_seq > 0) {
callbackHandler.processResponse(obj.request_seq, [obj]);
}
else if (obj.type === 'event') {
debugr.emit(obj.event, obj);
}
}
msg = false;
parse();
}
return;
}
if (!msg) {
msg = makeMessage();
}
offset = debugBuffer.indexOf('\r\n\r\n');
if (offset > 0) {
msg.headersDone = true;
msg.headers = debugBuffer.substr(0, offset + 4);
contentLengthMatch = /Content-Length: (\d+)/.exec(msg.headers);
if (contentLengthMatch[1]) {
msg.contentLength = parseInt(contentLengthMatch[1], 10);
}
else {
console.warn('no Content-Length');
}
debugBuffer = debugBuffer.slice(offset + 4);
parse();
}
}
debugr = Object.create(EventEmitter.prototype, {
send: {
value: function(data)
{
if (connected) {
conn.write('Content-Length: ' + data.length + '\r\n\r\n' + data);
}
}
},
// TODO(bajtos) replace all usages of request with sendDebugRequest
request: {
value: function(command, params, callback) {
var msg = {
seq: 0,
type: 'request',
command: command
};
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) {
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: {
value: function()
{
conn.end();
}
},
connected: {
get: function() { return connected; }
}
});
conn.on('connect', function() {
connected = true;
debugr.emit('connect');
});
conn.on('data', function(data) {
debugBuffer += data;
parse();
});
conn.on('error', function(e) {
debugr.emit('error', e);
});
conn.on('end', function() {
debugr.close();
});
conn.on('close', function() {
connected = false;
debugr.emit('close');
});
return debugr;
};