Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove eval #30

Merged
merged 4 commits into from Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
63 changes: 30 additions & 33 deletions index.js
Expand Up @@ -7,33 +7,34 @@ module.exports = thenify
/**
* Turn async functions into promises
*
* @param {Function} $$__fn__$$
* @param {Function} fn
* @return {Function}
* @api public
*/

function thenify($$__fn__$$, options) {
assert(typeof $$__fn__$$ === 'function')
return eval(createWrapper($$__fn__$$.name, options))
function thenify(fn, options) {
assert(typeof fn === 'function')
return createWrapper(fn, options)
}

/**
* Turn async functions into promises and backward compatible with callback
*
* @param {Function} $$__fn__$$
* @param {Function} fn
* @return {Function}
* @api public
*/

thenify.withCallback = function ($$__fn__$$, options) {
assert(typeof $$__fn__$$ === 'function')
thenify.withCallback = function (fn, options) {
assert(typeof fn === 'function')
options = options || {}
options.withCallback = true
if (options.multiArgs === undefined) options.multiArgs = true
return eval(createWrapper($$__fn__$$.name, options))
return createWrapper(fn, options)
}

function createCallback(resolve, reject, multiArgs) {
// default to true
if (multiArgs === undefined) multiArgs = true
return function(err, value) {
if (err) return reject(err)
var length = arguments.length
Expand All @@ -52,29 +53,25 @@ function createCallback(resolve, reject, multiArgs) {
}
}

function createWrapper(name, options) {
name = (name || '').replace(/\s|bound(?!$)/g, '')
function createWrapper(fn, options) {
options = options || {}
// default to true
var multiArgs = options.multiArgs !== undefined ? options.multiArgs : true
multiArgs = 'var multiArgs = ' + JSON.stringify(multiArgs) + '\n'

var withCallback = options.withCallback ?
'var lastType = typeof arguments[len - 1]\n'
+ 'if (lastType === "function") return $$__fn__$$.apply(self, arguments)\n'
: ''

return '(function ' + name + '() {\n'
+ 'var self = this\n'
+ 'var len = arguments.length\n'
+ multiArgs
+ withCallback
+ 'var args = new Array(len + 1)\n'
+ 'for (var i = 0; i < len; ++i) args[i] = arguments[i]\n'
+ 'var lastIndex = i\n'
+ 'return new Promise(function (resolve, reject) {\n'
+ 'args[lastIndex] = createCallback(resolve, reject, multiArgs)\n'
+ '$$__fn__$$.apply(self, args)\n'
+ '})\n'
+ '})'
var name = fn.name;
name = (name || '').replace(/\s|bound(?!$)/g, '')
var newFn = function () {
var self = this
var len = arguments.length
if (options.withCallback) {
var lastType = typeof arguments[len - 1]
if (lastType === 'function') return fn.apply(self, arguments)
}
var args = new Array(len + 1)
for (var i = 0; i < len; ++i) args[i] = arguments[i]
var lastIndex = i
return new Promise(function (resolve, reject) {
args[lastIndex] = createCallback(resolve, reject, options.multiArgs)
fn.apply(self, args)
})
}
Object.defineProperty(newFn, 'name', { value: name })
return newFn
}
24 changes: 24 additions & 0 deletions test/test.js
Expand Up @@ -69,3 +69,27 @@ it('fn(..args, callback())', function () {
assert.deepEqual(values, [1, 2, 3])
})
})

it('unicode function name', function () {
function 你好$hello_123(a, b, c, cb) {
cb(null, a, b, c)
}
var wrapper = thenify(你好$hello_123)
assert.equal(wrapper.name, '你好$hello_123')
wrapper(1, 2, 3).then(function (values) {
assert.deepEqual(values, [1, 2, 3])
})
})

it('invalid function name', function () {
function fn(a, b, c, cb) {
cb(null, a, b, c)
}

Object.defineProperty(fn, 'name', { value: 'fake(){a.b;})();(function(){//' })
var wrapper = thenify(fn)
assert.equal(wrapper.name, fn.name)
wrapper(1, 2, 3).then(function (values) {
assert.deepEqual(values, [1, 2, 3])
})
})