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);
}); });
......
This diff is collapsed.
...@@ -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 diff is collapsed.
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