Detach from debugger when front-end disconnects.

Modified session behaviour so that back-end closes session and detaches
from the debugger when front-end web-socked disconnects.

Changed handling of debugger-connection errors so that front-end displays
popup window with error description when back-end cannot connect to debugger.

When a session starts, all previously set breakpoints are removed, since
they were already deactivated by V8 debugger.
This commit is contained in:
Miroslav Bajtos 2013-05-20 08:56:51 +02:00
Родитель faad7b051f
Коммит 6b93aa7dc6
5 изменённых файлов: 76 добавлений и 48 удалений

Просмотреть файл

@ -21,9 +21,7 @@ function onWebSocketConnected() {
function onWebSocketMessage(message) {
if (!message || message === 'ping') return;
if (message === 'debuggerWasDisabled') {
WebInspector.debuggerModel.disableDebugger();
} else if (message === 'showConsolePanel') {
if (message === 'showConsolePanel') {
InspectorFrontendAPI.showConsole();
} else {
InspectorBackend.dispatch(message);

Просмотреть файл

@ -93,8 +93,6 @@ DebuggerAgent.prototype = {
done);
},
// TODO(bajtos) Keep track of breakpoints - see implementation in session.js
setBreakpointByUrl: function(params, done) {
// TODO(bajtos) - handle params.urlRegex
var requestParams = {

Просмотреть файл

@ -5,10 +5,7 @@ var Http = require('http'),
Session = require('./session'),
inherits = require('util').inherits,
WEBROOT = require('path').join(__dirname, '../front-end'),
sessions = {},
config = {},
connectionTimeout,
webPort;
config = {};
function serveStaticFiles(req, res) {
var re = /^\/debug/;
@ -23,26 +20,16 @@ function getDebuggerPort(url, defaultPort) {
return parseInt((/\?port=(\d+)/.exec(url) || [null, defaultPort])[1], 10);
}
function getSession(debuggerPort) {
var session = sessions[debuggerPort];
if (!session) {
session = Session.create(debuggerPort, config);
sessions[debuggerPort] = session;
session.on('ws_closed', function () {
connectionTimeout = setTimeout(function () {
session.close();
}, 3000);
});
session.on('close', function () {
sessions[debuggerPort] = null;
});
}
function createSession(debuggerPort) {
var session = Session.create(debuggerPort, config);
session.on('ws_closed', function () {
session.close();
});
return session;
}
function handleWebSocketConnection(socket) {
clearTimeout(connectionTimeout);
getSession(config.debugPort).join(socket);
createSession(config.debugPort).join(socket);
}
function handleServerListening() {

Просмотреть файл

@ -34,6 +34,9 @@ exports.attachDebugger = function(port) {
debugBuffer = b.toString('utf8', msg.contentLength, b.length);
if (msg.body.length > 0) {
obj = JSON.parse(msg.body);
if (typeof obj.running === 'boolean') {
debugr.isRunning = obj.running;
}
if (obj.type === 'response' && obj.request_seq > 0) {
callbackHandler.processResponse(obj.request_seq, [obj]);
}
@ -67,6 +70,8 @@ exports.attachDebugger = function(port) {
}
debugr = Object.create(EventEmitter.prototype, {
isRunning: { writable: true, value: true },
send: {
value: function(data)
{

Просмотреть файл

@ -1,4 +1,5 @@
var events = require('events'),
async = require('async'),
debugr = require('./debugger'),
convert = require('./convert.js'),
ScriptManager = require('./ScriptManager').ScriptManager;
@ -163,20 +164,60 @@ exports.create = function(debuggerPort, config) {
}
}
function removeAllBreakpoints(done) {
debug.sendDebugRequest('listbreakpoints', {}, function(error, response) {
if (error) {
console.log('Warning: cannot remove old breakpoints. %s', error);
done();
return;
}
function removeOneBreakpoint(bp, next) {
var req = { breakpoint: bp.number };
debug.sendDebugRequest('clearbreakpoint', req, function(error) {
if (error)
console.log(
'Warning: cannot remove old breakpoint %d. %s',
bp.number,
error);
next();
});
}
async.eachSeries(response.breakpoints, removeOneBreakpoint, done);
}.bind(this));
}
function reloadScripts(done) {
scriptManager.reset();
// TODO(bajtos) use sendDebugRequest and handle errors
debug.request(
'scripts',
{ arguments: { includeSource: true, types: 4 }},
function(msg) {
parsedScripts(msg);
done();
});
}
function sendBacktraceIfPaused() {
if (!debug.isRunning) {
sendBacktrace();
}
}
function browserConnected() { // TODO find a better name
sendPing();
scriptManager.reset();
var args = { arguments: { includeSource: true, types: 4 }};
debug.request('scripts', args, function(msg) {
parsedScripts(msg);
// TODO(bajtos) we should probably clear all existing breakpoints here, because:
async.waterfall([
// Remove all existing breakpoints because:
// 1) front-end inspector cannot restore breakpoints from debugger anyway
// 2) all breakpoints are disabled when debugger-client disconnects from
// debugged application
if (!msg.running) {
sendBacktrace();
}
});
// 2) all breakpoints were disabled when the previous debugger-client
// disconnected from the debugged application
removeAllBreakpoints,
reloadScripts,
sendBacktraceIfPaused,
]);
}
sessionInstance = Object.create(events.EventEmitter.prototype, {
@ -202,12 +243,7 @@ exports.create = function(debuggerPort, config) {
attach: {
value: function(done)
{
if (attachedToDebugger) {
// TODO(bajtos) duplicated code - see debug.on('connect')
done();
browserConnected();
return;
}
var closeReason = 'Debugged process exited.';
debug = debugr.attachDebugger(debuggerPort);
debug.on('break', breakEvent);
debug.on('afterCompile', onAfterCompile)
@ -216,16 +252,15 @@ exports.create = function(debuggerPort, config) {
debug = {
request: function() {
console.error('debugger not connected');
},
sendDebugRequest: function(command, args, callback) {
callback('debugger not connected');
}
};
if (conn)
conn.send('debuggerWasDisabled');
// Do not close the session - keep it for debugee restart
// self.close();
attachedToDebugger = false;
sendEvent('Inspector.detached', { reason: closeReason.replace(/\n/g, '. ') });
sessionInstance.close();
});
debug.on('connect', function() {
// TODO(bajtos) duplicated code - see if (attachedToDebugger)
done();
browserConnected();
});
@ -236,6 +271,10 @@ exports.create = function(debuggerPort, config) {
var err = e.toString();
if (err.match(/ECONNREFUSED/)) {
err += '\nIs node running with --debug port ' + debuggerPort + '?';
closeReason = err;
} else if (err.match(/ECONNRESET/)) {
err += '\nCheck there is no other debugger client attached to port ' + debuggerPort + '.';
closeReason = err;
}
sendLogToConsole('error', err);
});
@ -253,6 +292,7 @@ exports.create = function(debuggerPort, config) {
}
},
//Controller
// TODO(bajtos) move this method to DebuggerAgent.js
disableDebugger: {
value: function(done) {
if (debug && debug.connected) {