Skip to content

Instantly share code, notes, and snippets.

@jkrems
Last active December 21, 2015 14:09
Show Gist options
  • Save jkrems/6317838 to your computer and use it in GitHub Desktop.
Save jkrems/6317838 to your computer and use it in GitHub Desktop.
Transparent function and generator proxy
var toString$ = Object.prototype.toString;
// Ported from angular.js
var COMMENTS_PATTERN = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,
ARGS_PATTERN = /^function\s*(\*)?\s*[^\(]*\(\s*([^\)]*)\)/m,
ARG_PATTERN = /^\s*(_?)(\S+?)\1\s*$/;
module.exports = {
isGenerator: function isGenerator(obj) {
return toString$.call(obj).slice(8, -1) === 'Generator';
},
extractArgs: function(fn){
var source, ref$, _, genMarker, fnArgs, argArray;
var source = fn.toString().replace(COMMENTS_PATTERN, '');
var fnArgs = (source.match(ARGS_PATTERN))[2];
return fnArgs.split(',').map(function(arg) {
return arg.replace(ARG_PATTERN, '$2');
}).filter(function(arg) {
return !!arg;
});
}
};
'use strict';
var Q = require('q'),
isGenerator = require('./util').isGenerator,
extractArgs = require('./util').extractArgs;
// ported from Q
var wrapGenerator = module.exports = function wrapGenerator(makeGenerator) {
var inner = function() {
var callback, errback;
function continuer(verb, arg) {
try {
var result = generator[verb](arg);
return result.done ?
result.value : Q.when(result.value, callback, errback);
} catch (exception) {
return Q.reject(exception);
}
}
var generator = makeGenerator.apply(this, arguments);
if (isGenerator(generator)) {
callback = continuer.bind(this, 'next');
errback = continuer.bind(this, 'throw');
return callback();
} else {
return Q.when(generator);
}
};
var originalArgs = extractArgs(makeGenerator);
var fnProxy = new Function('inner', [
'return function (' + originalArgs.join(', ') + ') {',
' return inner(' + originalArgs.join(', ') + ');',
'};'
].join(''));
return fnProxy(inner);
}
if (module.parent == null) {
var assert = require('assert');
var fn = function (a, b) { return a + b; };
var args = extractArgs(fn);
assert.equal(args.length, 2);
assert.equal(args[0], 'a');
assert.equal(args[1], 'b');
assert.equal(fn(2, 3), 5);
var wrapped = wrapGenerator(fn);
assert.equal(wrapped.length, 2);
var args = extractArgs(wrapped);
assert.equal(args.length, 2);
assert.equal(args[0], 'a');
assert.equal(args[1], 'b');
wrapped(2, 3).done(function(result) {
assert.equal(result, 5);
console.log('ok');
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment