node-gdb
Version:
Control GDB from node.js
202 lines (175 loc) • 6.14 kB
JavaScript
// Generated by CoffeeScript 1.11.1
(function() {
var CompositeDisposable, Emitter, ExecState, ref;
ref = require('event-kit'), Emitter = ref.Emitter, CompositeDisposable = ref.CompositeDisposable;
ExecState = (function() {
function ExecState(gdb) {
this.gdb = gdb;
this.state = 'DISCONNECTED';
this.threadGroups = {};
this.emitter = new Emitter;
this.subscriptions = new CompositeDisposable;
this.subscriptions.add(this.gdb.onAsyncExec(this._onExec.bind(this)));
this.subscriptions.add(this.gdb.onAsyncNotify(this._onNotify.bind(this)));
this.subscriptions.add(this.gdb.onConnect((function(_this) {
return function() {
return _this._setState('EXITED');
};
})(this)));
this.subscriptions.add(this.gdb.onDisconnect((function(_this) {
return function() {
return _this._setState('DISCONNECTED');
};
})(this)));
}
ExecState.prototype.destroy = function() {
this.subscriptions.dispose();
return this.emitter.dispose();
};
ExecState.prototype.onFrameChanged = function(cb) {
return this.emitter.on('frame-changed', cb);
};
ExecState.prototype.onStopped = function(cb) {
return this.emitter.on('stopped', cb);
};
ExecState.prototype.onRunning = function(cb) {
return this.emitter.on('running', cb);
};
ExecState.prototype.onExited = function(cb) {
return this.emitter.on('exited', cb);
};
ExecState.prototype.onStateChanged = function(cb) {
return this.emitter.on('state-changed', cb);
};
ExecState.prototype.start = function() {
return this.gdb.breaks.insert('main', {
temp: true
}).then((function(_this) {
return function() {
return _this.gdb.send_mi('-exec-run');
};
})(this));
};
ExecState.prototype["continue"] = function() {
if (this.state === 'EXITED') {
return this.gdb.send_mi('-exec-run');
} else {
return this.gdb.send_mi('-exec-continue');
}
};
ExecState.prototype.next = function() {
return this.gdb.send_mi('-exec-next');
};
ExecState.prototype.step = function() {
return this.gdb.send_mi('-exec-step');
};
ExecState.prototype.finish = function() {
return this.gdb.send_mi('-exec-finish');
};
ExecState.prototype.interrupt = function() {
var t;
t = setTimeout(((function(_this) {
return function() {
return _this.gdb.child.kill('SIGINT');
};
})(this)), 100);
return this.gdb.send_mi('-exec-interrupt').then(function() {
return clearTimeout(t);
});
};
ExecState.prototype.getThreads = function() {
return this.gdb.send_mi("-thread-info").then(function(arg) {
var threads;
threads = arg.threads;
return threads;
});
};
ExecState.prototype.getFrames = function(thread) {
if (thread == null) {
thread = this.selectedThread;
}
return this.gdb.send_mi("-stack-list-frames --thread " + thread).then(function(result) {
return result.stack.frame;
});
};
ExecState.prototype.selectFrame = function(level, thread) {
if (thread == null) {
thread = this.selectedThread;
}
return this.gdb.send_mi("-stack-info-frame --thread " + thread + " --frame " + level).then((function(_this) {
return function(arg) {
var frame;
frame = arg.frame;
return _this._frameChanged(frame, thread);
};
})(this));
};
ExecState.prototype.getLocals = function(level, thread) {
if (thread == null) {
thread = this.selectedThread;
}
if (level == null) {
level = this.selectedFrame;
}
return this.gdb.send_mi("-stack-list-variables --thread " + thread + " --frame " + level + " --skip-unavailable --all-values").then((function(_this) {
return function(arg) {
var variables;
variables = arg.variables;
return variables;
};
})(this));
};
ExecState.prototype._setState = function(state, result) {
if (state !== this.state) {
this.emitter.emit(state.toLowerCase(), result);
}
this.state = state;
return this.emitter.emit('state-changed', [state, result != null ? result.frame : void 0]);
};
ExecState.prototype._onExec = function(arg) {
var cls, result;
cls = arg[0], result = arg[1];
switch (cls) {
case 'running':
this.emitter.emit('frame-changed', null);
return this._setState('RUNNING');
case 'stopped':
if ((result.reason != null) && result.reason.startsWith('exited')) {
this._setState('EXITED');
return;
}
this._frameChanged(result.frame, result['thread-id']);
return this._setState('STOPPED', result);
}
};
ExecState.prototype._onNotify = function(arg) {
var cls, index, results, threads;
cls = arg[0], results = arg[1];
switch (cls) {
case 'thread-group-started':
return this.threadGroups[results.id] = {
pid: +results.pid,
threads: []
};
case 'thread-created':
return this.threadGroups[results['group-id']].threads.push(results.id);
case 'thread-exited':
threads = this.threadGroups[results['group-id']].threads;
index = threads.indexOf(results.id);
return threads.splice(index, 1);
case 'thread-group-exited':
delete this.threadGroups[results.id];
if (Object.keys(this.threadGroups).length === 0 && this.state !== 'DISCONNECTED') {
return this._setState('EXITED');
}
}
};
ExecState.prototype._frameChanged = function(frame, thread) {
this.selectedThread = thread;
this.selectedFrame = frame.level || 0;
return this.emitter.emit('frame-changed', frame);
};
return ExecState;
})();
module.exports = ExecState;
}).call(this);