Skip to content

Commit 19849e1

Browse files
committed
Improve the ability to find async functions.
This provides an optional filter function to aid with intelligently locatating nested functions that are asynchronous. Also better represents the original functions after wrapping.
1 parent 5c159e9 commit 19849e1

1 file changed

Lines changed: 47 additions & 7 deletions

File tree

index.js

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,70 @@ var callbacks = ["cb", "callback", "callback_", "done"];
1010
* inspecting the last argument in the parameter signature for a callback.
1111
*
1212
* @param {*} exports - Should be a function or an object, identity other.
13+
* @param {Function} test - Optional function to identify async methods.
14+
* @param {String} parentKeyName - Tracks the keyName in a digestable format.
1315
* @returns {*} exports - Identity.
1416
*/
15-
function processExports(exports) {
17+
function processExports(exports, test, cached, parentKeyName) {
18+
// Return early if this object has already been processed.
19+
if (cached.indexOf(exports) > -1) {
20+
return exports;
21+
}
22+
23+
// Record this object in the cache.
24+
cached.push(exports);
25+
1626
// Pass through if not an object or function.
1727
if (typeof exports != "object" && typeof exports != "function") {
1828
return exports;
1929
}
2030

31+
var name = exports.name + "#";
32+
2133
// If a function, simply return it wrapped.
2234
if (typeof exports === "function") {
23-
return Promise.denodeify(exports);
35+
// Find properties added to functions.
36+
for (var keyName in exports) {
37+
exports[keyName] = processExports(exports[keyName], test, cached, name);
38+
}
39+
40+
// Assign the new function in place.
41+
var wrapped = Promise.denodeify(exports);
42+
43+
// Find methods on the prototype, if there are any.
44+
if (Object.keys(exports.prototype).length) {
45+
processExports(exports.prototype, test, cached, name);
46+
}
47+
48+
// Attach the augmented prototype.
49+
wrapped.prototype = exports.prototype;
50+
51+
// Ensure attached properties to the previous function are accessible.
52+
wrapped.__proto__ = exports;
53+
54+
return wrapped;
2455
}
2556

2657
Object.keys(exports).map(function(keyName) {
2758
// Convert to values.
2859
return [keyName, exports[keyName]];
2960
}).filter(function(keyVal) {
61+
var keyName = keyVal[0];
3062
var value = keyVal[1];
3163

3264
// If an object is encountered, recursively traverse.
3365
if (typeof value === "object") {
34-
processExports(exports);
66+
processExports(exports, test, cached, keyName + ".");
3567
}
3668
// Filter to functions with callbacks only.
3769
else if (typeof value === "function") {
70+
// If a filter function exists, use this to determine if the function
71+
// is asynchronous.
72+
if (test) {
73+
// Pass the function itself, its keyName, and the parent keyName.
74+
return test(value, keyName, parentKeyName);
75+
}
76+
3877
// If the callback name exists as the last argument, consider it an
3978
// asynchronous function. Brittle? Fragile? Effective.
4079
if (callbacks.indexOf(args(value).slice(-1)[0]) > -1) {
@@ -45,8 +84,8 @@ function processExports(exports) {
4584
var keyName = keyVal[0];
4685
var func = keyVal[1];
4786

48-
// Assign the new function in place.
49-
exports[keyName] = Promise.denodeify(func);
87+
// Wrap this function and reassign.
88+
exports[keyName] = processExports(func, test, cached, parentKeyName);
5089
});
5190

5291
return exports;
@@ -56,9 +95,10 @@ function processExports(exports) {
5695
* Public API for Promisify. Will resolve modules names using `require`.
5796
*
5897
* @param {*} name - Can be a module name, object, or function.
98+
* @param {Function} test - Optional function to identify async methods.
5999
* @returns {*} exports - The resolved value from require or passed in value.
60100
*/
61-
module.exports = function(name) {
101+
module.exports = function(name, test) {
62102
var exports = name;
63103

64104
// If the name argument is a String, will need to resovle using the built in
@@ -69,7 +109,7 @@ module.exports = function(name) {
69109

70110
// Iterate over all properties and find asynchronous functions to convert to
71111
// promises.
72-
return processExports(exports);
112+
return processExports(exports, test, []);
73113
};
74114

75115
// Export callbacks to the module.

0 commit comments

Comments
 (0)