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

parley

Package Overview
Dependencies
Maintainers
2
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

parley - npm Package Compare versions

Comparing version 2.2.0 to 2.3.0

71

lib/private/Deferred.js

@@ -85,6 +85,53 @@ /**

*
* @param {Function} cb
* @param {Function} _cb
* The Node-style callback to invoke when the parley-wrapped implementation is finished.
*
* @param {Function} handleUncaughtException
* If specified, this function will be used as a handler for uncaught exceptions
* thrown from within `_cb`. **But REMEMBER: this will not handle uncaught exceptions
* from any OTHER asynchronous callbacks which might happen to be used within `_cb`.**
* (It's the same sort of function you might pass into `.catch()`.)
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Example usage:
*
* ```
* User.create({ username: 'foo' }).exec(function (err, result) {
* if (err) {
* if (err.code === 'E_UNIQUE') { return res.badRequest('Username already in use.'); }
* else { return res.serverError(err); }
* }
*
* return res.ok();
*
* }, res.serverError);
* ```
*/
Deferred.prototype.exec = function(cb){
Deferred.prototype.exec = function(_cb, handleUncaughtException){
// If 2nd argument was provided, wrap `cb` in another function that protects
// against uncaught exceptions. Otherwise, just use `_cb` as-is.
var cb;
if (!_.isUndefined(handleUncaughtException)) {
if (!_.isFunction(handleUncaughtException)) {
throw new Error(
'Sorry, `.exec()` doesn\'t know how to handle an uncaught exception handler like that:\n'+
util.inspect(handleUncaughtException, {depth: 1})+'\n'+
'If provided, the 2nd argument to .exec() should be a function like `function(err){...}`\n'+
'(This function will be used as a failsafe in case the callback throws an uncaught error.)\n'+
'See http://npmjs.com/package/parley for help.'
);
}//-•
cb = function _tryToRunCb() {
try {
// > Note that we don't use .slice() -- this is for perf.
// > (see https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#what-is-safe-arguments-usage)
return _cb.apply(undefined, arguments);
} catch (e) { return handleUncaughtException(e); }
};
}
else {
cb = _cb;
}
// Since thar be closure scope below, a hazard for young `this`s, we define `self`.

@@ -166,5 +213,13 @@ var self = this;

if (arguments.length > 2) {
return cb.apply(undefined, Array.prototype.slice.call(arguments));
// > Note that we don't use .slice() -- this is for perf.
// > (see https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#what-is-safe-arguments-usage)
return cb.apply(undefined, arguments);
}
// Otherwise, this is the normal case.
// If there's no result, just call the callback w/ no args.
// (This just makes for better log output, etc.)
else if (_.isUndefined(result)) {
return cb();
}
// Otherwise, there's a result, so send it back.
else {

@@ -174,3 +229,3 @@ return cb(undefined, result);

});
});//</self._handleExec>
} catch (e) {

@@ -208,3 +263,5 @@

var promise = this.toPromise();
return promise.then.apply(promise, Array.prototype.slice.call(arguments));
// > Note that we don't use .slice() -- this is for perf.
// > (see https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#what-is-safe-arguments-usage)
return promise.then.apply(promise, arguments);
};

@@ -220,3 +277,5 @@

var promise = this.toPromise();
return promise.catch.apply(promise, Array.prototype.slice.call(arguments));
// > Note that we don't use .slice() -- this is for perf.
// > (see https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#what-is-safe-arguments-usage)
return promise.catch.apply(promise, arguments);
};

@@ -223,0 +282,0 @@

2

