});
};
+Client.prototype.reqScopes = function(cb) {
+ var self = this,
+ req = {
+ command: 'scopes',
+ arguments: {}
+ };
+ this.req(req, function(res) {
+ if (!res.success) return cb(Error(res.message) || true);
+ var refs = res.body.scopes.map(function(scope) {
+ return scope.object.ref;
+ });
+
+ self.reqLookup(refs, function(res) {
+ var globals = Object.keys(res.body).map(function(key) {
+ return res.body[key].properties.map(function(prop) {
+ return prop.name;
+ });
+ });
+ cb(null, globals.reverse());
+ });
+ });
+};
+
// This is like reqEval, except it will look up the expression in each of the
// scopes associated with the current frame.
Client.prototype.reqEval = function(expression, cb) {
// Lift all instance methods to repl context
var proto = Interface.prototype,
- ignored = ['pause', 'resume', 'exitRepl'];
+ ignored = ['pause', 'resume', 'exitRepl', 'handleBreak',
+ 'requireConnection', 'killChild', 'trySpawn'];
for (var i in proto) {
if (proto.hasOwnProperty(i) && ignored.indexOf(i) === -1) {
}, 1000);
};
-Interface.prototype.version = function() {
- if (!this.child) throw Error('App isn\'t running... Try `run()` instead');
+Interface.prototype.requireConnection = function() {
+ if (!this.client) throw Error('App isn\'t running... Try `run()` instead');
+};
+
+Interface.prototype.version = function() {
+ this.requireConnection();
var self = this;
this.pause();
});
};
+Interface.prototype.list = function() {
+ this.requireConnection();
+
+ var self = this,
+ client = this.client,
+ from = client.currentSourceLine - 5,
+ to = client.currentSourceLine + 5;
+
+ self.pause();
+ client.reqSource(from, to, function(res) {
+ var lines = res.source.split('\n');
+ for (var i = 0; i < lines.length; i++) {
+ var lineno = res.fromLine + i + 1;
+ if (lineno < from || lineno > to) continue;
+
+ if (lineno == 1) {
+ // The first line needs to have the module wrapper filtered out of
+ // it.
+ var wrapper = require('module').wrapper[0];
+ lines[i] = lines[i].slice(wrapper.length);
+ }
+
+ if (lineno == 1 + client.currentSourceLine) {
+ var nchars = intChars(lineno);
+ var pointer = '';
+ for (var j = 0; j < nchars - 1; j++) {
+ pointer += '=';
+ }
+ pointer += '>';
+ console.log(pointer + ' ' + lines[i]);
+ } else {
+ console.log(leftPad(lineno) + ' ' + lines[i]);
+ }
+ }
+ self.resume();
+ });
+};
+
+Interface.prototype.backtrace = function() {
+ this.requireConnection();
+
+ var self = this,
+ client = this.client;
+
+ self.pause();
+ client.fullTrace(function(bt) {
+ if (bt.totalFrames == 0) {
+ console.log('(empty stack)');
+ } else {
+ var text = '';
+ var firstFrameNative = bt.frames[0].script.isNative;
+ for (var i = 0; i < bt.frames.length; i++) {
+ var frame = bt.frames[i];
+ if (!firstFrameNative && frame.script.isNative) break;
+
+ text += '#' + i + ' ';
+ if (frame.func.inferredName && frame.func.inferredName.length > 0) {
+ text += frame.func.inferredName + ' ';
+ }
+ text += require('path').basename(frame.script.name) + ':';
+ text += (frame.line + 1) + ':' + (frame.column + 1);
+ text += '\n';
+ }
+
+ process.stdout.write(text);
+ }
+ self.resume();
+ });
+};
+
+// argument full tells if it should display internal node scripts or not
+Interface.prototype.scripts = function(displayNatives) {
+ this.requireConnection();
+
+ var client = this.client;
+ var text = '';
+
+ this.pause();
+ for (var id in client.scripts) {
+ var script = client.scripts[id];
+ if (typeof script == 'object' && script.name) {
+ if (displayNatives ||
+ script.name == client.currentScript ||
+ !script.isNative) {
+ text += script.name == client.currentScript ? '* ' : ' ';
+ text += require('path').basename(script.name) + '\n';
+ }
+ }
+ }
+ process.stdout.write(text);
+ this.resume();
+};
+
+Interface.prototype.cont = function() {
+ this.requireConnection();
+ this.pause();
+
+ var self = this;
+ this.client.reqContinue(function() {
+ self.resume();
+ });
+};
+
+Interface.prototype.next = function() {
+ this.requireConnection();
+
+ this.pause();
+
+ var self = this;
+ this.client.step('next', 1, function(res) {
+ self.resume();
+ });
+};
+
+Interface.prototype.step = function() {
+ this.requireConnection();
+
+ this.pause();
+
+ var self = this;
+ this.client.step('in', 1, function(res) {
+ self.resume();
+ });
+};
+
+Interface.prototype.out = function() {
+ this.requireConnection();
+
+ this.pause();
+
+ var self = this;
+ this.client.step('out', 1, function(res) {
+ self.resume();
+ });
+};
+
+Interface.prototype.breakpoints = function() {
+ this.requireConnection();
+ this.pause();
+ var self = this;
+ this.client.listbreakpoints(function(res) {
+ if (res.success) {
+ console.log(res.body);
+ } else {
+ throw Error(res.message || 'Some error happened');
+ }
+ self.resume();
+ });
+};
+
+Interface.prototype.kill = function() {
+ if (!this.child) return;
+ this.killChild();
+};
+
Interface.prototype.repl = function() {
if (!this.child) throw Error('App isn\'t running... Try `run()` instead');
var client = this.client;
+ // Save old eval
this.repl._eval = this.repl.eval;
+
+ // Set new
this.repl.eval = function(code, context, filename, callback) {
+ if (code === '.scope') {
+ client.reqScopes(callback);
+ return;
+ }
+
client.reqEval(code, function(res) {
if (!res.success) {
if (res.message) {
- callback(new Error(res.message));
+ if (/SyntaxError/.test(res.message)) {
+ callback(new SyntaxError(res.message));
+ } else {
+ callback(new Error(res.message));
+ }
} else {
callback(null);
}
});
});
};
+ this.repl.context = {};
this.repl.prompt = '> ';
this.repl.rli.setPrompt('> ');
this.debugRepl = false;
this.repl.eval = this.repl._eval;
this.repl.context = this.context;
- this.repl.prompt = 'debug>';
- this.repl.rli.setPrompt('debug>');
+ this.repl.prompt = 'debug> ';
+ this.repl.rli.setPrompt('debug> ');
this.repl.displayPrompt();
};
-Interface.prototype.handleCommand = function(cmd) {
- var self = this;
-
- var client = this.client;
- var term = this.term;
-
- if (cmd == 'quit' || cmd == 'q' || cmd == 'exit') {
- self._lastCommand = null;
- self.tryQuit();
-
- } else if (/^r(un)?/.test(cmd)) {
- // DONE
- } else if (/^help/.test(cmd)) {
- // DONE
- } else if ('version' == cmd) {
- if (!client) {
- self.printNotConnected();
- return;
- }
- client.reqVersion(function(v) {
- console.log(v);
- });
-
- } else if (/info +breakpoints/.test(cmd)) {
- if (!client) {
- self.printNotConnected();
- return;
- }
- client.listbreakpoints(function(res) {
- console.log(res);
- });
-
-
- } else if ('l' == cmd || 'list' == cmd) {
- if (!client) {
- self.printNotConnected();
- return;
- }
-
- var from = client.currentSourceLine - 5;
- var to = client.currentSourceLine + 5;
-
- client.reqSource(from, to, function(res) {
- var lines = res.source.split('\n');
- for (var i = 0; i < lines.length; i++) {
- var lineno = res.fromLine + i + 1;
- if (lineno < from || lineno > to) continue;
-
- if (lineno == 1) {
- // The first line needs to have the module wrapper filtered out of
- // it.
- var wrapper = require('module').wrapper[0];
- lines[i] = lines[i].slice(wrapper.length);
- }
-
- if (lineno == 1 + client.currentSourceLine) {
- var nchars = intChars(lineno);
- var pointer = '';
- for (var j = 0; j < nchars - 1; j++) {
- pointer += '=';
- }
- pointer += '>';
- console.log(pointer + ' ' + lines[i]);
- } else {
- console.log(leftPad(lineno) + ' ' + lines[i]);
- }
- }
- });
-
- } else if (/^backtrace/.test(cmd) || /^bt/.test(cmd)) {
- if (!client) {
- self.printNotConnected();
- return;
- }
-
- client.fullTrace(function(bt) {
- if (bt.totalFrames == 0) {
- console.log('(empty stack)');
- } else {
- var text = '';
- var firstFrameNative = bt.frames[0].script.isNative;
- for (var i = 0; i < bt.frames.length; i++) {
- var frame = bt.frames[i];
- if (!firstFrameNative && frame.script.isNative) break;
-
- text += '#' + i + ' ';
- if (frame.func.inferredName && frame.func.inferredName.length > 0) {
- text += frame.func.inferredName + ' ';
- }
- text += require('path').basename(frame.script.name) + ':';
- text += (frame.line + 1) + ':' + (frame.column + 1);
- text += '\n';
- }
-
- console.log(text);
- }
- });
-
- } else if (cmd == 'scripts' || cmd == 'scripts full') {
- if (!client) {
- self.printNotConnected();
- return;
- }
- self.printScripts(cmd.indexOf('full') > 0);
-
- } else if (/^c(ontinue)?/.test(cmd)) {
- if (!client) {
- self.printNotConnected();
- return;
- }
-
- self.pause();
- client.reqContinue(function() {
- self.resume();
- });
-
- } else if (/^k(ill)?/.test(cmd)) {
- if (!client) {
- self.printNotConnected();
- return;
- }
- // kill
- if (self.child) {
- self.killQuestion(function(yes) {
- if (yes) {
- self.killChild();
- } else {
- self._lastCommand = null;
- }
- });
- } else {
- }
-
- } else if (/^next/.test(cmd) || /^n/.test(cmd)) {
- if (!client) {
- self.printNotConnected();
- return;
- }
- client.step('next', 1, function(res) {
- // Wait for break point. (disable raw mode?)
- });
-
- } else if (/^step/.test(cmd) || /^s/.test(cmd)) {
- if (!client) {
- self.printNotConnected();
- return;
- }
- client.step('in', 1, function(res) {
- // Wait for break point. (disable raw mode?)
- });
-
- } else if (/^print/.test(cmd) || /^p/.test(cmd)) {
- if (!client) {
- self.printNotConnected();
- return;
- }
- var i = cmd.indexOf(' ');
- if (i < 0) {
- console.log('print [expression]');
- } else {
- cmd = cmd.slice(i);
- client.reqEval(cmd, function(res) {
- if (!res.success) {
- console.log(res.message);
- return;
- }
-
- client.mirrorObject(res.body, function(mirror) {
- console.log(mirror);
- });
- });
- }
-
- } else {
- if (!/^\s*$/.test(cmd)) {
- // If it's not all white-space print this error message.
- console.log('Unknown command "%s". Try "help"', cmd);
- }
- }
-};
-
-
Interface.prototype.killChild = function() {
if (this.child) {
});
client.on('close', function() {
+ self.pause()
console.log('program terminated');
+ self.resume();
self.client = null;
self.killChild();
});
});
client.on('unhandledResponse', function(res) {
+ self.pause();
console.log('\r\nunhandled res:');
console.log(res);
+ self.resume();
});
client.on('break', function(res) {
};
-// argument full tells if it should display internal node scripts or not
-Interface.prototype.printScripts = function(displayNatives) {
- var client = this.client;
- var text = '';
- for (var id in client.scripts) {
- var script = client.scripts[id];
- if (typeof script == 'object' && script.name) {
- if (displayNatives ||
- script.name == client.currentScript ||
- !script.isNative) {
- text += script.name == client.currentScript ? '* ' : ' ';
- text += require('path').basename(script.name) + '\n';
- }
- }
- }
- process.stdout.write(text);
-};