[debugger] implemented setBreakpoint, etc
authorFedor Indutny <fedor.indutny@gmail.com>
Sat, 10 Sep 2011 12:18:36 +0000 (19:18 +0700)
committerFedor Indutny <fedor.indutny@gmail.com>
Sat, 10 Sep 2011 12:18:36 +0000 (19:18 +0700)
Lift prototype methods not only as accessors, but as properties too.
this.print() supports javascript objects inspection
this.error() implemented, don't throw error at callbacks and commands
Fixed list() invokation, when script is not on a breakpoint
Removed obsolete process.nextTick from `step` commands

lib/_debugger.js

index 9864a2a..4575b17 100644 (file)
@@ -22,7 +22,8 @@
 var net = require('net'),
     repl = require('repl'),
     vm = require('vm'),
-    inherits = require('util').inherits,
+    util = require('util'),
+    inherits = util.inherits,
     spawn = require('child_process').spawn;
 
 exports.port = 5858;
@@ -419,6 +420,17 @@ Client.prototype.listbreakpoints = function(cb) {
   });
 };
 
+Client.prototype.setBreakpoint = function(req, cb) {
+  var req = {
+    command: 'setbreakpoint',
+    arguments: req
+  };
+
+  this.req(req, function(res) {
+    if (cb) cb(res);
+  });
+};
+
 Client.prototype.reqSource = function(from, to, cb) {
   var req = {
     command: 'source',
@@ -687,10 +699,15 @@ function Interface() {
       };
 
   function defineProperty(key, protoKey) {
-    Object.defineProperty(self.repl.context, key, {
-      get: proto[protoKey].bind(self),
-      enumerable: true
-    });
+    // Check arity
+    if (proto[protoKey].length === 0) {
+      Object.defineProperty(self.repl.context, key, {
+        get: proto[protoKey].bind(self),
+        enumerable: true
+      });
+    } else {
+      self.repl.context[key] = proto[protoKey].bind(self);
+    }
   };
 
   for (var i in proto) {
@@ -734,7 +751,8 @@ Interface.prototype.resume = function(silent) {
 Interface.prototype.print = function(text) {
   process.stdout.cursorTo(0);
   process.stdout.clearLine(1);
-  process.stdout.write(text + '\n');
+  process.stdout.write(typeof text === 'string' ? text : util.inspect(text));
+  process.stdout.write('\n');
 };
 
 Interface.prototype.childPrint = function(text) {
@@ -742,9 +760,13 @@ Interface.prototype.childPrint = function(text) {
     return chunk;
   }).map(function(chunk) {
     return '< ' + chunk;
-  }).join('\n'));
+  }).join('\n') + '\n');
 };
 
+Interface.prototype.error = function(text) {
+  this.print(text);
+  this.resume();
+};
 
 Interface.prototype.handleBreak = function(r) {
   this.pause();
@@ -760,7 +782,7 @@ Interface.prototype.handleBreak = function(r) {
 
 
 Interface.prototype.requireConnection = function() {
-  if (!this.client) throw Error('App isn\'t running... Try `run` instead');
+  if (!this.client) this.error('App isn\'t running... Try `run` instead');
 };
 
 Interface.prototype.controlEval = function(code, context, filename, callback) {
@@ -841,7 +863,7 @@ Interface.prototype.help = function() {
 // Run script
 Interface.prototype.run = function() {
   if (this.child) {
-    throw Error('App is already running... Try `restart` instead');
+    this.error('App is already running... Try `restart` instead');
   } else {
     this.trySpawn();
   }
@@ -850,7 +872,7 @@ Interface.prototype.run = function() {
 
 // Restart script
 Interface.prototype.restart = function() {
-  if (!this.child) throw Error('App isn\'t running... Try `run` instead');
+  if (!this.child) return this.error('App isn\'t running... Try `run` instead');
 
   var self = this;
 
@@ -886,6 +908,8 @@ Interface.prototype.list = function() {
 
   self.pause();
   client.reqSource(from, to, function(res) {
+    if (!res.source) return self.error('You can\'t list source code right now');
+
     var lines = res.source.split('\n');
     for (var i = 0; i < lines.length; i++) {
       var lineno = res.fromLine + i + 1;
@@ -982,9 +1006,7 @@ Interface.prototype.cont = function() {
 
   var self = this;
   this.client.reqContinue(function() {
-    process.nextTick(function() {
-      self.resume();
-    });
+    self.resume();
   });
 };
 
@@ -997,9 +1019,7 @@ Interface.prototype.next = function() {
 
   var self = this;
   this.client.step('next', 1, function(res) {
-    process.nextTick(function() {
-      self.resume();
-    });
+    self.resume();
   });
 };
 
@@ -1012,9 +1032,7 @@ Interface.prototype.step = function() {
 
   var self = this;
   this.client.step('in', 1, function(res) {
-    process.nextTick(function() {
-      self.resume();
-    });
+    self.resume();
   });
 };
 
@@ -1027,9 +1045,29 @@ Interface.prototype.out = function() {
 
   var self = this;
   this.client.step('out', 1, function(res) {
-    process.nextTick(function() {
-      self.resume();
-    });
+    self.resume();
+  });
+};
+
+
+// Add breakpoint
+Interface.prototype.setBreakpoint = function(script, line, condition) {
+  var self = this,
+      req = {
+        type: 'script',
+        target: script,
+        line: line,
+        condition: condition
+      };
+
+  self.pause();
+  self.client.setBreakpoint(req, function(res) {
+    if (res.success) {
+      self.print('ok');
+    } else {
+      self.print(req.message || 'error!');
+    }
+    self.resume();
   });
 };
 
@@ -1042,10 +1080,10 @@ Interface.prototype.breakpoints = function() {
   this.client.listbreakpoints(function(res) {
     if (res.success) {
       self.print(res.body);
+      self.resume();
     } else {
-      throw Error(res.message || 'Some error happened');
+      self.error(res.message || 'Some error happened');
     }
-    self.resume();
   });
 };