package.json
{
"name": "parley",
"version": "2.2.0",
"version": "2.3.0",
"description": "Practical, lightweight flow control for Node.js. Supports callbacks and promises.",

@@ -5,0 +5,0 @@ "main": "lib/parley.js",

@@ -222,2 +222,81 @@ parley

#### Handling uncaught exceptions
Out of the box, when using asynchronous callbacks in Node.js, _if the code in your callback throws an uncaught error, the process **will crash!**_
For example, the following code would crash the process:
```javascript
setTimeout(function (){
// Since this string can't be parsed as JSON, this will throw an error.
// And since we aren't using try...catch, it will crash the process.
JSON.parse('who0ps"thisis totally not valid js{}n');
return res.ok();
}, 50);
```
To protect against this, always be sure to use try...catch blocks around any logic
that might throw in an asynchronous, Node-style callback.
For example:
```javascript
setTimeout(function (){
try {
JSON.parse('who0ps"thisis totally not valid js{}n');
} catch (e) { return res.serverError(e); }
return res.ok();
}, 50);
```
Here are a few common use cases to watch out for:
+ basic JavaScript errors; e.g. syntax issues, or trying to use the dot (.) operator on `null`.
+ trying to JSON.parse() some data that is not a valid, parseable JSON string
+ trying to JSON.stringify() a circular object
+ RPS methods in Sails.js; e.g. `.publish()`, `.subscribe()`, `.unsubscribe()`
+ Waterline's `.validate()` model method
+ Node core's `assert()`
+ most synchronous methods from Node core (e.g. `fs.readFileSync()`)
+ any synchronous machine called with `.execSync()`
+ other synchronous functions from 3rd party libraries
_Note that this is not an issue when using promises, since `.then()` automatically catches uncaught errors
(although there are other considerations when using promises-- for instance, forgetting to use .catch()
each time .then() is used is a common source of hard-to-debug issues, technical debt, and memory leaks.)_
> **EXPERIMENTAL:** As of parley 2.3.x, there is a new, experimental feature that allows you to
> easily provide an extra layer of protection: an optional 2nd argument to `.exec()`. If specified,
> this function will be used as an uncaught exception handler-- a simple fallback just in case something
> happens to go wrong in your callback function.
>
> This allows you to safely write code like the following without crashing the server:
>
> ```javascript
> User.create({ username: 'foo' }).exec(function (err, result) {
> if (err) {
> if (err.code === 'E_UNIQUE') { return res.badRequest('Username already in use.'); }
> else { return res.serverError(err); }
> }
>
> var result = JSON.parse('who0ps"thisis totally not valid js{}n');
>
> return res.ok(result);
>
> }, res.serverError);
> ```
>
> Of course, it's still best to be explicit about error handling whenever possible.
> The extra layer of protection is just that-- it's here to help prevent issues
> stemming from the myriad runtime edge cases it's almost impossible to anticipate
> when building a production-ready web application.
### Flow control

@@ -302,3 +381,3 @@

Much like "if/then/finally" above, the secret to tidy asynchronous recursion is self-calling function.
Much like "if/then/finally" above, the secret to tidy asynchronous recursion is the (notorious) self-calling function.

@@ -305,0 +384,0 @@ ```javascript

@@ -376,2 +376,22 @@ /**

it('should be performant enough when calling fake "validate" w/ .exec() + uncaught exception handler (using benchSync())', function (){
benchSync('mock "validate().exec()"', [
function (){
validate()
.exec(function (err) {
if (err) {
console.error('Unexpected error running benchmark:',err);
}//>-
// Note: Since the handler is blocking, we actually make
// it in here within one tick of the event loop.
}, function (){
console.error('Consistency violation: This should never happen: Something is broken!');
throw new Error('Consistency violation: This should never happen: Something is broken!');
});
}
]);
});
it('should be performant enough calling fake "validateButWith9CustomMethods" w/ .exec() (using benchSync())', function (){

@@ -378,0 +398,0 @@ benchSync('mock "validateButWith9CustomMethods().exec()"', [

@@ -91,2 +91,18 @@ /**

});
describe('with two arguments and a callback that throws an uncaught exception', function() {
var deferred; before(function(){ deferred = parley(function(done){ setTimeout(function (){ return done(undefined, 'hello!'); }, 12); }); });
it('should run uncaught exception handler', function(done){
this.slow(300);
deferred.exec(function (){
throw new Error('This is uncaught! Watch out!');
}, function(uncaughtError) {
try {
assert.equal(uncaughtError.message, 'This is uncaught! Watch out!');
} catch (e) { return done(e); }
return done();
});
});
});
});//</.exec()>

@@ -93,0 +109,0 @@

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