🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

prfun

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prfun - npm Package Compare versions

Comparing version
2.1.2
to
2.1.3
+13
-0
CHANGELOG.md

@@ -0,1 +1,14 @@

# prfun 2.1.3 (2015-12-11)
* Optimize the `Promise` subclass constructor to avoid costly overhead
in ES5 environments. The slow ES6 path is only used if necessary
for correctness (or if the native Promise implementation uses ES6
class syntax).
* Added `Promise#then0` to the API, which is a shim when a native
`Promise#then0` is not available. Some `Promise` implementations
provide this method, which is much more efficient than calling
`Promise#then` and discarding the result.
* Used `Promise#then0` in internal implementations where appropriate,
including `Promise.async` (where the use of generators can now yield
better performance than chaining promises in the usual way).
# prfun 2.1.2 (2015-11-20)

@@ -2,0 +15,0 @@ * Ensure that `Promise.async` always returns a `Promise`.

+210
-88

@@ -32,28 +32,72 @@ // Utility functions for ES6 Promises.

// Create a new Promise subclass (this is less cumbersome in es6!)
var PrFunPromise = function PrFunPromise(exec) {
var self = new ParentPromise(exec);
setPrototypeOf(self, PrFunPromise.prototype);
self._promiseConstructor = PrFunPromise;
return self;
};
setPrototypeOf(PrFunPromise, ParentPromise);
PrFunPromise.prototype = Object.create(ParentPromise.prototype);
PrFunPromise.prototype.constructor = PrFunPromise;
// This isn't quite right: the way we are creating the subclass
// above doesn't set the internal [[PromiseConstructor]] field,
// so we need to tweak the implementation of Promise.resolve()
var makeResolve = function(parentResolve) {
return function(x) {
if (x && typeof x === 'object' && x._promiseConstructor) {
if (this === x._promiseConstructor) {
return x;
} else {
var makeResolve = null;
var PrFunPromise = (function makeSubclass(ParentPromise) {
var PrFunPromise;
// jscs:disable maximumLineLength
var isClass = function isClass(v) {
// See: http://stackoverflow.com/questions/30758961/how-to-check-if-a-variable-is-an-es6-class-declaration
// And: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-function.prototype.tostring
return typeof v === 'function' && /^\s*class\s+/.test(v.toString());
};
// jscs:enable maximumLineLength
if (isClass(ParentPromise)) {
// ES6 classes are currently unoptimized in V8.
// So let's not use them unless ParentPromise does.
try {
/* jshint evil:true */
return eval('(function(ParentPromise){' +
'"use strict";' +
'return class PrFunPromise extends ParentPromise {};' +
'})')(ParentPromise);
} catch (e) { /* I guess true ES6 classes are not supported. */ }
}
// Try the "ES5 way"; this is fastest on ES5 engines.
// (Faster even than ES6 classes, at least on node 5.x, but we assume
// that the performance of native classes will catch up eventually.)
PrFunPromise = function PrFunPromise(resolver) {
ParentPromise.call(this, resolver);
};
setPrototypeOf(PrFunPromise, ParentPromise);
PrFunPromise.prototype = Object.create(ParentPromise.prototype);
PrFunPromise.prototype.constructor = PrFunPromise;
// Try it out first.
try {
PrFunPromise.resolve(5);
// Some native promise implementations will object to the "ES5 way".
// If they didn't, then let's go with this version.
return PrFunPromise;
} catch (e) { /* I guess we'll use the "real" ES6-compatible way. */ }
PrFunPromise = function PrFunPromise(exec) {
var self = new ParentPromise(exec);
setPrototypeOf(self, PrFunPromise.prototype);
self._promiseConstructor = PrFunPromise;
return self;
};
setPrototypeOf(PrFunPromise, ParentPromise);
PrFunPromise.prototype = Object.create(ParentPromise.prototype);
PrFunPromise.prototype.constructor = PrFunPromise;
// This isn't quite right: the way we are creating the subclass
// above doesn't set the internal [[PromiseConstructor]] field,
// so we need to tweak the implementation of Promise.resolve()
// (Note that [[PromiseConstructor]] has been removed from the
// latest draft of the ES6 spec, but it may still be present in
// your (buggy) native Promise implementation.)
makeResolve = function(parentResolve) {
return function(x) {
if (x && typeof x === 'object' && x._promiseConstructor) {
if (this === x._promiseConstructor) {
return x;
}
return new this(function(r) { r(x); });
}
}
return parentResolve.call(this, x);
return parentResolve.call(this, x);
};
};
};
PrFunPromise.resolve = makeResolve(PrFunPromise.resolve);
return PrFunPromise;
})(ParentPromise);
if (makeResolve) {
PrFunPromise.resolve = makeResolve(PrFunPromise.resolve);
}
// Sometimes we just need to smash things (sigh)

@@ -72,2 +116,14 @@ var Promise = smash ? ParentPromise : PrFunPromise;

// ---------- then0 optimization -------
// Certain promise implementations (ie, babybird) provide an implementation
// of `then` which does not return a value. This can be much faster than
// the native `then`. Shim it if not provided natively.
if (!Promise.prototype.then0) {
Promise.prototype.then0 = function(f,r) { this.then(f, r); };
}
// Marker property, to indicate that we don't do anything unsafe
// in our constructor.
Promise.noSideEffects = true;
// ---------- collections --------------

@@ -89,3 +145,6 @@

// as an iterable
var args = Array.prototype.slice.call(arguments);
var args = new Array(arguments.length);
for (var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return P.all(args);

@@ -193,5 +252,4 @@ };

return P.reduce(this, callback);
} else {
return P.reduce(this, callback, arguments[1]);
}
return P.reduce(this, callback, arguments[1]);
};

