Commit 05e09ef3 authored by Stefan Penner's avatar Stefan Penner

Merge pull request #68 from stefanpenner/self_resolution

promise.resolve(promise) === fulfillment
parents 46bce2f6 557ffb79
...@@ -369,7 +369,13 @@ define("rsvp/promise", ...@@ -369,7 +369,13 @@ define("rsvp/promise",
var config = __dependency1__.config; var config = __dependency1__.config;
var EventTarget = __dependency2__.EventTarget; var EventTarget = __dependency2__.EventTarget;
var noop = function() {}; function objectOrFunction(x) {
return isFunction(x) || (typeof x === "object" && x !== null);
}
function isFunction(x){
return typeof x === "function";
}
var Promise = function(resolver) { var Promise = function(resolver) {
var promise = this, var promise = this,
...@@ -407,7 +413,7 @@ define("rsvp/promise", ...@@ -407,7 +413,7 @@ define("rsvp/promise",
}; };
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function', var hasCallback = isFunction(callback),
value, error, succeeded, failed; value, error, succeeded, failed;
if (hasCallback) { if (hasCallback) {
...@@ -423,7 +429,7 @@ define("rsvp/promise", ...@@ -423,7 +429,7 @@ define("rsvp/promise",
succeeded = true; succeeded = true;
} }
if (value && typeof value.then === 'function') { if (objectOrFunction(value) && isFunction(value.then)) {
value.then(function(value) { value.then(function(value) {
resolve(promise, value); resolve(promise, value);
}, function(error) { }, function(error) {
...@@ -473,9 +479,13 @@ define("rsvp/promise", ...@@ -473,9 +479,13 @@ define("rsvp/promise",
EventTarget.mixin(Promise.prototype); EventTarget.mixin(Promise.prototype);
function resolve(promise, value) { function resolve(promise, value) {
if (value && typeof value.then === 'function') { if (objectOrFunction(value) && isFunction(value.then)) {
value.then(function(val) { value.then(function(val) {
resolve(promise, val); if (value !== val) {
resolve(promise, val);
} else {
fulfill(promise, val);
}
}, function(val) { }, function(val) {
reject(promise, val); reject(promise, val);
}); });
......
(function(){var e,t;(function(){var r={},n={};e=function(e,t,n){r[e]={deps:t,callback:n}};t=function(e){if(n[e]){return n[e]}n[e]={};var i=r[e],o=i.deps,s=i.callback,f=[],c;for(var u=0,a=o.length;u<a;u++){if(o[u]==="exports"){f.push(c={})}else{f.push(t(o[u]))}}var v=s.apply(this,f);return n[e]=c||v}})();e("rsvp/all",["rsvp/defer","exports"],function(e,t){"use strict";var r=e.defer;function n(e){var t=[],n=r(),i=e.length;if(i===0){n.resolve([])}var o=function(e){return function(t){s(e,t)}};var s=function(e,r){t[e]=r;if(--i===0){n.resolve(t)}};var f=function(e){n.reject(e)};for(var c=0;c<e.length;c++){if(e[c]&&typeof e[c].then==="function"){e[c].then(o(c),f)}else{s(c,e[c])}}return n.promise}t.all=n});e("rsvp/async",["exports"],function(e){"use strict";var t=typeof window!=="undefined"?window:{};var r=t.MutationObserver||t.WebKitMutationObserver;var n;if(typeof process!=="undefined"&&{}.toString.call(process)==="[object process]"){n=function(e,t){process.nextTick(function(){e.call(t)})}}else if(r){var i=[];var o=new r(function(){var e=i.slice();i=[];e.forEach(function(e){var t=e[0],r=e[1];t.call(r)})});var s=document.createElement("div");o.observe(s,{attributes:true});window.addEventListener("unload",function(){o.disconnect();o=null});n=function(e,t){i.push([e,t]);s.setAttribute("drainQueue","drainQueue")}}else{n=function(e,t){setTimeout(function(){e.call(t)},1)}}e.async=n});e("rsvp/config",["rsvp/async","exports"],function(e,t){"use strict";var r=e.async;var n={};n.async=r;t.config=n});e("rsvp/defer",["rsvp/promise","exports"],function(e,t){"use strict";var r=e.Promise;function n(){var e={};var t=new r(function(t,r){e.resolve=t;e.reject=r});e.promise=t;return e}t.defer=n});e("rsvp/events",["exports"],function(e){"use strict";var t=function(e,t){this.type=e;for(var r in t){if(!t.hasOwnProperty(r)){continue}this[r]=t[r]}};var r=function(e,t){for(var r=0,n=e.length;r<n;r++){if(e[r][0]===t){return r}}return-1};var n=function(e){var t=e._promiseCallbacks;if(!t){t=e._promiseCallbacks={}}return t};var i={mixin:function(e){e.on=this.on;e.off=this.off;e.trigger=this.trigger;return e},on:function(e,t,i){var o=n(this),s,f;e=e.split(/\s+/);i=i||this;while(f=e.shift()){s=o[f];if(!s){s=o[f]=[]}if(r(s,t)===-1){s.push([t,i])}}},off:function(e,t){var i=n(this),o,s,f;e=e.split(/\s+/);while(s=e.shift()){if(!t){i[s]=[];continue}o=i[s];f=r(o,t);if(f!==-1){o.splice(f,1)}}},trigger:function(e,r){var i=n(this),o,s,f,c,u;if(o=i[e]){for(var a=0;a<o.length;a++){s=o[a];f=s[0];c=s[1];if(typeof r!=="object"){r={detail:r}}u=new t(e,r);f.call(c,u)}}}};e.EventTarget=i});e("rsvp/hash",["rsvp/defer","exports"],function(e,t){"use strict";var r=e.defer;function n(e){var t=0;for(var r in e){t++}return t}function i(e){var t={},i=r(),o=n(e);if(o===0){i.resolve({})}var s=function(e){return function(t){f(e,t)}};var f=function(e,r){t[e]=r;if(--o===0){i.resolve(t)}};var c=function(e){i.reject(e)};for(var u in e){if(e[u]&&typeof e[u].then==="function"){e[u].then(s(u),c)}else{f(u,e[u])}}return i.promise}t.hash=i});e("rsvp/node",["rsvp/promise","rsvp/all","exports"],function(e,t,r){"use strict";var n=e.Promise;var i=t.all;function o(e,t){return function(r,n){if(r){t(r)}else if(arguments.length>2){e(Array.prototype.slice.call(arguments,1))}else{e(n)}}}function s(e){return function(){var t=Array.prototype.slice.call(arguments),r,s;var f=new n(function(e,t){r=e;s=t});i(t).then(function(t){t.push(o(r,s));try{e.apply(this,t)}catch(n){s(n)}});return f}}r.denodeify=s});e("rsvp/promise",["rsvp/config","rsvp/events","exports"],function(e,t,r){"use strict";var n=e.config;var i=t.EventTarget;var o=function(){};var s=function(e){var t=this,r=false;if(typeof e!=="function"){throw new TypeError("You must pass a resolver function as the sole argument to the promise constructor")}if(!(t instanceof s)){return new s(e)}var n=function(e){if(r){return}r=true;c(t,e)};var i=function(e){if(r){return}r=true;a(t,e)};this.on("promise:resolved",function(e){this.trigger("success",{detail:e.detail})},this);this.on("promise:failed",function(e){this.trigger("error",{detail:e.detail})},this);e(n,i)};var f=function(e,t,r,n){var i=typeof r==="function",o,s,f,u;if(i){try{o=r(n.detail);f=true}catch(v){u=true;s=v}}else{o=n.detail;f=true}if(o&&typeof o.then==="function"){o.then(function(e){c(t,e)},function(e){a(t,e)})}else if(i&&f){c(t,o)}else if(u){a(t,s)}else if(e==="resolve"){c(t,o)}else if(e==="reject"){a(t,o)}};s.prototype={constructor:s,then:function(e,t){var r=new s(function(){});if(this.isFulfilled){n.async(function(){f("resolve",r,e,{detail:this.fulfillmentValue})},this)}if(this.isRejected){n.async(function(){f("reject",r,t,{detail:this.rejectedReason})},this)}this.on("promise:resolved",function(t){f("resolve",r,e,t)});this.on("promise:failed",function(e){f("reject",r,t,e)});return r}};i.mixin(s.prototype);function c(e,t){if(t&&typeof t.then==="function"){t.then(function(t){c(e,t)},function(t){a(e,t)})}else{u(e,t)}}function u(e,t){n.async(function(){e.trigger("promise:resolved",{detail:t});e.isFulfilled=true;e.fulfillmentValue=t})}function a(e,t){n.async(function(){e.trigger("promise:failed",{detail:t});e.isRejected=true;e.rejectedReason=t})}r.Promise=s});e("rsvp/resolve",["rsvp/promise","exports"],function(e,t){"use strict";var r=e.Promise;function n(e){return typeof e==="function"||typeof e==="object"&&e!==null}function i(e){var t=new r(function(t,r){var i;try{if(n(e)){i=e.then;if(typeof i==="function"){i.call(e,t,r)}else{t(e)}}else{t(e)}}catch(o){r(o)}});return t}t.resolve=i});e("rsvp",["rsvp/events","rsvp/promise","rsvp/node","rsvp/all","rsvp/hash","rsvp/defer","rsvp/config","rsvp/resolve","exports"],function(e,t,r,n,i,o,s,f,c){"use strict";var u=e.EventTarget;var a=t.Promise;var v=r.denodeify;var l=n.all;var p=i.hash;var h=o.defer;var d=s.config;var y=f.resolve;function g(e,t){d[e]=t}c.Promise=a;c.EventTarget=u;c.all=l;c.hash=p;c.defer=h;c.denodeify=v;c.configure=g;c.resolve=y});window.RSVP=t("rsvp")})(); (function(){var e,t;(function(){var r={},n={};e=function(e,t,n){r[e]={deps:t,callback:n}};t=function(e){if(n[e]){return n[e]}n[e]={};var i=r[e],o=i.deps,s=i.callback,f=[],c;for(var u=0,a=o.length;u<a;u++){if(o[u]==="exports"){f.push(c={})}else{f.push(t(o[u]))}}var l=s.apply(this,f);return n[e]=c||l}})();e("rsvp/all",["rsvp/defer","exports"],function(e,t){"use strict";var r=e.defer;function n(e){var t=[],n=r(),i=e.length;if(i===0){n.resolve([])}var o=function(e){return function(t){s(e,t)}};var s=function(e,r){t[e]=r;if(--i===0){n.resolve(t)}};var f=function(e){n.reject(e)};for(var c=0;c<e.length;c++){if(e[c]&&typeof e[c].then==="function"){e[c].then(o(c),f)}else{s(c,e[c])}}return n.promise}t.all=n});e("rsvp/async",["exports"],function(e){"use strict";var t=typeof window!=="undefined"?window:{};var r=t.MutationObserver||t.WebKitMutationObserver;var n;if(typeof process!=="undefined"&&{}.toString.call(process)==="[object process]"){n=function(e,t){process.nextTick(function(){e.call(t)})}}else if(r){var i=[];var o=new r(function(){var e=i.slice();i=[];e.forEach(function(e){var t=e[0],r=e[1];t.call(r)})});var s=document.createElement("div");o.observe(s,{attributes:true});window.addEventListener("unload",function(){o.disconnect();o=null});n=function(e,t){i.push([e,t]);s.setAttribute("drainQueue","drainQueue")}}else{n=function(e,t){setTimeout(function(){e.call(t)},1)}}e.async=n});e("rsvp/config",["rsvp/async","exports"],function(e,t){"use strict";var r=e.async;var n={};n.async=r;t.config=n});e("rsvp/defer",["rsvp/promise","exports"],function(e,t){"use strict";var r=e.Promise;function n(){var e={};var t=new r(function(t,r){e.resolve=t;e.reject=r});e.promise=t;return e}t.defer=n});e("rsvp/events",["exports"],function(e){"use strict";var t=function(e,t){this.type=e;for(var r in t){if(!t.hasOwnProperty(r)){continue}this[r]=t[r]}};var r=function(e,t){for(var r=0,n=e.length;r<n;r++){if(e[r][0]===t){return r}}return-1};var n=function(e){var t=e._promiseCallbacks;if(!t){t=e._promiseCallbacks={}}return t};var i={mixin:function(e){e.on=this.on;e.off=this.off;e.trigger=this.trigger;return e},on:function(e,t,i){var o=n(this),s,f;e=e.split(/\s+/);i=i||this;while(f=e.shift()){s=o[f];if(!s){s=o[f]=[]}if(r(s,t)===-1){s.push([t,i])}}},off:function(e,t){var i=n(this),o,s,f;e=e.split(/\s+/);while(s=e.shift()){if(!t){i[s]=[];continue}o=i[s];f=r(o,t);if(f!==-1){o.splice(f,1)}}},trigger:function(e,r){var i=n(this),o,s,f,c,u;if(o=i[e]){for(var a=0;a<o.length;a++){s=o[a];f=s[0];c=s[1];if(typeof r!=="object"){r={detail:r}}u=new t(e,r);f.call(c,u)}}}};e.EventTarget=i});e("rsvp/hash",["rsvp/defer","exports"],function(e,t){"use strict";var r=e.defer;function n(e){var t=0;for(var r in e){t++}return t}function i(e){var t={},i=r(),o=n(e);if(o===0){i.resolve({})}var s=function(e){return function(t){f(e,t)}};var f=function(e,r){t[e]=r;if(--o===0){i.resolve(t)}};var c=function(e){i.reject(e)};for(var u in e){if(e[u]&&typeof e[u].then==="function"){e[u].then(s(u),c)}else{f(u,e[u])}}return i.promise}t.hash=i});e("rsvp/node",["rsvp/promise","rsvp/all","exports"],function(e,t,r){"use strict";var n=e.Promise;var i=t.all;function o(e,t){return function(r,n){if(r){t(r)}else if(arguments.length>2){e(Array.prototype.slice.call(arguments,1))}else{e(n)}}}function s(e){return function(){var t=Array.prototype.slice.call(arguments),r,s;var f=new n(function(e,t){r=e;s=t});i(t).then(function(t){t.push(o(r,s));try{e.apply(this,t)}catch(n){s(n)}});return f}}r.denodeify=s});e("rsvp/promise",["rsvp/config","rsvp/events","exports"],function(e,t,r){"use strict";var n=e.config;var i=t.EventTarget;function o(e){return s(e)||typeof e==="object"&&e!==null}function s(e){return typeof e==="function"}var f=function(e){var t=this,r=false;if(typeof e!=="function"){throw new TypeError("You must pass a resolver function as the sole argument to the promise constructor")}if(!(t instanceof f)){return new f(e)}var n=function(e){if(r){return}r=true;u(t,e)};var i=function(e){if(r){return}r=true;l(t,e)};this.on("promise:resolved",function(e){this.trigger("success",{detail:e.detail})},this);this.on("promise:failed",function(e){this.trigger("error",{detail:e.detail})},this);e(n,i)};var c=function(e,t,r,n){var i=s(r),f,c,a,v;if(i){try{f=r(n.detail);a=true}catch(p){v=true;c=p}}else{f=n.detail;a=true}if(o(f)&&s(f.then)){f.then(function(e){u(t,e)},function(e){l(t,e)})}else if(i&&a){u(t,f)}else if(v){l(t,c)}else if(e==="resolve"){u(t,f)}else if(e==="reject"){l(t,f)}};f.prototype={constructor:f,then:function(e,t){var r=new f(function(){});if(this.isFulfilled){n.async(function(){c("resolve",r,e,{detail:this.fulfillmentValue})},this)}if(this.isRejected){n.async(function(){c("reject",r,t,{detail:this.rejectedReason})},this)}this.on("promise:resolved",function(t){c("resolve",r,e,t)});this.on("promise:failed",function(e){c("reject",r,t,e)});return r}};i.mixin(f.prototype);function u(e,t){if(o(t)&&s(t.then)){t.then(function(r){if(t!==r){u(e,r)}else{a(e,r)}},function(t){l(e,t)})}else{a(e,t)}}function a(e,t){n.async(function(){e.trigger("promise:resolved",{detail:t});e.isFulfilled=true;e.fulfillmentValue=t})}function l(e,t){n.async(function(){e.trigger("promise:failed",{detail:t});e.isRejected=true;e.rejectedReason=t})}r.Promise=f});e("rsvp/resolve",["rsvp/promise","exports"],function(e,t){"use strict";var r=e.Promise;function n(e){return typeof e==="function"||typeof e==="object"&&e!==null}function i(e){var t=new r(function(t,r){var i;try{if(n(e)){i=e.then;if(typeof i==="function"){i.call(e,t,r)}else{t(e)}}else{t(e)}}catch(o){r(o)}});return t}t.resolve=i});e("rsvp",["rsvp/events","rsvp/promise","rsvp/node","rsvp/all","rsvp/hash","rsvp/defer","rsvp/config","rsvp/resolve","exports"],function(e,t,r,n,i,o,s,f,c){"use strict";var u=e.EventTarget;var a=t.Promise;var l=r.denodeify;var v=n.all;var p=i.hash;var h=o.defer;var d=s.config;var y=f.resolve;function g(e,t){d[e]=t}c.Promise=a;c.EventTarget=u;c.all=v;c.hash=p;c.defer=h;c.denodeify=l;c.configure=g;c.resolve=y});window.RSVP=t("rsvp")})();
...@@ -5,7 +5,13 @@ define( ...@@ -5,7 +5,13 @@ define(
var config = __dependency1__.config; var config = __dependency1__.config;
var EventTarget = __dependency2__.EventTarget; var EventTarget = __dependency2__.EventTarget;
var noop = function() {}; function objectOrFunction(x) {
return isFunction(x) || (typeof x === "object" && x !== null);
}
function isFunction(x){
return typeof x === "function";
}
var Promise = function(resolver) { var Promise = function(resolver) {
var promise = this, var promise = this,
...@@ -43,7 +49,7 @@ define( ...@@ -43,7 +49,7 @@ define(
}; };
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function', var hasCallback = isFunction(callback),
value, error, succeeded, failed; value, error, succeeded, failed;
if (hasCallback) { if (hasCallback) {
...@@ -59,7 +65,7 @@ define( ...@@ -59,7 +65,7 @@ define(
succeeded = true; succeeded = true;
} }
if (value && typeof value.then === 'function') { if (objectOrFunction(value) && isFunction(value.then)) {
value.then(function(value) { value.then(function(value) {
resolve(promise, value); resolve(promise, value);
}, function(error) { }, function(error) {
...@@ -109,9 +115,13 @@ define( ...@@ -109,9 +115,13 @@ define(
EventTarget.mixin(Promise.prototype); EventTarget.mixin(Promise.prototype);
function resolve(promise, value) { function resolve(promise, value) {
if (value && typeof value.then === 'function') { if (objectOrFunction(value) && isFunction(value.then)) {
value.then(function(val) { value.then(function(val) {
resolve(promise, val); if (value !== val) {
resolve(promise, val);
} else {
fulfill(promise, val);
}
}, function(val) { }, function(val) {
reject(promise, val); reject(promise, val);
}); });
......
import { config } from "rsvp/config"; import { config } from "rsvp/config";
import { EventTarget } from "rsvp/events"; import { EventTarget } from "rsvp/events";
function objectOrFunction(x) {
return isFunction(x) || (typeof x === "object" && x !== null);
}
function isFunction(x){
return typeof x === "function";
}
var Promise = function(resolver) { var Promise = function(resolver) {
var promise = this, var promise = this,
resolved = false; resolved = false;
...@@ -37,7 +45,7 @@ var Promise = function(resolver) { ...@@ -37,7 +45,7 @@ var Promise = function(resolver) {
}; };
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function', var hasCallback = isFunction(callback),
value, error, succeeded, failed; value, error, succeeded, failed;
if (hasCallback) { if (hasCallback) {
...@@ -53,7 +61,7 @@ var invokeCallback = function(type, promise, callback, event) { ...@@ -53,7 +61,7 @@ var invokeCallback = function(type, promise, callback, event) {
succeeded = true; succeeded = true;
} }
if (value && typeof value.then === 'function') { if (objectOrFunction(value) && isFunction(value.then)) {
value.then(function(value) { value.then(function(value) {
resolve(promise, value); resolve(promise, value);
}, function(error) { }, function(error) {
...@@ -103,9 +111,13 @@ Promise.prototype = { ...@@ -103,9 +111,13 @@ Promise.prototype = {
EventTarget.mixin(Promise.prototype); EventTarget.mixin(Promise.prototype);
function resolve(promise, value) { function resolve(promise, value) {
if (value && typeof value.then === 'function') { if (objectOrFunction(value) && isFunction(value.then)) {
value.then(function(val) { value.then(function(val) {
resolve(promise, val); if (value !== val) {
resolve(promise, val);
} else {
fulfill(promise, val);
}
}, function(val) { }, function(val) {
reject(promise, val); reject(promise, val);
}); });
......
/*global RSVP, describe, specify, it, assert */ /*global RSVP, describe, specify, it, assert */
describe("RSVP extensions", function() { describe("RSVP extensions", function() {
describe("self fulfillment", function(){
it("treats self fulfillment as the recursive base case", function(done){
var aDefer = new RSVP.defer(),
bDefer = new RSVP.defer();
aDefer.promise.then(function(a){
setTimeout(function(){
bDefer.resolve(bDefer.promise);
}, 1);
return bDefer.promise;
});
bDefer.promise.then(function(c){
done();
})
aDefer.resolve(aDefer.promise);
});
});
describe("Promise constructor", function() { describe("Promise constructor", function() {
it('should exist and have length 1', function() { it('should exist and have length 1', function() {
assert(RSVP.Promise); assert(RSVP.Promise);
...@@ -113,6 +134,27 @@ describe("RSVP extensions", function() { ...@@ -113,6 +134,27 @@ describe("RSVP extensions", function() {
}); });
}); });
it('should assimilate two levels deep, for fulfillment of self fulfilling promises', function(done) {
var originalPromise, promise;
originalPromise = new RSVP.Promise(function(resolve) {
setTimeout(function() {
resolve(originalPromise);
}, 0)
});
promise = new RSVP.Promise(function(resolve) {
setTimeout(function() {
resolve(originalPromise);
}, 0);
});
promise.then(function(value) {
assert.equal(value, originalPromise);
done();
});
});
it('should assimilate two levels deep, for fulfillment', function(done) { it('should assimilate two levels deep, for fulfillment', function(done) {
var originalPromise = new RSVP.Promise(function(resolve) { resolve('original value'); }); var originalPromise = new RSVP.Promise(function(resolve) { resolve('original value'); });
var nextPromise = new RSVP.Promise(function(resolve) { resolve(originalPromise); }); var nextPromise = new RSVP.Promise(function(resolve) { resolve(originalPromise); });
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment