node-gdb
Version:
Control GDB from node.js
300 lines (267 loc) • 8.79 kB
JavaScript
// Generated by CoffeeScript 1.11.1
(function() {
var CompositeDisposable, Disposable, Emitter, Variable, VariableManager, _, cstr, ref,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
ref = require('event-kit'), Emitter = ref.Emitter, Disposable = ref.Disposable, CompositeDisposable = ref.CompositeDisposable;
cstr = require('./utils').cstr;
_ = require('underscore');
Variable = (function() {
Variable.prototype.watchpoint = null;
function Variable(gdb, varobj) {
this.gdb = gdb;
this.emitter = new Emitter;
_.extend(this, varobj);
}
Variable.prototype.onChanged = function(cb) {
return this.emitter.on('changed', cb);
};
Variable.prototype.onDeleted = function(cb) {
return this.emitter.on('deleted', cb);
};
Variable.prototype.assign = function(val) {
return this.gdb.send_mi("-var-assign " + this.name + " " + (cstr(val))).then((function(_this) {
return function(arg) {
var value;
value = arg.value;
_this.gdb.vars.update();
return value;
};
})(this));
};
Variable.prototype._getExpression = function() {
return this.gdb.send_mi("-var-info-path-expression " + this.name).then(function(arg) {
var path_expr;
path_expr = arg.path_expr;
return path_expr;
});
};
Variable.prototype.setWatch = function() {
return this._getExpression().then((function(_this) {
return function(expr) {
return _this.gdb.breaks.insertWatch(expr, function(number) {
return _this.gdb.vars.watchpoints[number] = _this.name;
});
};
})(this)).then((function(_this) {
return function(bkpt) {
return _this._watchSet(bkpt);
};
})(this));
};
Variable.prototype.clearWatch = function() {
return this.watchpoint.remove();
};
Variable.prototype.remove = function() {
return this.gdb.send_mi("-var-delete " + this.name).then((function(_this) {
return function() {
return _this._deleted();
};
})(this));
};
Variable.prototype.addChildren = function() {
return this.gdb.send_mi("-var-list-children --all-values " + this.name).then((function(_this) {
return function(result) {
var child;
return Promise.all((function() {
var j, len, ref1, results;
ref1 = result.children.child;
results = [];
for (j = 0, len = ref1.length; j < len; j++) {
child = ref1[j];
results.push(this.gdb.vars._added(child));
}
return results;
}).call(_this));
};
})(this)).then((function(_this) {
return function(children) {
_this.children = children;
return _this.children;
};
})(this));
};
Variable.prototype._watchSet = function(bkpt) {
this.watchpoint = bkpt;
bkpt.onDeleted((function(_this) {
return function() {
delete _this.watchpoint;
return _this._changed();
};
})(this));
bkpt.onChanged((function(_this) {
return function() {
return _this._changed();
};
})(this));
return this._changed();
};
Variable.prototype._changed = function(varobj) {
_.extend(this, varobj);
return this.emitter.emit('changed', this);
};
Variable.prototype._deleted = function() {
var child, j, len, ref1, ref2, results;
this.emitter.emit('deleted');
this.emitter.dispose();
if ((ref1 = this.watchpoint) != null) {
ref1.remove();
}
ref2 = this.children || [];
results = [];
for (j = 0, len = ref2.length; j < len; j++) {
child = ref2[j];
results.push(child._deleted());
}
return results;
};
return Variable;
})();
VariableManager = (function() {
function VariableManager(gdb) {
this.gdb = gdb;
this.roots = [];
this.vars = {};
this.observers = [];
this.watchpoints = {};
this.emitter = new Emitter;
this.subscriptions = new CompositeDisposable;
this.subscriptions.add(this.gdb.exec.onStateChanged(this._execStateChanged.bind(this)));
this.subscriptions.add(this.gdb.breaks.observe(this._breakObserver.bind(this)));
}
VariableManager.prototype.destroy = function() {
this.subscriptions.dispose();
this.emitter.dispose();
delete this.observers;
delete this.watchpoints;
delete this.roots;
return delete this.vars;
};
VariableManager.prototype.observe = function(cb) {
var j, len, n, r, ref1;
r = (function(_this) {
return function(n) {
var j, len, ref1, results, v;
v = _this.vars[n];
cb(n, v);
ref1 = v.children || [];
results = [];
for (j = 0, len = ref1.length; j < len; j++) {
n = ref1[j];
results.push(r(n));
}
return results;
};
})(this);
ref1 = this.roots;
for (j = 0, len = ref1.length; j < len; j++) {
n = ref1[j];
r(n);
}
this.observers.push(cb);
return new Disposable(function() {
return this.observers.splice(this.observers.indexOf(cb), 1);
});
};
VariableManager.prototype.add = function(expr, frame, thread) {
if (thread == null) {
thread = this.gdb.exec.selectedThread;
}
if (frame == null) {
frame = this.gdb.exec.selectedFrame;
}
return this.gdb.send_mi("-var-create --thread " + thread + " --frame " + frame + " - * " + (cstr(expr))).then((function(_this) {
return function(result) {
result.exp = expr;
return _this._added(result);
};
})(this));
};
VariableManager.prototype.evalExpression = function(expr, frame, thread) {
if (thread == null) {
thread = this.gdb.exec.selectedThread;
}
if (frame == null) {
frame = this.gdb.exec.selectedFrame;
}
return this.gdb.send_mi("-data-evaluate-expression --thread " + thread + " --frame " + frame + " " + expr).then(function(arg) {
var value;
value = arg.value;
return value;
});
};
VariableManager.prototype._notifyObservers = function(v) {
var cb, j, len, ref1;
ref1 = this.observers;
for (j = 0, len = ref1.length; j < len; j++) {
cb = ref1[j];
cb(v);
}
return v;
};
VariableManager.prototype._execStateChanged = function(arg) {
var j, len, name, ref1, state;
state = arg[0];
if (state === 'DISCONNECTED') {
ref1 = this.roots.slice();
for (j = 0, len = ref1.length; j < len; j++) {
name = ref1[j];
this._removeVar(name);
}
return;
}
if (state !== 'STOPPED') {
return;
}
return this.update();
};
VariableManager.prototype.update = function() {
return this.gdb.send_mi("-var-update --all-values *").then((function(_this) {
return function(arg) {
var changelist, j, len, results, v;
changelist = arg.changelist;
results = [];
for (j = 0, len = changelist.length; j < len; j++) {
v = changelist[j];
results.push(_this.vars[v.name]._changed(v));
}
return results;
};
})(this));
};
VariableManager.prototype._added = function(v) {
var i;
if ((i = v.name.lastIndexOf('.')) >= 0) {
v.parent = this.vars[v.name.slice(0, i)];
}
v.nest = v.name.split('.').length - 1;
v = new Variable(this.gdb, v);
this.vars[v.name] = v;
v.onDeleted((function(_this) {
return function() {
var ref1;
delete _this.vars[v.name];
if (ref1 = v.name, indexOf.call(_this.roots, ref1) >= 0) {
return _this.roots.splice(_this.roots.indexOf(v.name), 1);
}
};
})(this));
return this._notifyObservers(v);
};
VariableManager.prototype._breakObserver = function(id, bkpt) {
if (!bkpt.type.endsWith('watchpoint')) {
return;
}
if (this.watchpoints[id] != null) {
return;
}
return this.add(bkpt.what).then((function(_this) {
return function(v) {
_this.watchpoints[bkpt.number] = v.name;
return v._watchSet(bkpt);
};
})(this));
};
return VariableManager;
})();
module.exports = VariableManager;
}).call(this);