Comparing version 0.10.5-0 to 0.10.6-0
@@ -67,4 +67,2 @@ "use strict"; | ||
"cancel.js": ['Promise'], | ||
"simple_thenables.js": ['Promise'], | ||
"complex_thenables.js": ['Promise'], | ||
"synchronous_inspection.js": ['Promise'] | ||
@@ -89,4 +87,2 @@ | ||
"cancel.js": true, | ||
"simple_thenables.js": true, | ||
"complex_thenables.js": true, | ||
"synchronous_inspection.js": true | ||
@@ -268,4 +264,3 @@ | ||
"./src/synchronous_inspection.js", | ||
"./src/simple_thenables.js", | ||
"./src/complex_thenables.js", | ||
"./src/thenables.js", | ||
"./src/progress.js", | ||
@@ -507,2 +502,3 @@ "./src/cancel.js", | ||
"./src/bluebird.js", | ||
"./src/thenables.js", | ||
"./src/assert.js", | ||
@@ -530,24 +526,3 @@ "./src/global.js", | ||
var mutExPaths = [ | ||
{ | ||
feature: "simple_thenables", | ||
featureDisabled: "./src/complex_thenables.js", | ||
featureEnabled: "./src/simple_thenables.js" | ||
} | ||
]; | ||
function applyMutExPaths( paths, features ) { | ||
if( !Array.isArray( features ) ) { | ||
features = features.toLowerCase().split( /\s+/g ); | ||
} | ||
mutExPaths.forEach(function( mutExPath ){ | ||
if( features.indexOf( mutExPath.feature ) > -1 ) { | ||
paths.push( mutExPath.featureEnabled ); | ||
} | ||
else { | ||
paths.push( mutExPath.featureDisabled ); | ||
} | ||
}); | ||
return paths; | ||
} | ||
@@ -558,3 +533,3 @@ function build( paths, isCI ) { | ||
if( !paths ) { | ||
paths = applyMutExPaths( optionalPaths.concat(mandatoryPaths), [] ); | ||
paths = optionalPaths.concat(mandatoryPaths); | ||
} | ||
@@ -701,3 +676,2 @@ var optionalRequireCode = getOptionalRequireCode(paths.map(function(v) { | ||
paths = getOptionalPathsFromOption( features ).concat( mandatoryPaths ); | ||
applyMutExPaths( paths, features ); | ||
} | ||
@@ -704,0 +678,0 @@ |
@@ -25,5 +25,3 @@ /** | ||
var ASSERT = require("./assert.js"); | ||
var async = require( "./async.js" ); | ||
var util = require( "./util.js" ); | ||
var isPrimitive = util.isPrimitive; | ||
var errorObj = util.errorObj; | ||
@@ -43,21 +41,2 @@ var isObject = util.isObject; | ||
function isThenable(obj, ref) { | ||
if (isPrimitive(obj)) { | ||
return false; | ||
} | ||
var then = getThen(obj); | ||
if (then === errorObj) { | ||
ref.ref = errorObj; | ||
return false; | ||
} | ||
if (typeof then === "function") { | ||
ref.ref = then; | ||
return true; | ||
} | ||
return false; | ||
} | ||
var ref = {ref: null}; | ||
function Promise$_Cast( obj, caller ) { | ||
@@ -68,14 +47,10 @@ if( isObject( obj ) ) { | ||
} | ||
if( isThenable( obj, ref ) ) { | ||
var then = getThen(obj); | ||
if (then === errorObj) { | ||
return Promise.reject(then.e); | ||
} | ||
else if (typeof then === "function") { | ||
caller = typeof caller === "function" ? caller : Promise$_Cast; | ||
var then = ref.ref; | ||
ref.ref = null; | ||
return doThenable( obj, then, caller ); | ||
return doThenable(obj, then, caller); | ||
} | ||
else if (ref.ref === errorObj) { | ||
ref.ref = null; | ||
return Promise.reject(errorObj.e); | ||
} | ||
ref.ref = null; | ||
} | ||
@@ -85,5 +60,2 @@ return obj; | ||
Promise._cast = Promise$_Cast; | ||
Promise._isThenable = isThenable; | ||
function doThenable( x, then, caller ) { | ||
@@ -108,3 +80,3 @@ function resolveFromThenable( a ) { | ||
resolver, | ||
void 0, | ||
null, | ||
resolveFromThenable | ||
@@ -123,3 +95,3 @@ ); | ||
var resolver = Promise.defer( caller ); | ||
var resolver = Promise.defer(caller); | ||
@@ -134,86 +106,3 @@ var called = false; | ||
Promise.prototype._resolveThenable = | ||
function Promise$_resolveThenable(x, then) { | ||
var localP = this; | ||
var key = {}; | ||
var called = false; | ||
function resolveFromThenable( v ) { | ||
if( called && this !== key ) return; | ||
called = true; | ||
var fn = localP._fulfill; | ||
var b = Promise$_Cast( v ); | ||
if( b !== v || | ||
( b instanceof Promise && b.isPending() ) ) { | ||
if( v === x ) { | ||
async.invoke( fn, localP, v ); | ||
} | ||
else { | ||
b._then( resolveFromThenable, rejectFromThenable, void 0, | ||
key, void 0, resolveFromThenable); | ||
} | ||
return; | ||
} | ||
if( b instanceof Promise ) { | ||
var fn = b.isFulfilled() | ||
? localP._fulfill : localP._reject; | ||
v = v._resolvedValue; | ||
b = Promise$_Cast( v ); | ||
if( b !== v || | ||
( b instanceof Promise && b !== v ) ) { | ||
b._then(resolveFromThenable, rejectFromThenable, void 0, | ||
key, void 0, resolveFromThenable); | ||
return; | ||
} | ||
} | ||
async.invoke( fn, localP, v ); | ||
} | ||
function rejectFromThenable( v ) { | ||
if( called && this !== key ) return; | ||
var fn = localP._reject; | ||
called = true; | ||
var b = Promise$_Cast( v ); | ||
if( b !== v || | ||
( b instanceof Promise && b.isPending() ) ) { | ||
if( v === x ) { | ||
async.invoke( fn, localP, v ); | ||
} | ||
else { | ||
b._then(resolveFromThenable, rejectFromThenable, void 0, | ||
key, void 0, resolveFromThenable); | ||
} | ||
return; | ||
} | ||
if( b instanceof Promise ) { | ||
var fn = b.isFulfilled() | ||
? localP._fulfill : localP._reject; | ||
v = v._resolvedValue; | ||
b = Promise$_Cast( v ); | ||
if( b !== v || | ||
( b instanceof Promise && b.isPending() ) ) { | ||
b._then(resolveFromThenable, rejectFromThenable, void 0, | ||
key, void 0, resolveFromThenable); | ||
return; | ||
} | ||
} | ||
async.invoke( fn, localP, v ); | ||
} | ||
var threw = tryCatch2( then, x, | ||
resolveFromThenable, rejectFromThenable); | ||
if( threw === errorObj && | ||
!called ) { | ||
this._attachExtraTrace( threw.e ); | ||
async.invoke( this._reject, this, threw.e ); | ||
} | ||
}; | ||
Promise._cast = Promise$_Cast; | ||
}; |
@@ -575,3 +575,2 @@ /** | ||
var ignore = CatchFilter.prototype.doFilter; | ||
var ref = {ref: null}; | ||
Promise.prototype._resolvePromise = function Promise$_resolvePromise( | ||
@@ -647,24 +646,14 @@ onFulfilledOrRejected, receiver, value, promise | ||
else { | ||
if( promise._tryAssumeStateOf( x, true ) ) { | ||
return; | ||
} | ||
else if( Promise._isThenable( x, ref ) ) { | ||
var then = ref.ref; | ||
ref.ref = null; | ||
promise._resolveThenable(x, then); | ||
return; | ||
} | ||
var castValue = Promise._cast(x); | ||
var isThenable = castValue !== x; | ||
if (ref.ref === errorObj) { | ||
ref.ref = null; | ||
var e = errorObj.e; | ||
promise._attachExtraTrace(e); | ||
async.invoke(promise._reject, promise, e); | ||
if (isThenable || isPromise(castValue)) { | ||
if (castValue.isRejected()) { | ||
promise._attachExtraTrace(castValue._resolvedValue); | ||
} | ||
promise._assumeStateOf(castValue, true); | ||
} | ||
else { | ||
ref.ref = null; | ||
async.invoke( promise._fulfill, promise, x ); | ||
async.invoke(promise._fulfill, promise, x); | ||
} | ||
} | ||
@@ -685,3 +674,4 @@ }; | ||
this, | ||
void 0, this._tryAssumeStateOf | ||
null, | ||
this._assumeStateOf | ||
); | ||
@@ -710,7 +700,11 @@ } | ||
function Promise$_tryAssumeStateOf( value, mustAsync ) { | ||
if( !isPromise( value ) || | ||
this._isFollowingOrFulfilledOrRejected() || | ||
value === this ) return false; | ||
this._assumeStateOf( value, mustAsync ); | ||
if (this._isFollowingOrFulfilledOrRejected() || | ||
value === this) { | ||
return false; | ||
} | ||
var maybePromise = Promise._cast(value); | ||
if (!isPromise(maybePromise)) { | ||
return false; | ||
} | ||
this._assumeStateOf(maybePromise, mustAsync); | ||
return true; | ||
@@ -991,3 +985,4 @@ }; | ||
require( "./direct_resolve.js" )( Promise ); | ||
require( "./direct_resolve.js" )(Promise); | ||
require( "./thenables.js")(Promise); | ||
Promise.CancellationError = CancellationError; | ||
@@ -1012,3 +1007,2 @@ Promise.TimeoutError = TimeoutError; | ||
require('./cancel.js')(Promise); | ||
require('./complex_thenables.js')(Promise); | ||
@@ -1015,0 +1009,0 @@ Promise.prototype = Promise.prototype; |
@@ -25,5 +25,3 @@ /** | ||
var ASSERT = require("./assert.js"); | ||
var async = require( "./async.js" ); | ||
var util = require( "./util.js" ); | ||
var isPrimitive = util.isPrimitive; | ||
var errorObj = util.errorObj; | ||
@@ -43,21 +41,2 @@ var isObject = util.isObject; | ||
function isThenable(obj, ref) { | ||
if (isPrimitive(obj)) { | ||
return false; | ||
} | ||
var then = getThen(obj); | ||
if (then === errorObj) { | ||
ref.ref = errorObj; | ||
return false; | ||
} | ||
if (typeof then === "function") { | ||
ref.ref = then; | ||
return true; | ||
} | ||
return false; | ||
} | ||
var ref = {ref: null}; | ||
function Promise$_Cast( obj, caller ) { | ||
@@ -68,14 +47,10 @@ if( isObject( obj ) ) { | ||
} | ||
if( isThenable( obj, ref ) ) { | ||
var then = getThen(obj); | ||
if (then === errorObj) { | ||
return Promise.reject(then.e); | ||
} | ||
else if (typeof then === "function") { | ||
caller = typeof caller === "function" ? caller : Promise$_Cast; | ||
var then = ref.ref; | ||
ref.ref = null; | ||
return doThenable( obj, then, caller ); | ||
return doThenable(obj, then, caller); | ||
} | ||
else if (ref.ref === errorObj) { | ||
ref.ref = null; | ||
return Promise.reject(errorObj.e); | ||
} | ||
ref.ref = null; | ||
} | ||
@@ -85,5 +60,2 @@ return obj; | ||
Promise._cast = Promise$_Cast; | ||
Promise._isThenable = isThenable; | ||
function doThenable( x, then, caller ) { | ||
@@ -108,3 +80,3 @@ function resolveFromThenable( a ) { | ||
resolver, | ||
void 0, | ||
null, | ||
resolveFromThenable | ||
@@ -123,3 +95,3 @@ ); | ||
var resolver = Promise.defer( caller ); | ||
var resolver = Promise.defer(caller); | ||
@@ -134,86 +106,3 @@ var called = false; | ||
Promise.prototype._resolveThenable = | ||
function Promise$_resolveThenable(x, then) { | ||
var localP = this; | ||
var key = {}; | ||
var called = false; | ||
function resolveFromThenable( v ) { | ||
if( called && this !== key ) return; | ||
called = true; | ||
var fn = localP._fulfill; | ||
var b = Promise$_Cast( v ); | ||
if( b !== v || | ||
( b instanceof Promise && b.isPending() ) ) { | ||
if( v === x ) { | ||
fn.call(localP, v); | ||
} | ||
else { | ||
b._then( resolveFromThenable, rejectFromThenable, void 0, | ||
key, void 0, resolveFromThenable); | ||
} | ||
return; | ||
} | ||
if( b instanceof Promise ) { | ||
var fn = b.isFulfilled() | ||
? localP._fulfill : localP._reject; | ||
v = v._resolvedValue; | ||
b = Promise$_Cast( v ); | ||
if( b !== v || | ||
( b instanceof Promise && b !== v ) ) { | ||
b._then(resolveFromThenable, rejectFromThenable, void 0, | ||
key, void 0, resolveFromThenable); | ||
return; | ||
} | ||
} | ||
fn.call(localP, v); | ||
} | ||
function rejectFromThenable( v ) { | ||
if( called && this !== key ) return; | ||
var fn = localP._reject; | ||
called = true; | ||
var b = Promise$_Cast( v ); | ||
if( b !== v || | ||
( b instanceof Promise && b.isPending() ) ) { | ||
if( v === x ) { | ||
fn.call(localP, v); | ||
} | ||
else { | ||
b._then(resolveFromThenable, rejectFromThenable, void 0, | ||
key, void 0, resolveFromThenable); | ||
} | ||
return; | ||
} | ||
if( b instanceof Promise ) { | ||
var fn = b.isFulfilled() | ||
? localP._fulfill : localP._reject; | ||
v = v._resolvedValue; | ||
b = Promise$_Cast( v ); | ||
if( b !== v || | ||
( b instanceof Promise && b.isPending() ) ) { | ||
b._then(resolveFromThenable, rejectFromThenable, void 0, | ||
key, void 0, resolveFromThenable); | ||
return; | ||
} | ||
} | ||
fn.call(localP, v); | ||
} | ||
var threw = tryCatch2( then, x, | ||
resolveFromThenable, rejectFromThenable); | ||
if( threw === errorObj && | ||
!called ) { | ||
this._attachExtraTrace( threw.e ); | ||
this._reject(threw.e); | ||
} | ||
}; | ||
Promise._cast = Promise$_Cast; | ||
}; |
@@ -575,3 +575,2 @@ /** | ||
var ignore = CatchFilter.prototype.doFilter; | ||
var ref = {ref: null}; | ||
Promise.prototype._resolvePromise = function Promise$_resolvePromise( | ||
@@ -643,24 +642,14 @@ onFulfilledOrRejected, receiver, value, promise | ||
else { | ||
if( promise._tryAssumeStateOf( x, true ) ) { | ||
return; | ||
} | ||
else if( Promise._isThenable( x, ref ) ) { | ||
var then = ref.ref; | ||
ref.ref = null; | ||
promise._resolveThenable(x, then); | ||
return; | ||
} | ||
var castValue = Promise._cast(x); | ||
var isThenable = castValue !== x; | ||
if (ref.ref === errorObj) { | ||
ref.ref = null; | ||
var e = errorObj.e; | ||
promise._attachExtraTrace(e); | ||
promise._reject(e); | ||
if (isThenable || isPromise(castValue)) { | ||
if (castValue.isRejected()) { | ||
promise._attachExtraTrace(castValue._resolvedValue); | ||
} | ||
promise._assumeStateOf(castValue, true); | ||
} | ||
else { | ||
ref.ref = null; | ||
promise._fulfill(x); | ||
} | ||
} | ||
@@ -681,3 +670,4 @@ }; | ||
this, | ||
void 0, this._tryAssumeStateOf | ||
null, | ||
this._assumeStateOf | ||
); | ||
@@ -706,7 +696,11 @@ } | ||
function Promise$_tryAssumeStateOf( value, mustAsync ) { | ||
if( !isPromise( value ) || | ||
this._isFollowingOrFulfilledOrRejected() || | ||
value === this ) return false; | ||
this._assumeStateOf( value, mustAsync ); | ||
if (this._isFollowingOrFulfilledOrRejected() || | ||
value === this) { | ||
return false; | ||
} | ||
var maybePromise = Promise._cast(value); | ||
if (!isPromise(maybePromise)) { | ||
return false; | ||
} | ||
this._assumeStateOf(maybePromise, mustAsync); | ||
return true; | ||
@@ -987,3 +981,4 @@ }; | ||
require( "./direct_resolve.js" )( Promise ); | ||
require( "./direct_resolve.js" )(Promise); | ||
require( "./thenables.js")(Promise); | ||
Promise.CancellationError = CancellationError; | ||
@@ -1008,3 +1003,2 @@ Promise.TimeoutError = TimeoutError; | ||
require('./cancel.js')(Promise); | ||
require('./complex_thenables.js')(Promise); | ||
@@ -1011,0 +1005,0 @@ Promise.prototype = Promise.prototype; |
{ | ||
"name": "bluebird", | ||
"description": "Full featured Promises/A+ implementation with exceptionally good performance", | ||
"version": "0.10.5-0", | ||
"version": "0.10.6-0", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "promise", |
@@ -33,4 +33,3 @@ [![Build Status](https://travis-ci.org/petkaantonov/bluebird.png?branch=master)](https://travis-ci.org/petkaantonov/bluebird) | ||
- [Promises A+ 3.x.x](https://github.com/promises-aplus/promises-spec) | ||
- [Promises A+ 2.x.x](https://github.com/domenic/promises-unwrapping) | ||
- [Promises A+ 2.0.2](http://promisesaplus.com) | ||
- [Cancellation](https://github.com/promises-aplus) | ||
@@ -45,3 +44,3 @@ - [Progression](https://github.com/promises-aplus/progress-spec) | ||
Passes [AP2](https://github.com/petkaantonov/bluebird/tree/master/test/mocha), [AP3](https://github.com/petkaantonov/bluebird/tree/master/test/mocha), [Cancellation](https://github.com/petkaantonov/bluebird/blob/master/test/mocha/cancel.js), [Progress](https://github.com/petkaantonov/bluebird/blob/master/test/mocha/q_progress.js), [promises_unwrapping](https://github.com/petkaantonov/bluebird/blob/master/test/mocha/promises_unwrapping.js) (Just in time thenables), [Q](https://github.com/petkaantonov/bluebird/tree/master/test/mocha) and [When.js](https://github.com/petkaantonov/bluebird/tree/master/test) tests. See [testing](#testing). | ||
Passes [AP2](https://github.com/petkaantonov/bluebird/tree/master/test/mocha), [AP3](https://github.com/petkaantonov/bluebird/tree/master/test/mocha), [Cancellation](https://github.com/petkaantonov/bluebird/blob/master/test/mocha/cancel.js), [Progress](https://github.com/petkaantonov/bluebird/blob/master/test/mocha/q_progress.js), [Q](https://github.com/petkaantonov/bluebird/tree/master/test/mocha) and [When.js](https://github.com/petkaantonov/bluebird/tree/master/test) tests. See [testing](#testing). | ||
@@ -561,3 +560,2 @@ <hr> | ||
<tr><td><a href="https://github.com/petkaantonov/bluebird/blob/master/API.md#promisecoroutinegeneratorfunction-generatorfunction---function"><code>Promise.coroutine</code></a> and <a href="https://github.com/petkaantonov/bluebird/blob/master/API.md#promisespawngeneratorfunction-generatorfunction---promise"><code>Promise.spawn</code></a></td><td><code>generators</code></td></tr> | ||
<tr><td><a href="#complex-thenables">Complex thenables</a></td><td><code>simple_thenables</code></td></tr> | ||
<tr><td><a href="https://github.com/petkaantonov/bluebird/blob/master/API.md#progression">Progression</a></td><td><code>progress</code></td></tr> | ||
@@ -576,3 +574,3 @@ <tr><td><a href="https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification">Promisification</a></td><td><code>promisify</code></td></tr> | ||
grunt build --features="core simple_thenables" | ||
grunt build --features="core" | ||
@@ -582,3 +580,3 @@ | ||
grunt build --features="core simple_thenables filter map reduce" | ||
grunt build --features="core filter map reduce" | ||
@@ -592,28 +590,2 @@ The custom build file will be found from `/js/browser/bluebird.js`. It will have a comment that lists the disabled and enabled features. | ||
####Complex thenables | ||
In order to provide smooth interoperability experience, Promises/A+ requires supporting "thenables" which are promise-like objects but not trusted bluebird promises. | ||
For example this should work: | ||
```js | ||
bluebirdPromise.then(function(){ | ||
return $.get("/file.php"); | ||
}); | ||
``` | ||
Even though the handler returns a jQuery promise, it should work as if it returned a real bluebird promise, that is, the next `.then()` will wait until the ajax | ||
request is complete. | ||
However the specification in A+ 2.x.x requires handling of many theoretical edge cases that will never be seen in practice, such as: | ||
- Trying to retrieve the `.then` property from object to see if it's a function might throw. | ||
- Retrieving `.then` property multiple times from an object might return different result every time, or might be deleted after some time | ||
- Calling the `.then` property of an object before necessary (just in time thenables) might cause problems | ||
- etc. | ||
What you want in a browser is pretty much that the `return $.get` line works. Can you imagine jQuery defining a getter on `.then` property that throws? | ||
Handling such cases requires a lot of code in bluebird. You can use the `simple_thenables` feature which matches what other libraries such as Q are doing. | ||
<hr> | ||
@@ -620,0 +592,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
95
452481
9361
687