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

Add support for Promises #458

Merged
merged 8 commits into from
Dec 5, 2016
Merged

Add support for Promises #458

merged 8 commits into from
Dec 5, 2016

Conversation

recrsn
Copy link
Collaborator

@recrsn recrsn commented Nov 27, 2016

This pull request implements a Promise based interface to bcrypt library. A Promise is returned whenever there is no callback function specified. We have taken care not to break any existing functionality or behavior. Tests for the new interface have also been added.

@mention-bot
Copy link

@Agathver, thanks for your PR! By analyzing the history of the files in this pull request, we identified @defunctzombie, @shovon and @charmander to be potential reviewers.

@recrsn
Copy link
Collaborator Author

recrsn commented Nov 27, 2016

This undoubtedly fails on node <= 4.4 since Promises are not available

@@ -36,6 +36,10 @@ module.exports.genSalt = function(rounds, ignore, cb) {
cb = arguments[1];
}

if(!cb) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style nitpick: space after if (basically, look at the rest of the file and try to follow that style for any new code you add.

/// @param {f} function to be encapsulated
/// @param {args} Array like, args to be passed to the called function
/// @return {Promise} a promise encapuslaing the function
function _promise(f,args) {
Copy link
Collaborator

@defunctzombie defunctzombie Nov 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no single letter variables please, fn is a good alternative

//for node 0.12 stupidity
var _from = Array.from;
if(!_from)
_from = function(args) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More nitpick: please wrap all subsequent statements inside curly brackets.

//cant do anything without promise

if(typeof Promise === 'undefined')
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please wrap all subsequent statements inside curly brackets.

};

if(typeof args !== 'Array')
args = _from(args);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Wrap in curly braces please.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a standard code style that you follow ?

Copy link
Contributor

@shovon shovon Nov 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, it looks like this repository does not have a specific code style outlined in any documents. You'll have to infer the style based on other code in this repository.

As far as my suggestions are concerned: terrible, terrible things have happened when people omit curly braces. One such example is the recent goto fail error that Apple had with their TLS suite. http://www.dwheeler.com/essays/apple-goto-fail.html#braces

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created a eslint code style to help me adhere to the style of the rest of the code.
Here is it: https://gist.github.com/Agathver/9762cc1c65878753e4e799348ee0411c

@recrsn
Copy link
Collaborator Author

recrsn commented Nov 27, 2016

Thanks for pointing out. Will be making changes to adhere to code style.

@defunctzombie
Copy link
Collaborator

Thank you. I also mirror @shovon in requesting that you add { } and avoid single line if statements. I prefer the consistency of just having { } for all if statements.

/// @param {function} function to be encapsulated
/// @param {Array-like} args to be passed to the called function
/// @return {Promise} a Promise encapuslaing the function
var _promise = function (fn, args) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't need _ and can live in a separate file probably in a new lib folder

//just polyfill here (for 0.12)
//this just wont work on node 0.12
//this just won't work on node 0.12
//var _from = Array.from || [].slice.call;

//for node 0.12 stupidity
var _from = Array.from;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_ are not needed, not sure what they are suppose to convey here.

},
test_hash_compare: function(assert) {
assert.expect(3);
bcrypt.genSalt(10, function(err, salt) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is the promise tested here?

var _promise = function (fn, args) {

//fn must be a function
var _self = this;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_ unnecessary

/// @return {Promise} a Promise encapuslaing the function
var _promise = function (fn, args) {

//fn must be a function
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment doesn't make sense to me here

@defunctzombie
Copy link
Collaborator

@ncb000gt thoughts? I am +1 on adding promises support.

@Agathver please update the README with documentation outlining the new promises support and how to use it.

module.exports.promise = function (fn, context, args) {

//polyfill (for 0.12)
//avoid [].slice.call due to performance issues on v8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says it avoids [].slice.call because of performance issues with arguments, then proceeds to use instead… [].slice.call. It doesn’t matter, though, because arguments is never passed to it, and that by itself would already be a deoptimization.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code uses Array.from if available. But that is not available in node 0.12 so [].slice.call is used instead. args in most cases will be an arguments abject passed from another method.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “performance problem” already exists when you pass arguments to exports.promise, and exists as much for Array.from as it exists for [].slice.call. Since the JavaScript part of the bcrypt bindings isn’t the slow one, though, it doesn’t really matter and you don’t need to comment on it here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the block altogether.

@recrsn
Copy link
Collaborator Author

recrsn commented Nov 28, 2016

@defunctzombie My first language is not English, so please review the updated README. I'll try my best to clarify if something is unclear.

@@ -160,7 +205,7 @@ If you are using bcrypt on a simple script, using the sync mode is perfectly fin
* `hash(data, salt, cb)`
* `data` - [REQUIRED] - the data to be encrypted.
* `salt` - [REQUIRED] - the salt to be used to hash the password. if specified as a number then a salt will be generated with the specified number of rounds and used (see example under **Usage**).
* `cb` - [REQUIRED] - a callback to be fired once the data has been encrypted. uses eio making it asynchronous.
* `cb` - [OPTIONAL] - a callback to be fired once the data has been encrypted. uses eio making it asynchronous. If `cb` is not specified, a `Promise` is returned if Promise support is available.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two spaces after If looks strange

const someOtherPlaintextPassword = 'not_bacon';
```

#### To hash a password:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can avoid doing many examples and just say something along the lines of: any async method which takes a callback, can optionally return a promise if no callback is provided (or something of that nature). And maybe do a quick few line example. No need to go over all the api methods again.

@@ -155,8 +164,16 @@ module.exports.compare = function(data, hash, cb) {
});
}

if (!cb || typeof cb !== 'function') {
return;
//cb exists but not a function
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: space after the // I think that's how we do it in other places in the file.

assert.done();
};

//only run this tests if Promise is available
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only run these tests if Promise is available

var bcrypt = require('../bcrypt');

var fail = function(assert, error) {
assert.ok(false, error);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to require assert? Or is it already present globally?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert is passed to test cases by nodeunit

@defunctzombie
Copy link
Collaborator

@Agathver great work and good follow through on all of the feed back!

I will give @ncb000gt through tomorrow to give any comments/review but I am happy with this and will merge and release on Sunday.

@defunctzombie
Copy link
Collaborator

@shovon @charmander any additional showstopper feedback?

@shovon
Copy link
Contributor

shovon commented Dec 3, 2016

@defunctzombie LGTM

@defunctzombie defunctzombie merged commit 2488473 into kelektiv:master Dec 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants