Fix #3379 prevent domain.intercept passing 1st arg to cb
authorMarc Harter <wavded@gmail.com>
Wed, 6 Jun 2012 15:17:01 +0000 (10:17 -0500)
committerisaacs <i@izs.me>
Sat, 9 Jun 2012 06:32:13 +0000 (23:32 -0700)
doc/api/domain.markdown
lib/domain.js
test/simple/test-domain.js

index 5bbdcc33a0af84277809d9aec90bbdb462e965c1..f8df926ab8108705b657088ef31c0cf5fb92282d 100644 (file)
@@ -227,13 +227,16 @@ with a single error handler in a single place.
     var d = domain.create();
 
     function readSomeFile(filename, cb) {
-      fs.readFile(filename, d.intercept(function(er, data) {
+      fs.readFile(filename, d.intercept(function(data) {
+        // note, the first argument is never passed to the
+        // callback since it is assumed to be the 'Error' argument
+        // and thus intercepted by the domain.
+
         // if this throws, it will also be passed to the domain
-        // additionally, we know that 'er' will always be null,
         // so the error-handling logic can be moved to the 'error'
         // event on the domain instead of being repeated throughout
         // the program.
-        return cb(er, JSON.parse(data));
+        return cb(null, JSON.parse(data));
       }));
     }
 
index e865a1faa05e703f49fe9199c956de479b600368..12ab409c3414f7f885dd6fe918dc79368b3c41c7 100644 (file)
@@ -167,6 +167,34 @@ Domain.prototype.bind = function(cb, interceptError) {
       return;
     }
 
+    // remove first-arg if intercept as assumed to be the error-arg
+    if (interceptError) {
+      var len = arguments.length;
+      var args;
+      switch (len) {
+        case 0:
+        case 1:
+          // no args that we care about.
+          args = [];
+          break;
+        case 2:
+          // optimization for most common case: cb(er, data)
+          args = [arguments[1]];
+          break;
+        default:
+          // slower for less common case: cb(er, foo, bar, baz, ...)
+          args = new Array(len - 1);
+          for (var i = 1; i < len; i++) {
+            args[i] = arguments[i - 1];
+          }
+          break;
+      }
+      self.enter();
+      var ret = cb.apply(this, args);
+      self.exit();
+      return ret;
+    }
+
     self.enter();
     var ret = cb.apply(this, arguments);
     self.exit();
index e20868ed0fc08c8a305f36fbf100f6bd1aa93255..72d7655dfaea54c32c802c2e55b499a0d292be47 100644 (file)
@@ -127,6 +127,13 @@ function fn(er) {
 var bound = d.intercept(fn);
 bound(new Error('bound'));
 
+// intercepted should never pass first argument to callback
+function fn2(data) {
+  assert.equal(data, 'data', 'should not be null err argument')
+}
+
+var bound = d.intercept(fn2);
+bound(null, 'data');
 
 
 // throwing in a bound fn is also caught,