Skip to content

Commit

Permalink
Add jshint to package.json, update settings
Browse files Browse the repository at this point in the history
  • Loading branch information
briancavalier committed Apr 1, 2013
1 parent 7b71dbc commit 28afeee
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 33 deletions.
1 change: 1 addition & 0 deletions .jshintignore
@@ -0,0 +1 @@
node_modules/
7 changes: 3 additions & 4 deletions .jshintrc
Expand Up @@ -3,10 +3,9 @@
"node": true,
"es5": true,

"predef": [
"define",
"setImmediate"
],
"globals": {
"define": true
},

"boss": true,
"curly": true,
Expand Down
7 changes: 4 additions & 3 deletions README.md
@@ -1,8 +1,8 @@
# avow

Avow is a very tiny, very fast, fully asynchronous [Promises/A+](https://github.com/promises-aplus/promises-spec) implementation, and passes the [Promises/A+ Test Suite](https://github.com/promises-aplus/promises-tests). It tracks Promises/A+ and is currently forward compatible to the upcoming revision Promises/A+ (likely to be versioned 1.1.0).
Avow is a very tiny, very fast, fully asynchronous [Promises/A+](https://github.com/promises-aplus/promises-spec) implementation, and passes the [Promises/A+ Test Suite](https://github.com/promises-aplus/promises-tests). It tracks Promises/A+ and is currently *forward compatible* to the upcoming revision Promises/A+ (likely to be versioned 1.1.0).

It is less than 150 lines of code (sans comments and UMD boilerplate), less than 500 *bytes* when closured+gzipped, and in *very limited testing* appears to be as fast as or faster than most other synchronous implementations in environments where a fast `nextTick` is available. It uses `process.nextTick` or `setImmediate` if available (you can use [NobleJS's setImmediate polyfill](https://github.com/NobleJS/setImmediate)), and will fall back to `setTimeout` (srsly, use the polyfill) otherwise.
It is around 150 lines of code (sans comments and UMD boilerplate), less than 600 *bytes* when closured+gzipped, and in *very limited testing* appears to be as fast as or faster than most other synchronous implementations in environments where a fast `nextTick` is available. It uses `process.nextTick` or `setImmediate` if available (you can use [NobleJS's setImmediate polyfill](https://github.com/NobleJS/setImmediate)), and will fall back to `setTimeout` (srsly, use the polyfill) otherwise.

## Why?

Expand Down Expand Up @@ -64,6 +64,7 @@ Where `options` is an object that can have any of the following properties:

* `nextTick` - specify your own nextTick function
* `unhandled` - callback to be notified when an unhandled rejection reaches the end of a promise chain.
* `handled` - callback to be notified if, at some point, a previously unhandled rejected promise become handled. Since promises are temporal, this can happen if a consumer adds a rejection handler using `then()` at some point after the promise has been rejected.
* `protect` - function that is called on every promise avow creates, to give you a chance to protect it, e.g. by supplying Object.freeze() here.

## Running the Promises/A+ Test Suite
Expand All @@ -73,4 +74,4 @@ Where `options` is an object that can have any of the following properties:

## License

MIT License, Copyright (c) 2012 Brian Cavalier
MIT License, Copyright (c) 2012-2013 Brian Cavalier
57 changes: 33 additions & 24 deletions avow.js
@@ -1,4 +1,4 @@
/* Copyright (c) 2012 Brian Cavalier */
/* Copyright (c) 2012-2013 Brian Cavalier */
(function(define) {
define(function() {

Expand All @@ -10,22 +10,22 @@ define(function() {
// Use process.nextTick or setImmediate if available, fallback to setTimeout
nextTick = (function () {
var globalSetTimeout = setTimeout;
/*global setImmediate:true */
/*global window,setImmediate,process*/
return typeof setImmediate === 'function'
? typeof window === 'undefined'
? setImmediate
: setImmediate.bind(window)
? setImmediate
: setImmediate.bind(window)
: typeof process === 'object'
? process.nextTick
: function(task) { globalSetTimeout(task, 0); };
? process.nextTick
: function(task) { globalSetTimeout(task, 0); };
}());

// Default configuration
defaultConfig = {
nextTick: nextTick,
unhandled: noop,
handled: noop,
protect: noop,
nextTick: nextTick
handled: noop,
protect: noop
};

// Create the default module instance
Expand All @@ -50,19 +50,19 @@ define(function() {
protect = config.protect || defaultConfig.protect;

// Add resolve and reject methods.
avow.from = from;
avow.reject = reject;
promise.from = from;
promise.reject = reject;

return avow;
return promise;

// Trusted promise constructor
function Promise(then) {
this.then = then;
protect(this);
}

// Return a promise whose fate is determined by resolver
function avow(resolver) {
// Return a pending promise whose fate is determined by resolver
function promise(resolver) {
var value, handlers = [];

// Call the resolver to seal the promise's fate
Expand All @@ -75,30 +75,32 @@ define(function() {
// Return the promise
return new Promise(then);

function then(onFulfilled, onRejected, onProgress) {
return avow(function(resolve, reject, notify) {
// Register handlers with this promise
function then(onFulfilled, onRejected) {
return promise(function(resolve, reject) {
handlers
// Call handlers later, after resolution
? handlers.push(function(value) {
value.then(onFulfilled, onRejected, onProgress)
.then(resolve, reject, notify);
})
value.then(onFulfilled, onRejected).then(resolve, reject);
})
// Call handlers soon, but not in the current stack
: nextTick(function() {
value.then(onFulfilled, onRejected, onProgress)
.then(resolve, reject, notify);
});
value.then(onFulfilled, onRejected).then(resolve, reject);
});
});
}

// Resolve with a value, promise, or thenable
function promiseResolve(value) {
resolve(from(value));
}

// Reject with reason verbatim
function promiseReject(reason) {
resolve(reject(reason));
}

// For all handlers, run the Promise Resolution Procedure on this promise
function resolve(x) {
if(!handlers) {
return;
Expand All @@ -119,14 +121,19 @@ define(function() {
}
}

// Return a trusted promise for x, where
// - if x is a Promise, return it
// - if x is a value, return a promise that will eventually fulfill with x
// - if x is a thenable, assimilate it and return a promise whose fate
// follows that of x.
function from(x) {
if(x instanceof Promise) {
return x;
} else if (x !== Object(x)) {
return fulfilled(x);
}

return avow(function(resolve, reject) {
return promise(function(resolve, reject) {
nextTick(function() {
try {
// We must check and assimilate in the same tick, but not the
Expand All @@ -151,7 +158,7 @@ define(function() {
// Return a rejected promise
function reject(reason) {
return new Promise(function (_, onRejected) {
return avow(function(resolve, reject) {
return promise(function(resolve, reject) {
if(typeof onRejected == 'function') {
resolve(onRejected(reason));
} else {
Expand All @@ -161,6 +168,8 @@ define(function() {
});
}

// private
// create an already-fulfilled promise used to break assimilation recursion
function fulfilled(value) {
var self = new Promise(function (onFulfilled) {
try {
Expand Down
5 changes: 3 additions & 2 deletions package.json
Expand Up @@ -5,9 +5,10 @@
"keywords": ["promise", "promises", "async", "asynchronous", "deferred"],
"main": "avow",
"devDependencies": {
"promises-aplus-tests": ""
"promises-aplus-tests": "",
"jshint": "~1"
},
"scripts": {
"test": "promises-aplus-tests test/avow-adapter.js"
"test": "jshint . && promises-aplus-tests test/avow-adapter.js"
}
}

0 comments on commit 28afeee

Please sign in to comment.