From 8c69d7bed47358d5ef4a5226f60e97145300b49b Mon Sep 17 00:00:00 2001 From: micnic Date: Sat, 29 Nov 2014 14:50:29 +0200 Subject: [PATCH] domain: forward args to .run(fn) Adds the feature to define arguments for the function called in domain.run(), this is supposed to be useful when a function is called from another context and some values from the current context are needed as arguments, it's similar to the callback from setTimeout or setInterval. PR-URL: https://github.com/iojs/io.js/pull/15 Reviewed-By: Chris Dickinson Reviewed-By: Ben Noordhuis --- benchmark/misc/domain-fn-args.js | 43 ++++++++++++++++++++++++++++++++ doc/api/domain.markdown | 5 ++-- lib/domain.js | 16 +++++++++++- test/simple/test-domain.js | 7 ++++++ 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 benchmark/misc/domain-fn-args.js diff --git a/benchmark/misc/domain-fn-args.js b/benchmark/misc/domain-fn-args.js new file mode 100644 index 00000000000000..36e9e900299bb2 --- /dev/null +++ b/benchmark/misc/domain-fn-args.js @@ -0,0 +1,43 @@ +var common = require('../common.js'); +var domain = require('domain'); + +var bench = common.createBenchmark(main, { + arguments: [0, 1, 2, 3], + n: [10] +}); + +var bdomain = domain.create(); +var gargs = [1, 2, 3]; + +function main(conf) { + + var args, ret, n = +conf.n; + var arguments = gargs.slice(0, conf.arguments); + bench.start(); + + bdomain.enter(); + for (var i = 0; i < n; i++) { + if (arguments.length >= 2) { + args = Array.prototype.slice.call(arguments, 1); + ret = fn.apply(this, args); + } else { + ret = fn.call(this); + } + } + bdomain.exit(); + + bench.end(n); +} + +function fn(a, b, c) { + if (!a) + a = 1; + + if (!b) + b = 2; + + if (!c) + c = 3; + + return a + b + c; +} \ No newline at end of file diff --git a/doc/api/domain.markdown b/doc/api/domain.markdown index 123020f14a9f1d..d3bf1c8506fa3c 100644 --- a/doc/api/domain.markdown +++ b/doc/api/domain.markdown @@ -260,13 +260,14 @@ uncaught exceptions to the active Domain object. Domain is a child class of [EventEmitter][]. To handle the errors that it catches, listen to its `error` event. -### domain.run(fn) +### domain.run(fn[, arg][, ...]) * `fn` {Function} Run the supplied function in the context of the domain, implicitly binding all event emitters, timers, and lowlevel requests that are -created in that context. +created in that context. Optionally, arguments can be passed to +the function. This is the most basic way to use a domain. diff --git a/lib/domain.js b/lib/domain.js index 4121ede82ccb05..f35bf838ca626a 100644 --- a/lib/domain.js +++ b/lib/domain.js @@ -195,9 +195,23 @@ Domain.prototype.remove = function(ee) { Domain.prototype.run = function(fn) { if (this._disposed) return; + + var ret; + this.enter(); - var ret = fn.call(this); + if (arguments.length >= 2) { + var len = arguments.length; + var args = new Array(len - 1); + + for (var i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + ret = fn.apply(this, args); + } else { + ret = fn.call(this); + } this.exit(); + return ret; }; diff --git a/test/simple/test-domain.js b/test/simple/test-domain.js index 25227585357ff7..41eb602e424ddb 100644 --- a/test/simple/test-domain.js +++ b/test/simple/test-domain.js @@ -258,6 +258,13 @@ var result = d.run(function () { assert.equal(result, 'return value'); +// check if the executed function take in count the applied parameters +result = d.run(function (a, b) { + return a + ' ' + b; +}, 'return', 'value'); +assert.equal(result, 'return value'); + + var fst = fs.createReadStream('stream for nonexistent file') d.add(fst) expectCaught++;