Skip to content

Commit 215c421

Browse files
committed
Attempted first class support for Promise, see #36, #38
1 parent 89c1940 commit 215c421

File tree

7 files changed

+248
-122
lines changed

7 files changed

+248
-122
lines changed

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "bcryptjs",
33
"description": "Optimized bcrypt in plain JavaScript with zero dependencies.",
4-
"version": "2.3.0",
4+
"version": "2.4.0",
55
"main": "dist/bcrypt-isaac.js",
66
"license": "New-BSD",
77
"homepage": "http://dcode.io/",

dist/bcrypt.js

Lines changed: 91 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@
8787

8888
// Default fallback, if any
8989
randomFallback = null;
90-
9190
/**
9291
* Sets the pseudo random number generator to use as a fallback if neither node's `crypto` module nor the Web Crypto
9392
* API is available. Please note: It is highly important that the PRNG used is cryptographically secure and that it
@@ -132,6 +131,8 @@
132131
* @param {(number|function(Error, string=))=} rounds Number of rounds to use, defaults to 10 if omitted
133132
* @param {(number|function(Error, string=))=} seed_length Not supported.
134133
* @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting salt
134+
* @returns {!Promise} If `callback` has been omitted
135+
* @throws {Error} If the callback argument is present but not a function
135136
* @expose
136137
*/
137138
bcrypt.genSalt = function(rounds, seed_length, callback) {
@@ -141,19 +142,35 @@
141142
if (typeof rounds === 'function')
142143
callback = rounds,
143144
rounds = GENSALT_DEFAULT_LOG2_ROUNDS;
144-
if (typeof callback !== 'function')
145-
throw Error("Illegal callback: "+typeof(callback));
146-
if (typeof rounds !== 'number') {
147-
nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof rounds))));
148-
return;
145+
146+
function _async(callback) {
147+
nextTick(function() { // Pretty thin, but salting is fast enough
148+
if (typeof rounds !== 'number') {
149+
callback(Error("Illegal arguments: "+(typeof rounds)));
150+
return;
151+
}
152+
try {
153+
callback(null, bcrypt.genSaltSync(rounds));
154+
} catch (err) {
155+
callback(err);
156+
}
157+
});
149158
}
150-
nextTick(function() { // Pretty thin, but salting is fast enough
151-
try {
152-
callback(null, bcrypt.genSaltSync(rounds));
153-
} catch (err) {
154-
callback(err);
155-
}
156-
});
159+
160+
if (callback) {
161+
if (typeof callback !== 'function')
162+
throw Error("Illegal callback: "+typeof(callback));
163+
_async(callback);
164+
} else
165+
return new Promise(function(resolve, reject) {
166+
_async(function(err, res) {
167+
if (err) {
168+
reject(err);
169+
return;
170+
}
171+
resolve(res);
172+
});
173+
});
157174
};
158175

159176
/**
@@ -177,22 +194,40 @@
177194
* Asynchronously generates a hash for the given string.
178195
* @param {string} s String to hash
179196
* @param {number|string} salt Salt length to generate or salt to use
180-
* @param {function(Error, string=)} callback Callback receiving the error, if any, and the resulting hash
197+
* @param {function(Error, string=)=} callback Callback receiving the error, if any, and the resulting hash
181198
* @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed
182199
* (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms.
200+
* @returns {!Promise} If `callback` has been omitted
201+
* @throws {Error} If the callback argument is present but not a function
183202
* @expose
184203
*/
185204
bcrypt.hash = function(s, salt, callback, progressCallback) {
186-
if (typeof callback !== 'function')
187-
throw Error("Illegal callback: "+typeof(callback));
188-
if (typeof s === 'string' && typeof salt === 'number')
189-
bcrypt.genSalt(salt, function(err, salt) {
205+
206+
function _async(callback) {
207+
if (typeof s === 'string' && typeof salt === 'number')
208+
bcrypt.genSalt(salt, function(err, salt) {
209+
_hash(s, salt, callback, progressCallback);
210+
});
211+
else if (typeof s === 'string' && typeof salt === 'string')
190212
_hash(s, salt, callback, progressCallback);
213+
else
214+
nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof salt))));
215+
}
216+
217+
if (callback) {
218+
if (typeof callback !== 'function')
219+
throw Error("Illegal callback: "+typeof(callback));
220+
_async(callback);
221+
} else
222+
return new Promise(function(resolve, reject) {
223+
_async(function(err, res) {
224+
if (err) {
225+
reject(err);
226+
return;
227+
}
228+
resolve(res);
229+
});
191230
});
192-
else if (typeof s === 'string' && typeof salt === 'string')
193-
_hash(s, salt, callback, progressCallback);
194-
else
195-
nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof salt))));
196231
};
197232

198233
/**
@@ -237,29 +272,46 @@
237272
* Asynchronously compares the given data against the given hash.
238273
* @param {string} s Data to compare
239274
* @param {string} hash Data to be compared to
240-
* @param {function(Error, boolean)} callback Callback receiving the error, if any, otherwise the result
275+
* @param {function(Error, boolean)=} callback Callback receiving the error, if any, otherwise the result
241276
* @param {function(number)=} progressCallback Callback successively called with the percentage of rounds completed
242277
* (0.0 - 1.0), maximally once per `MAX_EXECUTION_TIME = 100` ms.
243-
* @throws {Error} If the callback argument is invalid
278+
* @returns {!Promise} If `callback` has been omitted
279+
* @throws {Error} If the callback argument is present but not a function
244280
* @expose
245281
*/
246282
bcrypt.compare = function(s, hash, callback, progressCallback) {
247-
if (typeof callback !== 'function')
248-
throw Error("Illegal callback: "+typeof(callback));
249-
if (typeof s !== "string" || typeof hash !== "string") {
250-
nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof hash))));
251-
return;
252-
}
253-
if (hash.length !== 60) {
254-
nextTick(callback.bind(this, null, false));
255-
return;
283+
284+
function _async(callback) {
285+
if (typeof s !== "string" || typeof hash !== "string") {
286+
nextTick(callback.bind(this, Error("Illegal arguments: "+(typeof s)+', '+(typeof hash))));
287+
return;
288+
}
289+
if (hash.length !== 60) {
290+
nextTick(callback.bind(this, null, false));
291+
return;
292+
}
293+
bcrypt.hash(s, hash.substr(0, 29), function(err, comp) {
294+
if (err)
295+
callback(err);
296+
else
297+
callback(null, safeStringCompare(comp, hash));
298+
}, progressCallback);
256299
}
257-
bcrypt.hash(s, hash.substr(0, 29), function(err, comp) {
258-
if (err)
259-
callback(err);
260-
else
261-
callback(null, safeStringCompare(comp, hash));
262-
}, progressCallback);
300+
301+
if (callback) {
302+
if (typeof callback !== 'function')
303+
throw Error("Illegal callback: "+typeof(callback));
304+
_async(callback);
305+
} else
306+
return new Promise(function(resolve, reject) {
307+
_async(function(err, res) {
308+
if (err) {
309+
reject(err);
310+
return;
311+
}
312+
resolve(res);
313+
});
314+
});
263315
};
264316

265317
/**

0 commit comments

Comments
 (0)