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

native-promise-only

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

native-promise-only - npm Package Compare versions

Comparing version 0.0.0-a to 0.0.1-a

build.js

72

lib/npo.src.js

@@ -1,2 +0,5 @@

// Native Promise Only - (c) 2014 Kyle Simpson - MIT License
/*! Native Promise Only
v0.0.1-a (c) Kyle Simpson
MIT License: http://getify.mit-license.org
*/

@@ -76,20 +79,36 @@ (function UMD(name,context,definition){

function resolve(msg) {
if (this.state !== 0) {
var _then, self, obj;
if (this.def) {
if (this.triggered) {
return;
}
this.triggered = true;
self = this.def;
}
else {
self = this;
}
if (self.state !== 0) {
return;
}
var _then;
obj = {
def: self,
triggered: false
};
try {
if ((_then = isThenable(msg))) {
_then.call(msg,resolve.bind(this),reject.bind(this));
_then.call(msg,resolve.bind(obj),reject.bind(obj));
}
else {
this.msg = msg;
this.state = 1;
schedule(notify.bind(this));
self.msg = msg;
self.state = 1;
schedule(notify.bind(self));
}
}
catch (err) {
reject.call(this,err);
reject.call(obj,err);
}

@@ -108,23 +127,22 @@ }

function reject(msg) {
if (this.state !== 0) {
return;
}
var self;
var _then;
try {
if ((_then = isThenable(msg))) {
_then.call(msg,resolve.bind(this),reject.bind(this));
if (this.def) {
if (this.triggered) {
return;
}
else {
this.msg = msg;
this.state = 2;
schedule(notify.bind(this));
}
this.triggered = true;
self = this.def;
}
catch (err) {
this.msg = err;
this.state = 2;
schedule(notify.bind(this));
else {
self = this;
}
if (self.state !== 0) {
return;
}
self.msg = msg;
self.state = 2;
schedule(notify.bind(self));
}

@@ -142,4 +160,4 @@

function then(success,failure) {
this.success.push(isFunction(success) ? success : function(m){ return m; });
this.failure.push(isFunction(failure) ? failure : function(m){ throw m; });
this.success.push(isFunction(success) ? success : function __default_success__(m){ return m; });
this.failure.push(isFunction(failure) ? failure : function __default_failure__(m){ throw m; });

@@ -146,0 +164,0 @@ var p = new Promise(function __Promise__(resolve,reject){

{
"name": "native-promise-only",
"version": "0.0.0-a",
"version": "0.0.1-a",
"description": "Native Promise Only: A polyfill for native ES6 Promises **only**, nothing else.",
"main": "./lib/npo.src.js",
"main": "./npo.js",
"scripts": {
"test": "promises-aplus-tests test_adapter.js"
"test": "promises-aplus-tests test_adapter.js",
"build": "./build.js"
},
"devDependencies": {
"promises-aplus-tests": "*"
"promises-aplus-tests": "*",
"uglify-js": "~2.4.8"
},

@@ -12,0 +14,0 @@ "repository": {

# Native Promise Only (NPO)
A polyfill for native ES6 Promises that deviates as little as possible from the strict spec definition (no add-ons).
A polyfill for native ES6 Promises that as close as possible (no extensions) to the strict spec definitions.
## Intent
The aim of this project is to be the smallest (and maybe the fastest!?) polyfill for Promises, staying as close as possible to what's specified in both [Promises/A+](http://promisesaplus.com) and the upcoming ES6 specification (**link needed**).
An equally important goal is to avoid exposing any capability for promise-state to be mutated externally. The next section explains the trade-offs of that balance.
## Known Limitations
A promise object **will be** an instance of the `Promise` object:
On the bright side, a promise object from this polyfill **will be** an instance of the `Promise` constructor, which makes identification of genuine promises easier:

@@ -15,3 +21,3 @@ ```js

However, these promise instances don't inherit (delegate to) a meaningful `Promise.prototype` object. That is:
However, these promise instances don't inherit (delegate to) a *meaningful* `Promise.prototype` object for their methods. That is:

@@ -25,21 +31,88 @@ ```js

As such, these promises are not really "sub-classable" in the ES6 `class` / `extends` sense, though theoretically you should be able to do that in ES6.
As such, these promises are not really "sub-classable" in the ES6 `class` / `extends` sense, though theoretically you should be able to do that in ES6 with the built-in Promises.
The reason for this deviation is that there's a choice between having delegated methods on the `.prototype` or having private state. Since **the spirit of promises was always to ensure trustability** -- that they were immutable to everyone except the initial resolver/deferred -- private state is a critically important feature to preserve.
The reason for this deviation is that there's a choice between having delegated methods on the `.prototype` or having private state. Since **the spirit of promises was always to ensure trustability** -- that promises were immutable (from the outside) to everyone except the initial resolver/deferred -- private state is a critically important feature to preserve.
Many other ES6 promise shims/libs seem to have forgotten that important point, as many of them either expose the state publicly on the object instance or provide public accessor methods which can externally mutate a promise's state. Both of these deviations are intolerable in my opinion, so this library chose the opposite trade-off: loss of ES6 sub-classing.
Many other ES6 promise shims/libs seem to have forgotten that important point, as many of them either expose the state publicly on the object instance or provide public accessor methods which can externally mutate a promise's state. Both of these deviations are **intolerable** in my opinion, so this library chose the opposite trade-off: *no ES6 sub-classing*.
## Test Compliance
Any trade-off is a shame, but this one is the least of a few evils, and probably won't prove to limit very many, as there are only a limited number of use-cases for `extend`ing `Promise` in the ES6 sub-class sense.
This polyfill/shim is aiming to be "spec compliant" in the sense of passing all tests in the [Promises/A+ Test Suite](https://github.com/promises-aplus/promises-tests).
## ES5 Assumption
Test status at present:
This polyfill assumes various ES5 capabilities, such as `Function#bind` and `Array#forEach`. If you need to use this polyfill in older JS environments, make sure to provide polyfills/shims [such as these](https://github.com/es-shims/es5-shim).
*Native Promise Only* needs (all of which have compliant ES5 shims):
* `Array.isArray`
* `Array#forEach`
* `Array#some`
* `Function#bind`
## Usage
To use this polyfill in the browser, include the "npo.js" file with your site's scripts. It's a polyfill, which means it will not overwrite `Promise` if it exists as a global already, so it's safe to include unconditionally.
To use with AMD, import the "npo.js" file module.
To use the polyfill in node, run:
```
824 passing
48 failing
npm install native-promise-only
```
Then require the module into your node code like this:
```
var Promise = require("native-promise-only");
```
Other than the above "Known Limitations" discussion and some browser bugs (such as [these](https://gist.github.com/getify/bd11ccf1eff2efdac0fb)) which **this polyfill doesn't have**, your promises should operate the same in all JS environments.
Exactly like native promises, here's a quick example of how you create and use the polyfilled promises:
```js
var p = new Promise(function(resolve,reject){
setTimeout(function(){
resolve("Yay!");
},100);
});
p.then(function(msg){
console.log(msg); // Yay!
});
```
For more on how to use and enjoy native (or polyfilled!) promises, check out [JavaScript Promises](http://www.html5rocks.com/en/tutorials/es6/promises/) by [Jake Archibald](http://twitter.com/jaffathecake).
## Still Want More?
This project intentionally adheres pretty strictly to the narrow core of [Promises/A+](http://promisesaplus.com) as adopted/implemented by ES6 into the native `Promise()` mechanism.
But it's quite likely that you will experience a variety of scenarios in which using *only* native promises might be tedious, limiting, or more trouble than it's worth. There's good reason why most other **Promises/A+** "compliant" libs are actually superset extensions on the narrow core: **because async flow-control is often quite complex in the real world.**
*Native Promise Only* will not add any of these extra flourishes. Sorry.
**However, I have another project**: [asynquence](http://github.com/getify/asynquence) (async + sequence). It's an abstraction on top of the promises concept (promises are hidden inside), designed to drastically improve the readability and expressiveness of your async flow-control code.
You simply express your async flow-control and *asynquence* creates and chains all the promises for you underneath. **Super simple.**
*asynquence* has a custom implementation for the hidden "promises" it uses, and as such does not need native `Promises`, nor does it need/include this polyfill.
Get your feet wet with native promises first, but then when you go looking for something more, consider [asynquence](http://github.com/getify/asynquence) (which is vastly more powerful and is still only 2k!).
## Tests/Compliance
<a href="http://promisesaplus.com/" float="right">
<img src="http://promisesaplus.com/assets/logo-small.png" alt="Promises/A+ logo"
title="Promises/A+ 1.1 compliant" align="right" />
</a>
*Native Promise Only* is "spec compliant" in the sense of passing all tests in the [Promises/A+ Test Suite](https://github.com/promises-aplus/promises-tests).
To run the test suite after cloning this repo, run `npm install` to install the dev-dependencies, then run `npm test`.
However, there are definitely other tests that need to be added, for example testing the `Promise()` constructor's behavior, as well as the `Promise.*` static helpers (`resolve(..)`, `reject(..)`, `all(..)`, and `race(..)`), none of which are covered by Promises/A+ test suite.
Developing a more comprehensive test-suite to augment the Promises/A+ test suite **is now another primary goal** of this project.
## License

@@ -46,0 +119,0 @@

// Adapter for "promises-aplus-tests" test runner
var Promise = require(__dirname + "/lib/npo.src.js");
var path = require("path");
var Promise = require(path.join(__dirname,"/npo.js"));

@@ -5,0 +6,0 @@ module.exports.deferred = function __deferred__() {

@@ -17,104 +17,137 @@ var Promise = require("./lib/npo.src.js");

delay("Hello World")
.then(function(msg){
console.log(msg);
return msg;
})
.then(function(msg){
return delay(msg.toUpperCase());
})
.then(function(msg){
console.log(msg);
});
// delay("Hello World")
// .then(function(msg){
// console.log(msg);
// return msg;
// })
// .then(function(msg){
// return delay(msg.toUpperCase());
// })
// .then(function(msg){
// console.log(msg);
// });
Promise.race([
delay("Hello"),
delay("World")
])
.then(function(msgs){
console.log(msgs);
});
// Promise.race([
// delay("Hello"),
// delay("World")
// ])
// .then(function(msgs){
// console.log(msgs);
// });
var x = Promise.resolve(2);
// var x = Promise.resolve(2);
var p = x.then(function(){
return 5;
});
// var p = x.then(function(){
// return 5;
// });
var p2 = x.then(function(){
return p2;
});
// var p2 = x.then(function(){
// return p2;
// });
p.then(function(msg){
console.log("p:" + msg);
},
function(err){
console.log("p-err:" + err);
});
// p.then(function(msg){
// console.log("p:" + msg);
// },
// function(err){
// console.log("p-err:" + err);
// });
p2.then(function(msg){
console.log("p2:" + msg);
},
function(err){
console.log("p2-err:" + err);
});
// p2.then(function(msg){
// console.log("p2:" + msg);
// },
// function(err){
// console.log("p2-err:" + err);
// });
Promise.reject(42).then(null,null).then(null,function(reason){
console.log("reason:" + reason);
}); // reason:42
// Promise.reject(42).then(null,null).then(null,function(reason){
// console.log("reason:" + reason);
// }); // reason:42
Promise.reject(42).then(5,null).then(null,function(reason){
console.log("reason:" + reason);
}); // reason:42
// Promise.reject(42).then(5,null).then(null,function(reason){
// console.log("reason:" + reason);
// }); // reason:42
Promise.reject(42).then(null,5).then(null,function(reason){
console.log("reason:" + reason);
}); // TypeError: number is not a function
// Promise.reject(42).then(null,5).then(null,function(reason){
// console.log("reason:" + reason);
// }); // TypeError: number is not a function
// *************
// // *************
Promise.resolve(42).then(null,null).then(function(msg){
console.log("msg:" + msg);
},null); // msg:42
// Promise.resolve(42).then(null,null).then(function(msg){
// console.log("msg:" + msg);
// },null); // msg:42
Promise.resolve(42).then(null,5).then(function(msg){
console.log("msg:" + msg);
},null); // msg:42
// Promise.resolve(42).then(null,5).then(function(msg){
// console.log("msg:" + msg);
// },null); // msg:42
Promise.resolve(42).then(5,null).then(function(msg){
console.log("msg:" + msg);
},null); // (nothing printed)
// Promise.resolve(42).then(5,null).then(function(msg){
// console.log("msg:" + msg);
// },null); // (nothing printed)
var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it
var sentinel = { sentinel: "sentinel" }; // a sentinel fulfillment value to test for with strict equality
// var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it
// var sentinel = { sentinel: "sentinel" }; // a sentinel fulfillment value to test for with strict equality
function thenable(value) {
return {
then: function (onFulfilled) {
onFulfilled(value);
}
};
}
// function thenable(value) {
// return {
// then: function (onFulfilled) {
// onFulfilled(value);
// }
// };
// }
function yFactory() {
return thenable(sentinel);
}
// function yFactory() {
// return thenable(sentinel);
// }
function xFactory() {
return {
then: function (resolvePromise) {
resolvePromise(yFactory());
}
};
}
// function xFactory() {
// return {
// then: function (resolvePromise) {
// resolvePromise(yFactory());
// }
// };
// }
var promise = Promise.resolve(dummy).then(function() {
return xFactory();
});
// var promise = Promise.resolve(dummy).then(function() {
// return xFactory();
// });
promise.then(function onPromiseFulfilled(value) {
console.log(value === sentinel);
});
// promise.then(function onPromiseFulfilled(value) {
// console.log(value === sentinel);
// });
//var p1 = new Promise(function(resolve,reject){
// setTimeout(reject,1000,"reject-p1");
//});
var inner = {
then: function(s,f) {
console.log("inner.then");
setTimeout(s,500,"inner.then");
}
};
var outer = {
then: function(s,f) {
console.log("outer.then");
console.log("first call to s()");
s(inner);
console.log("now throwing");
throw "booyah";
}
};
var p2 = Promise.resolve(outer)
.then(
function(msg){
console.log("msg:" + msg);
},
function(reason){
console.log("err:" + reason);
}
);

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