@@ -206,8 +264,7 @@

});
} else {
var initialValue = P.resolve(arguments[2]);
return P.resolve(pArray).then(function(arr) {
return arrayReduce.call(arr, reducer(P, callback), initialValue);
});
}
var initialValue = P.resolve(arguments[2]);
return P.resolve(pArray).then(function(arr) {
return arrayReduce.call(arr, reducer(P, callback), initialValue);
});
};

@@ -220,5 +277,4 @@

return P.reduceRight(this, callback);
} else {
return P.reduceRight(this, callback, arguments[1]);
}
return P.reduceRight(this, callback, arguments[1]);
};

@@ -233,8 +289,7 @@

});
} else {
var initialValue = P.resolve(arguments[2]);
return P.resolve(pArray).then(function(arr) {
return arrayReduceRight.call(arr, reducer(P, callback), initialValue);
});
}
var initialValue = P.resolve(arguments[2]);
return P.resolve(pArray).then(function(arr) {
return arrayReduceRight.call(arr, reducer(P, callback), initialValue);
});
};

@@ -293,3 +348,6 @@

var P = this.constructor || Promise;
var pArgs = Array.prototype.slice.call(arguments, 1);
var pArgs = new Array(arguments.length - 1);
for (var i = 0; i < pArgs.length; ++i) {
pArgs[i] = arguments[i + 1];
}
return this.then(function(obj) {

@@ -329,3 +387,3 @@ return P.all(pArgs).then(function(args) {

}
this['catch'](function(e) {
this.then0(undefined, function(e) {
// Throw from new scope to ensure the exception will be unhandled

@@ -377,5 +435,5 @@ // (and thus reported).

return new P(function(resolve, reject) {
promise.then(resolve, reject);
promise.then0(resolve, reject);
var cleanup = makeRejector(reject, message, ms);
promise.then(cleanup, cleanup);
promise.then0(cleanup, cleanup);
});

@@ -391,3 +449,6 @@ };

// as an iterable.
var args = Array.prototype.slice.call(arguments);
var args = new Array(arguments.length);
for (var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return P.all(args).then(function(args) {

@@ -410,3 +471,6 @@ var fn = args[0];

if (arguments.length <= 1) { return promise['catch'](predicate); }
var predicates = Array.prototype.slice.call(arguments);
var predicates = new Array(arguments.length);
for (var i = 0; i < predicates.length; ++i) {
predicates[i] = arguments[i];
}
handler = predicates.pop();

@@ -419,10 +483,10 @@ predicates = predicates.map(function(v) {

return function(e) { return (e instanceof v); };
} else if (typeof v === 'function') {
}
if (typeof v === 'function') {
return function(e) { return !!v(e); };
} else {
return function(e) {
throw new TypeError('caught filter must inherit from Error ' +
'or be a simple predicate function');
};
}
return function(e) {
throw new TypeError('caught filter must inherit from Error ' +
'or be a simple predicate function');
};
});

@@ -452,8 +516,8 @@ return promise['catch'](function(e) {

return new P(function(resolve, reject) {
promise.then(function(value) {
promise.then0(function(value) {
var cb = function() { resolve(value); };
P.resolve().then(handler).then(cb, reject);
P.resolve().then(handler).then0(cb, reject);
}, function(reason) {
var cb = function() { reject(reason); };
P.resolve().then(handler).then(cb, reject);
P.resolve().then(handler).then0(cb, reject);
});

@@ -474,5 +538,17 @@ });

var self = this;
var args = [ fn, this ];
Array.prototype.push.apply(args, arguments);
return P['try'].apply(P, args);
var args = new Array(arguments.length);
for (var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return P.resolve(self).then(function(self) {
return P.all(args).then(function(args) {
return new P(function(resolve, reject) {
try {
resolve(fn.apply(self, args));
} catch (e) {
reject(e);
}
});
});
});
};

@@ -489,3 +565,3 @@ };

};
promise.then(function(v) {
promise.then0(function(v) {
try {

@@ -511,11 +587,39 @@ callback.call(this, null, v);

var hasThis = (arguments.length > 2);
return function() {
return function(a, b, c) {
var self = hasThis ? optThis : this;
var args = Array.prototype.slice.call(arguments);
var l = arguments.length;
if (l <= 3 && !names) {
// This section is a bit redundant, but it improves performance
// in the common case.
return new P(function(resolve, reject) {
var cb = function(e, v) {
if (e) {
reject(e);
} else {
resolve(v);
}
};
switch (l) {
case 0: { nodeFunction.call(self, cb); return; }
case 1: { nodeFunction.call(self, a, cb); return; }
case 2: { nodeFunction.call(self, a, b, cb); return; }
case 3: { nodeFunction.call(self, a, b, c, cb); return; }
default: { throw new Error('unreachable'); }
}
});
}
var args = new Array(l + 1);
for (var i = 0; i < l; ++i) {
args[i] = arguments[i];
}
return new P(function(resolve, reject) {
args.push(function(e, v) {
args[l] = function(e, v) {
if (e) {
reject(e);
} else if (names === true) {
resolve(Array.prototype.slice.call(arguments, 1));
var a = new Array(arguments.length - 1);
for (var j = 0; j < a.length; ++j) {
a[j] = arguments[j + 1];
}
resolve(a);
} else if (names) {

@@ -530,8 +634,4 @@ var value = {};

}
});
try {
nodeFunction.apply(self, args);
} catch (e) {
reject(e);
}
};
nodeFunction.apply(self, args);
});

@@ -565,3 +665,6 @@ };

self = this;
args = arguments;
args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}

@@ -638,5 +741,8 @@ return P.resolve(condition()).then(function(exit) {

})(BoundPromise.prototype.then);
BoundPromise.prototype.then0 = function(f,r) { this.then(f, r); };
// See discussion of PrFunPromise.resolve above:
BoundPromise.resolve = makeResolve(BoundPromise.resolve);
if (makeResolve) {
BoundPromise.resolve = makeResolve(BoundPromise.resolve);
}

@@ -647,28 +753,44 @@ return newThis ? BoundPromise.resolve(this) : SuperPromise.resolve(this);

// Generators.
// Implementation borrowed from Q.async()
Promise.async = function(makeGenerator) {
var P = this || Promise;
return function() {
var generator, callback, errback;
// When verb is "send", arg is a value
// When verb is "throw", arg is an exception
function continuer(verb, arg) {
var result;
var generator = makeGenerator.apply(this, arguments);
// Isolate try/catch to standalone functions, since v8
// will not optimize any method containing a `try` block.
var errObject = { e: null };
var tryCatchNext = function(arg) {
try {
result = generator[verb](arg);
} catch (exception) {
return P.reject(exception);
return generator.next(arg);
} catch (e) {
errObject.e = e;
return errObject;
}
// XXX: Possibly check for array-like (or iterable) value and
// use Promise.all() before returning/invoking callback?
if (result.done) {
return P.resolve(result.value);
} else {
return P.resolve(result.value).then(callback, errback);
};
var tryCatchThrow = function(arg) {
try {
return generator['throw'](arg);
} catch (e) {
errObject.e = e;
return errObject;
}
}
generator = makeGenerator.apply(this, arguments);
callback = continuer.bind(continuer, 'next');
errback = continuer.bind(continuer, 'throw');
return callback();
};
return new P(function(resolve, reject) {
var callback, errback;
var continuer = function(fn, arg) {
var result = fn(arg);
if (result === errObject) {
reject(result.e);
return;
}
if (result.done) {
resolve(result.value);
return;
}
// Using then0 here yields a significant performance improvement.
P.resolve(result.value).then0(callback, errback);
};
callback = function(arg) { return continuer(tryCatchNext, arg); };
errback = function(e) { return continuer(tryCatchThrow, e); };
callback();
});
};

@@ -675,0 +797,0 @@ };

{
"name": "prfun",
"version": "2.1.2",
"version": "2.1.3",
"description": "Helper functions for ES6 promises",
"main": "index.js",
"scripts": {
"lint": "jshint . && jscs .",
"jscs": "jscs .",
"jscs-fix": "jscs --fix .",
"lint": "jshint . && npm run jscs",
"lint-no-0.8": "node -e 'process.exit(/v0[.][0-8][.]/.test(process.version) ? 0 : 1)' || npm run lint",

@@ -30,3 +32,3 @@ "mocha": "if node -e 'process.exit(/v0[.]([0-9]|10)[.]/.test(process.version) ? 0 : 1)' ; then mocha ; else mocha --harmony ; fi",

"core-js": "~1.2.6",
"jscs": "~2.6.0",
"jscs": "~2.7.0",
"jshint": "~2.8.0",

@@ -33,0 +35,0 @@ "mocha": "~2.3.4"

@@ -102,2 +102,3 @@ # prfun

- [`Promise#tap`]
- [`Promise#then0`]
- [`Promise#throw`]

@@ -738,2 +739,19 @@ - [`Promise.defer`]

#### `Promise#then0([Function onFulfilled [, Function onRejected]])` → `undefined`
[`Promise#then0`]: #promisethen0function-onFulfilled--undefined
This is identical to `Promise#then` except that it does not return
a value. Some `Promise` implementations (for example, `babybird`)
export a `then0` implementation which is substantially faster than
calling `Promise#then`. If such an implementation is present, its
implementation will be used. Otherwise `prfun` will provide a
shim implementation that just calls `Promise#then` and discards
the result.
This allows you to use `then0` freely in your own code whenever
you don't care about the result, and `prfun` will use the most
efficient implementation available.
<hr>
#### `Promise#throw(Promise|dynamic reason)` → `Promise`

@@ -740,0 +758,0 @@ [`Promise#throw`]: #promisethrowpromisedynamic-reason--promise