Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
Conflicts:
	when.js
  • Loading branch information
gamtiq committed Aug 7, 2013
2 parents 50b9f29 + 875fc08 commit b41173a
Show file tree
Hide file tree
Showing 61 changed files with 3,056 additions and 593 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
.npmignore
.idea/
experiments/
node_modules/
Expand Down
1 change: 1 addition & 0 deletions .jshintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules/
.git/
.idea/
experiments/
test/monitor
1 change: 1 addition & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"nonew": true,
"quotmark": "single",
"strict": false,
"sub": true,
"trailing": true,
"undef": true,
"unused": true,
Expand Down
13 changes: 13 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.idea/
.idea/.name
.gitignore/
test/
projectFilesBackup/
experiments/
docs
jsdoc
jsdoc3
.npmignore
.gitmodules
.travis.yml
*.globalized.js
30 changes: 30 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
### 2.2.1

* Fix for `when.defer().reject()` bypassing the unhandled rejection monitor. (#166)
* Fix for `when/function`, `when/callbacks`, and `when/node/function` not preserving `thisArg`. (#162)
* Doc clarifications for [`promise.yield`](docs/api.md#yield). (#164)

### 2.2.0

* New experimental [promise monitoring and debugging](docs.md#debugging-promises) via `when/monitor/console`.
* New [`when.promise(resolver)`](docs/api.md#whenpromise) promise creation API. A lighter alternative to the heavier `when.defer()`
* New `bindCallback` and `liftCallback` in `when/node/function` for more integration options with node-style callbacks.

### 2.1.1

* Quote internal usages of `promise.yield` to workaround .NET minifier tools that don't yet understand ES5 identifier-as-property rules. See [#157](https://github.com/cujojs/when/issues/157)

### 2.1.0

* New [`when.settle`](docs/api.md#whensettle) that settles an array of promises, regardless of whether the fulfill or reject.
* New [`when/guard`](docs/api.md#whenguard) generalized concurrency guarding and limiting
* New [`promise.inspect`](docs/api.md#inspect) for synchronously getting a snapshot of a promise's state at a particular instant.
* Significant performance improvements when resolving promises with non-primitives (Arrays, Objects, etc.)
* Experimental [vert.x](http://vertx.io) support
* **DEPRECATED**: `onFulfilled`, `onRejected`, `onProgress` handler arguments to `when.all`, `when.any`, `when.some`. Use the returned promise's `then()` (or `otherwise()`, `ensure()`, etc) to register handlers instead.
* For example, do this: `when.all(array).then(onFulfilled, onRejected)` instead of this: `when.all(array, onFulfilled, onRejected)`. The functionality is equivalent.

### 2.0.1

* Account for the fact that Mocha creates a global named `process`. Thanks [Narsul](https://github.com/cujojs/when/pull/136)

### 2.0.0

* Fully asynchronous resolutions.
Expand Down
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,43 @@

# when.js

When.js is cujojs's lightweight [Promises/A+](http://promises-aplus.github.com/promises-spec) and `when()` implementation that powers the async core of [wire.js](https://github.com/cujojs/wire), cujojs's IOC Container. It features:
When.js is cujoJS's lightweight [Promises/A+](http://promises-aplus.github.com/promises-spec) and `when()` implementation that powers the async core of [wire.js](https://github.com/cujojs/wire), cujoJS's IOC Container. It features:

* A rock solid, battle-tested Promise implementation
* Resolving, mapping, and reducing arrays of promises
* Resolving, settling, mapping, and reducing arrays of promises
* Executing tasks in parallel and sequence
* Transforming Node-style and other callback-based APIs into promise-based APIs

It passes the [Promises/A+ Test Suite](https://github.com/promises-aplus/promises-tests), is [very fast](https://github.com/cujojs/promise-perf-tests#test-results), is under 1.5k when compiled with Google Closure + gzip, and has no external dependencies.

# What's New?

### 2.2.1

* Fix for `when.defer().reject()` bypassing the unhandled rejection monitor. (#166)
* Fix for `when/function`, `when/callbacks`, and `when/node/function` not preserving `thisArg`. (#162)
* Doc clarifications for [`promise.yield`](docs/api.md#yield). (#164)

### 2.2.0

* New experimental [promise monitoring and debugging](docs/api.md#debugging-promises) via `when/monitor/console`.
* New [`when.promise(resolver)`](docs/api.md#whenpromise) promise creation API. A lighter alternative to the heavier `when.defer()`
* New `bindCallback` and `liftCallback` in `when/node/function` for more integration options with node-style callbacks.

### 2.1.1

* Quote internal usages of `promise.yield` to workaround .NET minifier tools that don't yet understand ES5 identifier-as-property rules. See [#157](https://github.com/cujojs/when/issues/157)

### 2.1.0

* New [`when.settle`](docs/api.md#whensettle) that settles an array of promises
* New [`when/guard`](docs/api.md#whenguard) generalized concurrency guarding and limiting
* New [`promise.inspect`](docs/api.md#inspect) for synchronously getting a snapshot of a promise's state at a particular instant.
* Significant performance improvements when resolving promises with non-primitives (e.g. with Arrays, Objects, etc.)
* Experimental [vert.x](http://vertx.io) support
* **DEPRECATED**: `onFulfilled`, `onRejected`, `onProgress` handler arguments to `when.all`, `when.any`, `when.some`. Use the returned promise's `then()` (or `otherwise()`, `ensure()`, etc) to register handlers instead.
* For example, do this: `when.all(array).then(onFulfilled, onRejected)` instead of this: `when.all(array, onFulfilled, onRejected)`. The functionality is equivalent.

### 2.0.1

* Account for the fact that Mocha creates a global named `process`. Thanks [Narsul](https://github.com/cujojs/when/pull/136)
Expand Down
23 changes: 23 additions & 0 deletions benchmark/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!doctype html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="../node_modules/curl/src/curl.js"></script>
<script type="text/javascript">
curl.config({
packages: {
when: { location: '..', main: 'when' },
benchmark: {
location: '../node_modules/benchmark', main: 'benchmark'
}
}
});

curl(['./promise.js']);
</script>
</head>
<body>

</body>
</html>
54 changes: 54 additions & 0 deletions benchmark/map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/** @license MIT License (c) copyright 2010-2013 original author or authors */

/**
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
* @author: Brian Cavalier
* @author: John Hann
*/

(function(define) { 'use strict';
define(function(require) {

var when, tests, run;

when = require('../when');
run = require('./run');

tests = [
{ name: 'map 100', fn: map(100), defer: true },
{ name: 'map 1k', fn: map(1e3), defer: true }
];

run(tests);

//
// Benchmark tests
//

function map(n) {
return function(deferred) {

var input = [];
for(var i = 0; i < n; i++) {
input.push(when(i));
}

when.map(input, addOne).then(function() {
deferred.resolve();
});

};
}

//
// Promise helpers
//

function addOne(x) {
return x + 1;
}

});
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
180 changes: 180 additions & 0 deletions benchmark/promise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/** @license MIT License (c) copyright 2010-2013 original author or authors */

/**
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
* @author: Brian Cavalier
* @author: John Hann
*/

(function(define) { 'use strict';
define(function(require) {
/*global setImmediate,process*/

var when, tests, run, ok;

when = require('../when');
run = require('./run');
ok = 0;

tests = [
{ name: 'create pending', fn: createPending },
{ name: 'resolve promise', fn: resolvePromise, defer: true },
{ name: 'setImmediate', fn: viaSetImmediate, defer: true,
condition: checkSetImmediate },
{ name: 'process.nextTick', fn: viaProcessNextTick, defer: true,
condition: checkProcessNextTick },
{ name: 'setTimeout', fn: viaSetTimeout, defer: true },
{ name: 'reject promise', fn: rejectPromise, defer: true },
{ name: 'reject then resolve', fn: rejectThenResolve, defer: true },
{ name: 'resolve chain 100', fn: resolveChain(100), defer: true },
{ name: 'resolve chain 1k', fn: resolveChain(1e3), defer: true },
{ name: 'sparse resolve chain 1k', fn: resolveChainSparse(1e3), defer: true },
{ name: 'reject chain 100', fn: rejectChain(100), defer: true },
{ name: 'reject chain 1k', fn: rejectChain(1e3), defer: true },
{ name: 'sparse reject chain 1k', fn: rejectChainSparse(1e3), defer: true },
// These 10k tests seem to cause significant garbage collection
// hits that skew results of other tests. So, they are disabled
// for now, but we need to figure out how to reduce the memory
// thrashing these cause.
// Leaving one enabled for now.
{ name: 'resolve chain 10k', fn: resolveChain(1e4), defer: true }
// { name: 'sparse resolve chain 10k', fn: resolveChainSparse(1e4), defer: true },
// { name: 'reject chain 10k', fn: rejectChain(1e4), defer: true },
// { name: 'sparse reject chain 10k', fn: rejectChainSparse(1e4), defer: true }
];

run(tests);

//
// Benchmark tests
//

function createPending() {
when.promise(pendingForever);
}

function resolvePromise(deferred) {
when.promise(resolve).then(function() {
deferred.resolve();
});
}

function rejectPromise(deferred) {
when.promise(reject).then(null, function() {
deferred.resolve();
});
}

function rejectThenResolve(deferred) {
when.promise(reject).then(null, identity).then(function() {
deferred.resolve();
});
}

function viaSetTimeout(deferred) {
setTimeout(function() {
deferred.resolve();
}, 0);
}

function viaSetImmediate(deferred) {
setImmediate(function() {
deferred.resolve();
});
}

function viaProcessNextTick(deferred) {
process.nextTick(function() {
deferred.resolve();
});
}

function resolveChain(n) {
return function(deferred) {
var p = when.resolve({}), i = 0;
for(;i < n; i++) {
p = p.then(identity);
}

p.then(function() {
deferred.resolve();
});
};
}

function resolveChainSparse(n) {
return function(deferred) {
var p = when.resolve({}), i = 1;
for(;i < n; i++) {
p = p.then(null);
}

p.then(identity).then(function() {
deferred.resolve();
});
};
}

function rejectChain(n) {
return function(deferred) {
var p = when.reject({}), i = 0;
for(;i < n; i++) {
p = p.then(null, rethrow);
}

p.then(null, function() {
deferred.resolve();
});
};
}

function rejectChainSparse(n) {
return function(deferred) {
var p = when.reject({}), i = 1;
for(;i < n; i++) {
p = p.then(null, rethrow);
}

p.then(null, identity).then(function() {
deferred.resolve();
});
};
}

//
// Promise helpers
//

function pendingForever() {}

function resolve(r) {
r();
}

function reject(_, r) {
r();
}

function identity(x) {
return x;
}

function rethrow(e) {
throw e;
}

function checkSetImmediate() {
return typeof setImmediate === 'function'
? ok : 'setImmediate() not available';
}

function checkProcessNextTick() {
return typeof process !== 'undefined'
&& typeof process.nextTick === 'function'
? ok : 'process.nextTick() not available';
}

});
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
Loading

0 comments on commit b41173a

Please sign in to comment.