Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

promisify-node

Package Overview
Dependencies
Maintainers
2
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

promisify-node - npm Package Compare versions

Comparing version 0.3.0 to 0.4.0

test/examples/fn-export.js

110

index.js
const Promise = require("nodegit-promise");
const args = require("./utils/args");
const cloneFunction = require("./utils/cloneFunction");
const objectAssign = require("object-assign");

@@ -15,13 +17,29 @@ // Unfortunately this list is not exhaustive, so if you find that a method does

* @param {String} parentKeyName - Tracks the keyName in a digestable format.
* @param {Boolean} noMutate - if set to true then all reference properties are
* cloned to avoid mutating the original object.
* @returns {*} exports - Identity.
*/
function processExports(exports, test, cached, parentKeyName) {
// Return early if this object has already been processed.
if (cached.indexOf(exports) > -1) {
function processExports(exports, test, cached, parentKeyName, noMutate) {
if(!exports) {
return exports;
}
// Record this object in the cache.
cached.push(exports);
if(noMutate || typeof exports === "function") {
// When not mutating we have to cache the original and the wrapped clone.
var cacheResult = cached.filter(function(c) { return c.original === exports; });
if(cacheResult.length) {
return cacheResult[0].wrapped;
}
} else {
// Return early if this object has already been processed.
if (cached.indexOf(exports) > -1) {
return exports;
}
}
// Record this object in the cache, if it is not a function.
if(typeof exports != "function") {
cached.push(exports);
}
// Pass through if not an object or function.

@@ -33,23 +51,49 @@ if (typeof exports != "object" && typeof exports != "function") {

var name = exports.name + "#";
var target;
// If a function, simply return it wrapped.
if (typeof exports === "function") {
var wrapped = exports;
var isAsyncFunction = false;
// Check the callback either passes the test function, or accepts a callback.
if ((test && test(exports, exports.name, parentKeyName))
// If the callback name exists as the last argument, consider it an
// asynchronous function. Brittle? Fragile? Effective.
|| (callbacks.indexOf(args(exports).slice(-1)[0]) > -1)) {
// Assign the new function in place.
wrapped = Promise.denodeify(exports);
isAsyncFunction = true;
} else if(noMutate) {
// If not mutating, then we need to clone the function, even though it isn't async.
wrapped = cloneFunction(exports);
}
// Set which object we'll mutate based upon the noMutate flag.
target = noMutate ? wrapped : exports;
// Here we can push our cloned/wrapped function and original onto cache.
cached.push({
original: exports,
wrapped: wrapped
});
// Find properties added to functions.
for (var keyName in exports) {
exports[keyName] = processExports(exports[keyName], test, cached, name);
target[keyName] = processExports(exports[keyName], test, cached, name, noMutate);
}
// Assign the new function in place.
var wrapped = Promise.denodeify(exports);
// Find methods on the prototype, if there are any.
if (Object.keys(exports.prototype).length) {
processExports(exports.prototype, test, cached, name);
// Attach the augmented prototype.
wrapped.prototype = processExports(exports.prototype, test, cached, name, noMutate);
}
// Attach the augmented prototype.
wrapped.prototype = exports.prototype;
// Ensure attached properties to the previous function are accessible.
wrapped.__proto__ = exports;
// Only do this if it's an async (wrapped) function, else we're setting
// __proto__ to itself, which isn't allowed.
if(isAsyncFunction) {
wrapped.__proto__ = exports;
}

@@ -59,5 +103,16 @@ return wrapped;

Object.keys(exports).map(function(keyName) {
// Make a shallow clone if we're not mutating and set it as the target, else just use exports
target = noMutate ? objectAssign({}, exports) : exports;
// We have our shallow cloned object, so put it (and the original) in the cache
if(noMutate) {
cached.push({
original: exports,
wrapped: target
});
}
Object.keys(target).map(function(keyName) {
// Convert to values.
return [keyName, exports[keyName]];
return [keyName, target[keyName]];
}).filter(function(keyVal) {

@@ -69,6 +124,4 @@ var keyName = keyVal[0];

if (typeof value === "object") {
processExports(exports, test, cached, keyName + ".");
}
// Filter to functions with callbacks only.
else if (typeof value === "function") {
processExports(value, test, cached, keyName + ".", noMutate);
} else if (typeof value === "function") {
// If a filter function exists, use this to determine if the function

@@ -81,7 +134,3 @@ // is asynchronous.

// If the callback name exists as the last argument, consider it an
// asynchronous function. Brittle? Fragile? Effective.
if (callbacks.indexOf(args(value).slice(-1)[0]) > -1) {
return true;
}
return true;
}

@@ -93,6 +142,6 @@ }).forEach(function(keyVal) {

// Wrap this function and reassign.
exports[keyName] = processExports(func, test, cached, parentKeyName);
target[keyName] = processExports(func, test, cached, parentKeyName, noMutate);
});
return exports;
return target;
}

@@ -105,5 +154,6 @@

* @param {Function} test - Optional function to identify async methods.
* @param {Boolean} noMutate - Optional set to true to avoid mutating the target.
* @returns {*} exports - The resolved value from require or passed in value.
*/
module.exports = function(name, test) {
module.exports = function(name, test, noMutate) {
var exports = name;

@@ -115,2 +165,4 @@

exports = require(name);
// Unless explicitly overridden, don't mutate when requiring modules.
noMutate = !(noMutate === false);
}

@@ -120,3 +172,3 @@

// promises.
return processExports(exports, test, []);
return processExports(exports, test, [], undefined, noMutate);
};

@@ -123,0 +175,0 @@

{
"name": "promisify-node",
"version": "0.3.0",
"version": "0.4.0",
"description": "Wrap Node-callback functions to return Promises.",
"main": "index.js",
"dependencies": {
"nodegit-promise": "~4.0.0"
"nodegit-promise": "~4.0.0",
"object-assign": "^4.0.1"
},

@@ -9,0 +10,0 @@ "devDependencies": {

@@ -73,2 +73,28 @@ Promisify Node

Wrap without mutating the original:
```javascript
var promisify = require("promisify-node");
var myObj = {
myMethod: function(a, b, cb) {
cb(a, b);
}
};
// Store the original method to check later
var originalMethod = myObj.myMethod;
// Now store the result, since the 'true' value means it won't mutate 'myObj'.
var promisifiedObj = promisify(myObj, undefined, true);
// Intentionally cause a failure by passing an object and inspect the message.
promisifiedObj.myMethod({ msg: "Failure!" }, null).then(null, function(err) {
console.log(err.msg);
});
// The original method is still intact
assert(myObj.myMethod === originalMethod);
assert(promisifiedObj.myMethod !== myObj.myMethod);
```
### Tests ###

@@ -75,0 +101,0 @@

var promisify = require("../");
var assert = require("assert");
var assert = require("assert"),
fsOriginal = require('fs');
describe("Promisify", function() {
function isPromisified(fn, ctx) {
var result = fn && fn.apply(ctx, Array.prototype.slice.call(arguments, 2));
return result && (typeof result.then === 'function');
}
it("can convert a basic async function", function() {

@@ -33,2 +39,37 @@ function test(cb) {

});
it("doesn't mutate objects for other consumers", function() {
var fsp = promisify("fs");
var fs2 = require("fs");
assert(fsOriginal.readFile !== fsp.readFile, "pre-required mutated");
assert(fsOriginal.readFile === fs2.readFile, "post-required mutated");
assert(fsp.readFile !== fs2.readFile, "post-required mutated");
});
it("doesn't mutate functions for other consumers", function() {
var fn = require(__dirname + "/examples/fn-export.js");
var fnx = fn.x;
var fnp = promisify(__dirname + "/examples/fn-export.js");
var fn2 = require(__dirname + "/examples/fn-export.js");
assert(fn.x !== fnp, "pre-required mutated");
assert(fn2.x !== fnp, "post-required mutated");
assert(fn.x === fnx, "function property mutated");
assert(fnp.x !== fn, "function property not replaced");
});
it("doesn't mutate prototypes for other consumers", function() {
var A = require(__dirname + "/examples/proto-export.js");
var a = new A(5);
var Ap = promisify(__dirname + "/examples/proto-export.js");
var ap = new Ap(5);
var A2 = require(__dirname + "/examples/proto-export.js");
var a2 = new A2(5);
assert(isPromisified(ap.a, ap), "prototype method not promisified");
assert(a.a !== ap.a, "pre-required mutated");
assert(a2.a !== ap.a, "post-required mutated");
assert(a2.a === a.a, "post-required mutated");
});
});

@@ -108,3 +149,75 @@

});
it("can deal with the same async function being present in an object more than once", function() {
var a = {
a: function(d, cb) {
cb && cb(null, d);
}
};
a.b = a.a;
a = promisify(a);
assert(a.a(5) !== undefined, "function not wrapped");
assert(typeof a.a(5).then === "function", "function not wrapped");
assert(a.b(5) !== undefined, "duplicate function not wrapped");
assert(typeof a.b(5).then === "function", "duplicate function not wrapped");
});
it("can deal with cyclical function properties", function() {
var a = function(d, cb) {
cb && cb(null, d);
};
a.a = a;
a = promisify(a);
assert(a(5) !== undefined, "function not wrapped");
assert(typeof a(5).then === "function", "function not wrapped");
assert(a.a(5) !== undefined, "function property not wrapped");
assert(typeof a.a(5).then === "function", "function property not wrapped");
});
});
describe("no mutate", function() {
it("can promisify an object without mutating it", function() {
var a = {
a: function(cb) { cb(); }
};
var b = promisify(a, undefined, true);
assert(isPromisified(b.a, b), "method not promisified");
assert(a.a !== b.a, "object mutated");
});
it("can promisify a function's properties without mutating it", function() {
var a = function(cb){ cb(null, 1); };
a.a = function(cb) { cb(); };
var b = promisify(a, undefined, true);
assert(isPromisified(b), "method not promisified");
assert(isPromisified(b.a, b), "method property not promisified");
assert(a.a !== b, "method property mutated");
assert(a.a !== b.a, "method property mutated");
});
it("can promisify a constructor without mutating it", function() {
var A = function(){ };
A.a = function(cb) { cb(); };
A.prototype.a = function(cb) { cb(null, 2); };
var B = promisify(A, undefined, true);
var b = new B();
assert(isPromisified(B.a, B), "method property not promisified");
assert(isPromisified(b.a, b), "prototype method not promisified");
assert(A.a !== B.a, "method property mutated");
assert(A.prototype.a !== b.a, "prototype mutated");
});
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc