Commit a6cb2f64 authored by Tomhuda Katzdale's avatar Tomhuda Katzdale

Make RSVP's API more aligned with general practice

parent 9d7fa43c
...@@ -144,7 +144,23 @@ define( ...@@ -144,7 +144,23 @@ define(
} }
}; };
var Promise = function() { var noop = function() {};
var Promise = function(resolver) {
var promise = this;
var resolvePromise = function(value) {
resolve(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
var rejectPromise = function(value) {
reject(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
this.on('promise:resolved', function(event) { this.on('promise:resolved', function(event) {
this.trigger('success', { detail: event.detail }); this.trigger('success', { detail: event.detail });
}, this); }, this);
...@@ -152,9 +168,11 @@ define( ...@@ -152,9 +168,11 @@ define(
this.on('promise:failed', function(event) { this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
};
var noop = function() {}; if (resolver) {
resolver(resolvePromise, rejectPromise);
}
};
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function', var hasCallback = typeof callback === 'function',
...@@ -175,16 +193,18 @@ define( ...@@ -175,16 +193,18 @@ define(
if (value && typeof value.then === 'function') { if (value && typeof value.then === 'function') {
value.then(function(value) { value.then(function(value) {
promise.resolve(value); resolve(promise, value);
}, function(error) { }, function(error) {
promise.reject(error); reject(promise, error);
}); });
} else if (hasCallback && succeeded) { } else if (hasCallback && succeeded) {
promise.resolve(value); resolve(promise, value);
} else if (failed) { } else if (failed) {
promise.reject(error); reject(promise, error);
} else { } else if (type === 'resolve') {
promise[type](value); resolve(promise, value);
} else if (type === 'reject') {
reject(promise, value);
} }
}; };
...@@ -213,20 +233,6 @@ define( ...@@ -213,20 +233,6 @@ define(
}); });
return thenPromise; return thenPromise;
},
resolve: function(value) {
resolve(this, value);
this.resolve = noop;
this.reject = noop;
},
reject: function(value) {
reject(this, value);
this.resolve = noop;
this.reject = noop;
} }
}; };
...@@ -252,28 +258,28 @@ define( ...@@ -252,28 +258,28 @@ define(
var remaining = promises.length; var remaining = promises.length;
if (remaining === 0) { if (remaining === 0) {
allPromise.resolve([]); resolve(allPromise, []);
} }
var resolver = function(index) { var resolver = function(index) {
return function(value) { return function(value) {
resolve(index, value); resolveAll(index, value);
}; };
}; };
var resolve = function(index, value) { var resolveAll = function(index, value) {
results[index] = value; results[index] = value;
if (--remaining === 0) { if (--remaining === 0) {
allPromise.resolve(results); resolve(allPromise, results);
} }
}; };
var reject = function(error) { var rejectAll = function(error) {
allPromise.reject(error); reject(allPromise, error);
}; };
for (i = 0; i < remaining; i++) { for (i = 0; i < remaining; i++) {
promises[i].then(resolver(i), reject); promises[i].then(resolver(i), rejectAll);
} }
return allPromise; return allPromise;
} }
......
...@@ -142,7 +142,23 @@ ...@@ -142,7 +142,23 @@
} }
}; };
var Promise = function() { var noop = function() {};
var Promise = function(resolver) {
var promise = this;
var resolvePromise = function(value) {
resolve(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
var rejectPromise = function(value) {
reject(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
this.on('promise:resolved', function(event) { this.on('promise:resolved', function(event) {
this.trigger('success', { detail: event.detail }); this.trigger('success', { detail: event.detail });
}, this); }, this);
...@@ -150,9 +166,11 @@ ...@@ -150,9 +166,11 @@
this.on('promise:failed', function(event) { this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
};
var noop = function() {}; if (resolver) {
resolver(resolvePromise, rejectPromise);
}
};
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function', var hasCallback = typeof callback === 'function',
...@@ -173,16 +191,18 @@ ...@@ -173,16 +191,18 @@
if (value && typeof value.then === 'function') { if (value && typeof value.then === 'function') {
value.then(function(value) { value.then(function(value) {
promise.resolve(value); resolve(promise, value);
}, function(error) { }, function(error) {
promise.reject(error); reject(promise, error);
}); });
} else if (hasCallback && succeeded) { } else if (hasCallback && succeeded) {
promise.resolve(value); resolve(promise, value);
} else if (failed) { } else if (failed) {
promise.reject(error); reject(promise, error);
} else { } else if (type === 'resolve') {
promise[type](value); resolve(promise, value);
} else if (type === 'reject') {
reject(promise, value);
} }
}; };
...@@ -211,20 +231,6 @@ ...@@ -211,20 +231,6 @@
}); });
return thenPromise; return thenPromise;
},
resolve: function(value) {
resolve(this, value);
this.resolve = noop;
this.reject = noop;
},
reject: function(value) {
reject(this, value);
this.resolve = noop;
this.reject = noop;
} }
}; };
...@@ -250,28 +256,28 @@ ...@@ -250,28 +256,28 @@
var remaining = promises.length; var remaining = promises.length;
if (remaining === 0) { if (remaining === 0) {
allPromise.resolve([]); resolve(allPromise, []);
} }
var resolver = function(index) { var resolver = function(index) {
return function(value) { return function(value) {
resolve(index, value); resolveAll(index, value);
}; };
}; };
var resolve = function(index, value) { var resolveAll = function(index, value) {
results[index] = value; results[index] = value;
if (--remaining === 0) { if (--remaining === 0) {
allPromise.resolve(results); resolve(allPromise, results);
} }
}; };
var reject = function(error) { var rejectAll = function(error) {
allPromise.reject(error); reject(allPromise, error);
}; };
for (i = 0; i < remaining; i++) { for (i = 0; i < remaining; i++) {
promises[i].then(resolver(i), reject); promises[i].then(resolver(i), rejectAll);
} }
return allPromise; return allPromise;
} }
......
(function(e){"use strict";function v(e,n){t.async(function(){e.trigger("promise:resolved",{detail:n}),e.isResolved=!0,e.resolvedValue=n})}function m(e,n){t.async(function(){e.trigger("promise:failed",{detail:n}),e.isRejected=!0,e.rejectedValue=n})}function g(e){var t,n=[],r=new h,i=e.length;i===0&&r.resolve([]);var s=function(e){return function(t){o(e,t)}},o=function(e,t){n[e]=t,--i===0&&r.resolve(n)},u=function(e){r.reject(e)};for(t=0;t<i;t++)e[t].then(s(t),u);return r}function y(e,n){t[e]=n}var t={},n=typeof window!="undefined"?window:{},r=n.MutationObserver||n.WebKitMutationObserver,i;if(typeof process!="undefined"&&{}.toString.call(process)==="[object process]")t.async=function(e,t){process.nextTick(function(){e.call(t)})};else if(r){var s=[],o=new r(function(){var e=s.slice();s=[],e.forEach(function(e){var t=e[0],n=e[1];t.call(n)})}),u=document.createElement("div");o.observe(u,{attributes:!0}),window.addEventListener("unload",function(){o.disconnect(),o=null}),t.async=function(e,t){s.push([e,t]),u.setAttribute("drainQueue","drainQueue")}}else t.async=function(e,t){setTimeout(function(){e.call(t)},1)};var a=function(e,t){this.type=e;for(var n in t){if(!t.hasOwnProperty(n))continue;this[n]=t[n]}},f=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n][0]===t)return n;return-1},l=function(e){var t=e._promiseCallbacks;return t||(t=e._promiseCallbacks={}),t},c={mixin:function(e){return e.on=this.on,e.off=this.off,e.trigger=this.trigger,e},on:function(e,t,n){var r=l(this),i,s;e=e.split(/\s+/),n=n||this;while(s=e.shift())i=r[s],i||(i=r[s]=[]),f(i,t)===-1&&i.push([t,n])},off:function(e,t){var n=l(this),r,i,s;e=e.split(/\s+/);while(i=e.shift()){if(!t){n[i]=[];continue}r=n[i],s=f(r,t),s!==-1&&r.splice(s,1)}},trigger:function(e,t){var n=l(this),r,i,s,o,u;if(r=n[e])for(var f=0;f<r.length;f++)i=r[f],s=i[0],o=i[1],typeof t!="object"&&(t={detail:t}),u=new a(e,t),s.call(o,u)}},h=function(){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)},p=function(){},d=function(e,t,n,r){var i=typeof n=="function",s,o,u,a;if(i)try{s=n(r.detail),u=!0}catch(f){a=!0,o=f}else s=r.detail,u=!0;s&&typeof s.then=="function"?s.then(function(e){t.resolve(e)},function(e){t.reject(e)}):i&&u?t.resolve(s):a?t.reject(o):t[e](s)};h.prototype={then:function(e,n){var r=new h;return this.isResolved&&t.async(function(){d("resolve",r,e,{detail:this.resolvedValue})},this),this.isRejected&&t.async(function(){d("reject",r,n,{detail:this.rejectedValue})},this),this.on("promise:resolved",function(t){d("resolve",r,e,t)}),this.on("promise:failed",function(e){d("reject",r,n,e)}),r},resolve:function(e){v(this,e),this.resolve=p,this.reject=p},reject:function(e){m(this,e),this.resolve=p,this.reject=p}},c.mixin(h.prototype),e.Promise=h,e.Event=a,e.EventTarget=c,e.all=g,e.configure=y})(window.RSVP={}); (function(e){"use strict";function v(e,n){t.async(function(){e.trigger("promise:resolved",{detail:n}),e.isResolved=!0,e.resolvedValue=n})}function m(e,n){t.async(function(){e.trigger("promise:failed",{detail:n}),e.isRejected=!0,e.rejectedValue=n})}function g(e){var t,n=[],r=new p,i=e.length;i===0&&v(r,[]);var s=function(e){return function(t){o(e,t)}},o=function(e,t){n[e]=t,--i===0&&v(r,n)},u=function(e){m(r,e)};for(t=0;t<i;t++)e[t].then(s(t),u);return r}function y(e,n){t[e]=n}var t={},n=typeof window!="undefined"?window:{},r=n.MutationObserver||n.WebKitMutationObserver,i;if(typeof process!="undefined"&&{}.toString.call(process)==="[object process]")t.async=function(e,t){process.nextTick(function(){e.call(t)})};else if(r){var s=[],o=new r(function(){var e=s.slice();s=[],e.forEach(function(e){var t=e[0],n=e[1];t.call(n)})}),u=document.createElement("div");o.observe(u,{attributes:!0}),window.addEventListener("unload",function(){o.disconnect(),o=null}),t.async=function(e,t){s.push([e,t]),u.setAttribute("drainQueue","drainQueue")}}else t.async=function(e,t){setTimeout(function(){e.call(t)},1)};var a=function(e,t){this.type=e;for(var n in t){if(!t.hasOwnProperty(n))continue;this[n]=t[n]}},f=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n][0]===t)return n;return-1},l=function(e){var t=e._promiseCallbacks;return t||(t=e._promiseCallbacks={}),t},c={mixin:function(e){return e.on=this.on,e.off=this.off,e.trigger=this.trigger,e},on:function(e,t,n){var r=l(this),i,s;e=e.split(/\s+/),n=n||this;while(s=e.shift())i=r[s],i||(i=r[s]=[]),f(i,t)===-1&&i.push([t,n])},off:function(e,t){var n=l(this),r,i,s;e=e.split(/\s+/);while(i=e.shift()){if(!t){n[i]=[];continue}r=n[i],s=f(r,t),s!==-1&&r.splice(s,1)}},trigger:function(e,t){var n=l(this),r,i,s,o,u;if(r=n[e])for(var f=0;f<r.length;f++)i=r[f],s=i[0],o=i[1],typeof t!="object"&&(t={detail:t}),u=new a(e,t),s.call(o,u)}},h=function(){},p=function(e){var t=this,n=function(e){v(t,e),n=h,r=h},r=function(e){m(t,e),n=h,r=h};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&&e(n,r)},d=function(e,t,n,r){var i=typeof n=="function",s,o,u,a;if(i)try{s=n(r.detail),u=!0}catch(f){a=!0,o=f}else s=r.detail,u=!0;s&&typeof s.then=="function"?s.then(function(e){v(t,e)},function(e){m(t,e)}):i&&u?v(t,s):a?m(t,o):e==="resolve"?v(t,s):e==="reject"&&m(t,s)};p.prototype={then:function(e,n){var r=new p;return this.isResolved&&t.async(function(){d("resolve",r,e,{detail:this.resolvedValue})},this),this.isRejected&&t.async(function(){d("reject",r,n,{detail:this.rejectedValue})},this),this.on("promise:resolved",function(t){d("resolve",r,e,t)}),this.on("promise:failed",function(e){d("reject",r,n,e)}),r}},c.mixin(p.prototype),e.Promise=p,e.Event=a,e.EventTarget=c,e.all=g,e.configure=y})(window.RSVP={});
...@@ -140,7 +140,23 @@ var EventTarget = { ...@@ -140,7 +140,23 @@ var EventTarget = {
} }
}; };
var Promise = function() { var noop = function() {};
var Promise = function(resolver) {
var promise = this;
var resolvePromise = function(value) {
resolve(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
var rejectPromise = function(value) {
reject(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
this.on('promise:resolved', function(event) { this.on('promise:resolved', function(event) {
this.trigger('success', { detail: event.detail }); this.trigger('success', { detail: event.detail });
}, this); }, this);
...@@ -148,9 +164,11 @@ var Promise = function() { ...@@ -148,9 +164,11 @@ var Promise = function() {
this.on('promise:failed', function(event) { this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
};
var noop = function() {}; if (resolver) {
resolver(resolvePromise, rejectPromise);
}
};
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function', var hasCallback = typeof callback === 'function',
...@@ -171,16 +189,18 @@ var invokeCallback = function(type, promise, callback, event) { ...@@ -171,16 +189,18 @@ var invokeCallback = function(type, promise, callback, event) {
if (value && typeof value.then === 'function') { if (value && typeof value.then === 'function') {
value.then(function(value) { value.then(function(value) {
promise.resolve(value); resolve(promise, value);
}, function(error) { }, function(error) {
promise.reject(error); reject(promise, error);
}); });
} else if (hasCallback && succeeded) { } else if (hasCallback && succeeded) {
promise.resolve(value); resolve(promise, value);
} else if (failed) { } else if (failed) {
promise.reject(error); reject(promise, error);
} else { } else if (type === 'resolve') {
promise[type](value); resolve(promise, value);
} else if (type === 'reject') {
reject(promise, value);
} }
}; };
...@@ -209,20 +229,6 @@ Promise.prototype = { ...@@ -209,20 +229,6 @@ Promise.prototype = {
}); });
return thenPromise; return thenPromise;
},
resolve: function(value) {
resolve(this, value);
this.resolve = noop;
this.reject = noop;
},
reject: function(value) {
reject(this, value);
this.resolve = noop;
this.reject = noop;
} }
}; };
...@@ -248,28 +254,28 @@ function all(promises) { ...@@ -248,28 +254,28 @@ function all(promises) {
var remaining = promises.length; var remaining = promises.length;
if (remaining === 0) { if (remaining === 0) {
allPromise.resolve([]); resolve(allPromise, []);
} }
var resolver = function(index) { var resolver = function(index) {
return function(value) { return function(value) {
resolve(index, value); resolveAll(index, value);
}; };
}; };
var resolve = function(index, value) { var resolveAll = function(index, value) {
results[index] = value; results[index] = value;
if (--remaining === 0) { if (--remaining === 0) {
allPromise.resolve(results); resolve(allPromise, results);
} }
}; };
var reject = function(error) { var rejectAll = function(error) {
allPromise.reject(error); reject(allPromise, error);
}; };
for (i = 0; i < remaining; i++) { for (i = 0; i < remaining; i++) {
promises[i].then(resolver(i), reject); promises[i].then(resolver(i), rejectAll);
} }
return allPromise; return allPromise;
} }
......
...@@ -141,7 +141,23 @@ var EventTarget = { ...@@ -141,7 +141,23 @@ var EventTarget = {
} }
}; };
var Promise = function() { var noop = function() {};
var Promise = function(resolver) {
var promise = this;
var resolvePromise = function(value) {
resolve(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
var rejectPromise = function(value) {
reject(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
this.on('promise:resolved', function(event) { this.on('promise:resolved', function(event) {
this.trigger('success', { detail: event.detail }); this.trigger('success', { detail: event.detail });
}, this); }, this);
...@@ -149,9 +165,11 @@ var Promise = function() { ...@@ -149,9 +165,11 @@ var Promise = function() {
this.on('promise:failed', function(event) { this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
};
var noop = function() {}; if (resolver) {
resolver(resolvePromise, rejectPromise);
}
};
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function', var hasCallback = typeof callback === 'function',
...@@ -172,16 +190,18 @@ var invokeCallback = function(type, promise, callback, event) { ...@@ -172,16 +190,18 @@ var invokeCallback = function(type, promise, callback, event) {
if (value && typeof value.then === 'function') { if (value && typeof value.then === 'function') {
value.then(function(value) { value.then(function(value) {
promise.resolve(value); resolve(promise, value);
}, function(error) { }, function(error) {
promise.reject(error); reject(promise, error);
}); });
} else if (hasCallback && succeeded) { } else if (hasCallback && succeeded) {
promise.resolve(value); resolve(promise, value);
} else if (failed) { } else if (failed) {
promise.reject(error); reject(promise, error);
} else { } else if (type === 'resolve') {
promise[type](value); resolve(promise, value);
} else if (type === 'reject') {
reject(promise, value);
} }
}; };
...@@ -210,20 +230,6 @@ Promise.prototype = { ...@@ -210,20 +230,6 @@ Promise.prototype = {
}); });
return thenPromise; return thenPromise;
},
resolve: function(value) {
resolve(this, value);
this.resolve = noop;
this.reject = noop;
},
reject: function(value) {
reject(this, value);
this.resolve = noop;
this.reject = noop;
} }
}; };
...@@ -249,28 +255,28 @@ function all(promises) { ...@@ -249,28 +255,28 @@ function all(promises) {
var remaining = promises.length; var remaining = promises.length;
if (remaining === 0) { if (remaining === 0) {
allPromise.resolve([]); resolve(allPromise, []);
} }
var resolver = function(index) { var resolver = function(index) {
return function(value) { return function(value) {
resolve(index, value); resolveAll(index, value);
}; };
}; };
var resolve = function(index, value) { var resolveAll = function(index, value) {
results[index] = value; results[index] = value;
if (--remaining === 0) { if (--remaining === 0) {
allPromise.resolve(results); resolve(allPromise, results);
} }
}; };
var reject = function(error) { var rejectAll = function(error) {
allPromise.reject(error); reject(allPromise, error);
}; };
for (i = 0; i < remaining; i++) { for (i = 0; i < remaining; i++) {
promises[i].then(resolver(i), reject); promises[i].then(resolver(i), rejectAll);
} }
return allPromise; return allPromise;
} }
......
...@@ -6,34 +6,54 @@ describe("RSVP extensions", function() { ...@@ -6,34 +6,54 @@ describe("RSVP extensions", function() {
}); });
specify('fulfilled only after all of the other promises are fulfilled', function(done) { specify('fulfilled only after all of the other promises are fulfilled', function(done) {
var first = new RSVP.Promise(); var firstResolved, secondResolved, firstResolver, secondResolver;
var second = new RSVP.Promise();
var first = new RSVP.Promise(function(resolve) {
firstResolver = resolve;
});
first.then(function() {
firstResolved = true;
});
var second = new RSVP.Promise(function(resolve) {
secondResolver = resolve;
});
second.then(function() {
secondResolved = true;
});
setTimeout(function() { setTimeout(function() {
first.resolve(true); firstResolver(true);
}, 0); }, 0);
setTimeout(function() { setTimeout(function() {
second.resolve(true); secondResolver(true);
}, 0); }, 0);
RSVP.all([first, second]).then(function() { RSVP.all([first, second]).then(function() {
assert(first.isResolved); assert(firstResolved);
assert(second.isResolved); assert(secondResolved);
done(); done();
}); });
}); });
specify('rejected as soon as a promise is rejected', function(done) { specify('rejected as soon as a promise is rejected', function(done) {
var first = new RSVP.Promise(); var firstResolver, secondResolver;
var second = new RSVP.Promise();
var first = new RSVP.Promise(function(resolve, reject) {
firstResolver = { resolve: resolve, reject: reject };
});
var second = new RSVP.Promise(function(resolve, reject) {
secondResolver = { resolve: resolve, reject: reject };
});
setTimeout(function() { setTimeout(function() {
first.reject({}); firstResolver.reject({});
}, 0); }, 0);
setTimeout(function() { setTimeout(function() {
second.resolve(true); secondResolver.resolve(true);
}, 5000); }, 5000);
RSVP.all([first, second]).then(function() { RSVP.all([first, second]).then(function() {
...@@ -46,13 +66,23 @@ describe("RSVP extensions", function() { ...@@ -46,13 +66,23 @@ describe("RSVP extensions", function() {
}); });
specify('passes the resolved values of each promise to the callback in the correct order', function(done) { specify('passes the resolved values of each promise to the callback in the correct order', function(done) {
var first = new RSVP.Promise(); var firstResolver, secondResolver, thirdResolver;
var second = new RSVP.Promise();
var third = new RSVP.Promise(); var first = new RSVP.Promise(function(resolve, reject) {
firstResolver = { resolve: resolve, reject: reject };
});
var second = new RSVP.Promise(function(resolve, reject) {
secondResolver = { resolve: resolve, reject: reject };
});
var third = new RSVP.Promise(function(resolve, reject) {
thirdResolver = { resolve: resolve, reject: reject };
});
third.resolve(3); thirdResolver.resolve(3);
first.resolve(1); firstResolver.resolve(1);
second.resolve(2); secondResolver.resolve(2);
RSVP.all([first, second, third]).then(function(results) { RSVP.all([first, second, third]).then(function(results) {
assert(results.length === 3); assert(results.length === 3);
......
...@@ -141,7 +141,17 @@ var EventTarget = { ...@@ -141,7 +141,17 @@ var EventTarget = {
} }
}; };
var Promise = function() { var Promise = function(resolver) {
var promise = this;
function resolvePromise(value) {
resolve(promise, value);
}
function rejectPromise(value) {
reject(promise, value);
}
this.on('promise:resolved', function(event) { this.on('promise:resolved', function(event) {
this.trigger('success', { detail: event.detail }); this.trigger('success', { detail: event.detail });
}, this); }, this);
...@@ -149,6 +159,10 @@ var Promise = function() { ...@@ -149,6 +159,10 @@ var Promise = function() {
this.on('promise:failed', function(event) { this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
if (resolver) {
resolver(resolvePromise, rejectPromise);
}
}; };
var noop = function() {}; var noop = function() {};
......
...@@ -15,29 +15,26 @@ if (typeof RSVP !== 'undefined') { ...@@ -15,29 +15,26 @@ if (typeof RSVP !== 'undefined') {
var adapter = {}; var adapter = {};
adapter.fulfilled = function(value) { adapter.fulfilled = function(value) {
var promise = new Promise(); return new Promise(function(resolve, reject) {
promise.resolve(value); resolve(value);
return promise; });
}; };
adapter.rejected = function(error) { adapter.rejected = function(error) {
var promise = new Promise(); return new Promise(function(resolve, reject) {
promise.reject(error); reject(error);
return promise; });
}; };
adapter.pending = function () { adapter.pending = function () {
var promise = new Promise(); var pending = {};
return { pending.promise = new Promise(function(resolve, reject) {
promise: promise, pending.fulfill = resolve;
fulfill: function(value) { pending.reject = reject;
promise.resolve(value); });
},
reject: function(error) { return pending;
promise.reject(error);
}
};
}; };
module.exports = global.adapter = adapter; module.exports = global.adapter = adapter;
...@@ -558,7 +558,8 @@ var EventTarget = { ...@@ -558,7 +558,8 @@ var EventTarget = {
callbacks, callbackTuple, callback, binding, event; callbacks, callbackTuple, callback, binding, event;
if (callbacks = allCallbacks[eventName]) { if (callbacks = allCallbacks[eventName]) {
for (var i=0, l=callbacks.length; i<l; i++) { // Don't cache the callbacks.length since it may grow
for (var i=0; i<callbacks.length; i++) {
callbackTuple = callbacks[i]; callbackTuple = callbacks[i];
callback = callbackTuple[0]; callback = callbackTuple[0];
binding = callbackTuple[1]; binding = callbackTuple[1];
...@@ -574,7 +575,23 @@ var EventTarget = { ...@@ -574,7 +575,23 @@ var EventTarget = {
} }
}; };
var Promise = function() { var noop = function() {};
var Promise = function(resolver) {
var promise = this;
var resolvePromise = function(value) {
resolve(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
var rejectPromise = function(value) {
reject(promise, value);
resolvePromise = noop;
rejectPromise = noop;
};
this.on('promise:resolved', function(event) { this.on('promise:resolved', function(event) {
this.trigger('success', { detail: event.detail }); this.trigger('success', { detail: event.detail });
}, this); }, this);
...@@ -582,9 +599,11 @@ var Promise = function() { ...@@ -582,9 +599,11 @@ var Promise = function() {
this.on('promise:failed', function(event) { this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
};
var noop = function() {}; if (resolver) {
resolver(resolvePromise, rejectPromise);
}
};
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = typeof callback === 'function', var hasCallback = typeof callback === 'function',
...@@ -643,20 +662,6 @@ Promise.prototype = { ...@@ -643,20 +662,6 @@ Promise.prototype = {
}); });
return thenPromise; return thenPromise;
},
resolve: function(value) {
resolve(this, value);
this.resolve = noop;
this.reject = noop;
},
reject: function(value) {
reject(this, value);
this.resolve = noop;
this.reject = noop;
} }
}; };
...@@ -3102,7 +3107,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon.js",function(requir ...@@ -3102,7 +3107,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon.js",function(requir
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -3346,7 +3351,7 @@ var sinon = (function (buster) { ...@@ -3346,7 +3351,7 @@ var sinon = (function (buster) {
calledInOrder: function (spies) { calledInOrder: function (spies) {
for (var i = 1, l = spies.length; i < l; i++) { for (var i = 1, l = spies.length; i < l; i++) {
if (!spies[i - 1].calledBefore(spies[i])) { if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
return false; return false;
} }
} }
...@@ -3388,6 +3393,13 @@ var sinon = (function (buster) { ...@@ -3388,6 +3393,13 @@ var sinon = (function (buster) {
} }
var string = Object.prototype.toString.call(value); var string = Object.prototype.toString.call(value);
return string.substring(8, string.length - 1).toLowerCase(); return string.substring(8, string.length - 1).toLowerCase();
},
createStubInstance: function (constructor) {
if (typeof constructor !== "function") {
throw new TypeError("The constructor should be a function.");
}
return sinon.stub(sinon.create(constructor.prototype));
} }
}; };
...@@ -4768,19 +4780,19 @@ require.define("fs",function(require,module,exports,__dirname,__filename,process ...@@ -4768,19 +4780,19 @@ require.define("fs",function(require,module,exports,__dirname,__filename,process
}); });
require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(require,module,exports,__dirname,__filename,process,global){/** require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(require,module,exports,__dirname,__filename,process,global){/**
* @depend ../sinon.js * @depend ../sinon.js
* @depend match.js * @depend match.js
*/ */
/*jslint eqeqeq: false, onevar: false, plusplus: false*/ /*jslint eqeqeq: false, onevar: false, plusplus: false*/
/*global module, require, sinon*/ /*global module, require, sinon*/
/** /**
* Spy functions * Spy functions
* *
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
(function (sinon) { (function (sinon) {
...@@ -4804,7 +4816,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -4804,7 +4816,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
} }
if (!object && !property) { if (!object && !property) {
return spy.create(function () {}); return spy.create(function () { });
} }
var method = object[property]; var method = object[property];
...@@ -4877,7 +4889,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -4877,7 +4889,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
var p; var p;
if (func.length) { if (func.length) {
eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) + eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
") { return p.invoke(func, this, slice.call(arguments)); });"); ") { return p.invoke(func, this, slice.call(arguments)); });");
} }
else { else {
p = function proxy() { p = function proxy() {
...@@ -4918,7 +4930,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -4918,7 +4930,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
var name; var name;
if (typeof func != "function") { if (typeof func != "function") {
func = function () {}; func = function () { };
} else { } else {
name = sinon.functionName(func); name = sinon.functionName(func);
} }
...@@ -4975,8 +4987,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -4975,8 +4987,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
} }
return spyCall.create(this, this.thisValues[i], this.args[i], return spyCall.create(this, this.thisValues[i], this.args[i],
this.returnValues[i], this.exceptions[i], this.returnValues[i], this.exceptions[i],
this.callIds[i]); this.callIds[i]);
}, },
calledBefore: function calledBefore(spyFn) { calledBefore: function calledBefore(spyFn) {
...@@ -5086,15 +5098,26 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -5086,15 +5098,26 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
throw new Error(this.toString() + " cannot call arg since it was not yet invoked."); throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
}); });
spyApi.callArgWith = spyApi.callArg; spyApi.callArgWith = spyApi.callArg;
delegateToCalls(spyApi, "callArgOn", false, "callArgOnWith", function () {
throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
});
spyApi.callArgOnWith = spyApi.callArgOn;
delegateToCalls(spyApi, "yield", false, "yield", function () { delegateToCalls(spyApi, "yield", false, "yield", function () {
throw new Error(this.toString() + " cannot yield since it was not yet invoked."); throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
}); });
// "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode. // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
spyApi.invokeCallback = spyApi.yield; spyApi.invokeCallback = spyApi.yield;
delegateToCalls(spyApi, "yieldOn", false, "yieldOn", function () {
throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
});
delegateToCalls(spyApi, "yieldTo", false, "yieldTo", function (property) { delegateToCalls(spyApi, "yieldTo", false, "yieldTo", function (property) {
throw new Error(this.toString() + " cannot yield to '" + property + throw new Error(this.toString() + " cannot yield to '" + property +
"' since it was not yet invoked."); "' since it was not yet invoked.");
}); });
delegateToCalls(spyApi, "yieldToOn", false, "yieldToOn", function (property) {
throw new Error(this.toString() + " cannot yield to '" + property +
"' since it was not yet invoked.");
});
spyApi.formatters = { spyApi.formatters = {
"c": function (spy) { "c": function (spy) {
...@@ -5109,7 +5132,11 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -5109,7 +5132,11 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
var calls = []; var calls = [];
for (var i = 0, l = spy.callCount; i < l; ++i) { for (var i = 0, l = spy.callCount; i < l; ++i) {
push.call(calls, " " + spy.getCall(i).toString()); var stringifiedCall = " " + spy.getCall(i).toString();
if (/\n/.test(calls[i - 1])) {
stringifiedCall = "\n" + stringifiedCall;
}
push.call(calls, stringifiedCall);
} }
return calls.length > 0 ? "\n" + calls.join("\n") : ""; return calls.length > 0 ? "\n" + calls.join("\n") : "";
...@@ -5181,14 +5208,14 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -5181,14 +5208,14 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
}, },
calledWithMatch: function calledWithMatch() { calledWithMatch: function calledWithMatch() {
for (var i = 0, l = arguments.length; i < l; i += 1) { for (var i = 0, l = arguments.length; i < l; i += 1) {
var actual = this.args[i]; var actual = this.args[i];
var expectation = arguments[i]; var expectation = arguments[i];
if (!sinon.match || !sinon.match(expectation).test(actual)) { if (!sinon.match || !sinon.match(expectation).test(actual)) {
return false; return false;
} }
} }
return true; return true;
}, },
calledWithExactly: function calledWithExactly() { calledWithExactly: function calledWithExactly() {
...@@ -5201,7 +5228,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -5201,7 +5228,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
}, },
notCalledWithMatch: function notCalledWithMatch() { notCalledWithMatch: function notCalledWithMatch() {
return !this.calledWithMatch.apply(this, arguments); return !this.calledWithMatch.apply(this, arguments);
}, },
returned: function returned(value) { returned: function returned(value) {
...@@ -5236,16 +5263,28 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -5236,16 +5263,28 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
this.args[pos](); this.args[pos]();
}, },
callArgOn: function (pos, thisValue) {
this.args[pos].apply(thisValue);
},
callArgWith: function (pos) { callArgWith: function (pos) {
var args = slice.call(arguments, 1); this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
this.args[pos].apply(null, args); },
callArgOnWith: function (pos, thisValue) {
var args = slice.call(arguments, 2);
this.args[pos].apply(thisValue, args);
}, },
"yield": function () { "yield": function () {
this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
},
yieldOn: function (thisValue) {
var args = this.args; var args = this.args;
for (var i = 0, l = args.length; i < l; ++i) { for (var i = 0, l = args.length; i < l; ++i) {
if (typeof args[i] === "function") { if (typeof args[i] === "function") {
args[i].apply(null, slice.call(arguments)); args[i].apply(thisValue, slice.call(arguments, 1));
return; return;
} }
} }
...@@ -5253,10 +5292,14 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -5253,10 +5292,14 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
}, },
yieldTo: function (prop) { yieldTo: function (prop) {
this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
},
yieldToOn: function (prop, thisValue) {
var args = this.args; var args = this.args;
for (var i = 0, l = args.length; i < l; ++i) { for (var i = 0, l = args.length; i < l; ++i) {
if (args[i] && typeof args[i][prop] === "function") { if (args[i] && typeof args[i][prop] === "function") {
args[i][prop].apply(null, slice.call(arguments, 1)); args[i][prop].apply(thisValue, slice.call(arguments, 2));
return; return;
} }
} }
...@@ -5319,7 +5362,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -5319,7 +5362,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -5366,7 +5409,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -5366,7 +5409,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
function getChangingValue(stub, property) { function getChangingValue(stub, property) {
var index = stub.callCount - 1; var index = stub.callCount - 1;
var prop = index in stub[property] ? stub[property][index] : stub[property + "Last"]; var values = stub[property];
var prop = index in values ? values[index] : values[values.length - 1];
stub[property + "Last"] = prop; stub[property + "Last"] = prop;
return prop; return prop;
...@@ -5423,8 +5467,6 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -5423,8 +5467,6 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
var nextTick = (function () { var nextTick = (function () {
if (typeof process === "object" && typeof process.nextTick === "function") { if (typeof process === "object" && typeof process.nextTick === "function") {
return process.nextTick; return process.nextTick;
} else if (typeof msSetImmediate === "function") {
return msSetImmediate.bind(window);
} else if (typeof setImmediate === "function") { } else if (typeof setImmediate === "function") {
return setImmediate; return setImmediate;
} else { } else {
...@@ -5442,8 +5484,6 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -5442,8 +5484,6 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
throw new TypeError(getCallbackError(stub, func, args)); throw new TypeError(getCallbackError(stub, func, args));
} }
var index = stub.callCount - 1;
var callbackArguments = getChangingValue(stub, "callbackArguments"); var callbackArguments = getChangingValue(stub, "callbackArguments");
var callbackContext = getChangingValue(stub, "callbackContexts"); var callbackContext = getChangingValue(stub, "callbackContexts");
...@@ -5509,6 +5549,25 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -5509,6 +5549,25 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
return functionStub; return functionStub;
}, },
resetBehavior: function () {
var i;
this.callArgAts = [];
this.callbackArguments = [];
this.callbackContexts = [];
this.callArgProps = [];
delete this.returnValue;
delete this.returnArgAt;
this.returnThis = false;
if (this.fakes) {
for (i = 0; i < this.fakes.length; i++) {
this.fakes[i].resetBehavior();
}
}
},
returns: function returns(value) { returns: function returns(value) {
this.returnValue = value; this.returnValue = value;
...@@ -5677,7 +5736,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/mock.js",function(r ...@@ -5677,7 +5736,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/mock.js",function(r
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -6046,7 +6105,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/mock.js",function(r ...@@ -6046,7 +6105,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/mock.js",function(r
} }
var callStr = sinon.spyCall.toString.call({ var callStr = sinon.spyCall.toString.call({
proxy: this.method, args: args proxy: this.method || "anonymous mock expectation",
args: args
}); });
var message = callStr.replace(", [...", "[, ...") + " " + var message = callStr.replace(", [...", "[, ...") + " " +
...@@ -6104,7 +6164,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/collection.js",func ...@@ -6104,7 +6164,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/collection.js",func
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -6259,7 +6319,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/assert.js",function ...@@ -6259,7 +6319,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/assert.js",function
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -6441,7 +6501,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/sandbox.js",functio ...@@ -6441,7 +6501,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/sandbox.js",functio
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -6571,7 +6631,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/util/fake_timers.js ...@@ -6571,7 +6631,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/util/fake_timers.js
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -6713,6 +6773,8 @@ if (typeof sinon == "undefined") { ...@@ -6713,6 +6773,8 @@ if (typeof sinon == "undefined") {
if (firstException) { if (firstException) {
throw firstException; throw firstException;
} }
return this.now;
}, },
firstTimerInRange: function (from, to) { firstTimerInRange: function (from, to) {
...@@ -6920,7 +6982,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/test.js",function(r ...@@ -6920,7 +6982,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/test.js",function(r
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -6996,7 +7058,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/test_case.js",funct ...@@ -6996,7 +7058,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/test_case.js",funct
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -7343,29 +7405,26 @@ if (typeof RSVP !== 'undefined') { ...@@ -7343,29 +7405,26 @@ if (typeof RSVP !== 'undefined') {
var adapter = {}; var adapter = {};
adapter.fulfilled = function(value) { adapter.fulfilled = function(value) {
var promise = new Promise(); return new Promise(function(resolve, reject) {
promise.resolve(value); resolve(value);
return promise; });
}; };
adapter.rejected = function(error) { adapter.rejected = function(error) {
var promise = new Promise(); return new Promise(function(resolve, reject) {
promise.reject(error); reject(error);
return promise; });
}; };
adapter.pending = function () { adapter.pending = function () {
var promise = new Promise(); var pending = {};
return { pending.promise = new Promise(function(resolve, reject) {
promise: promise, pending.fulfill = resolve;
fulfill: function(value) { pending.reject = reject;
promise.resolve(value); });
},
reject: function(error) { return pending;
promise.reject(error);
}
};
}; };
module.exports = global.adapter = adapter; module.exports = global.adapter = adapter;
...@@ -7950,6 +8009,28 @@ describe("3.2.5: `then` may be called multiple times on the same promise.", func ...@@ -7950,6 +8009,28 @@ describe("3.2.5: `then` may be called multiple times on the same promise.", func
done(); done();
}); });
}); });
describe("even when one handler is added inside another handler", function () {
testFulfilled(dummy, function (promise, done) {
var handler1 = sinon.spy();
var handler2 = sinon.spy();
var handler3 = sinon.spy();
promise.then(function () {
handler1();
promise.then(handler3);
});
promise.then(handler2);
promise.then(function () {
// Give implementations a bit of extra time to flush their internal queue, if necessary.
setTimeout(function () {
sinon.assert.callOrder(handler1, handler2, handler3);
done();
}, 15);
});
});
});
}); });
}); });
...@@ -8045,6 +8126,28 @@ describe("3.2.5: `then` may be called multiple times on the same promise.", func ...@@ -8045,6 +8126,28 @@ describe("3.2.5: `then` may be called multiple times on the same promise.", func
done(); done();
}); });
}); });
describe("even when one handler is added inside another handler", function () {
testRejected(dummy, function (promise, done) {
var handler1 = sinon.spy();
var handler2 = sinon.spy();
var handler3 = sinon.spy();
promise.then(null, function () {
handler1();
promise.then(null, handler3);
});
promise.then(null, handler2);
promise.then(null, function () {
// Give implementations a bit of extra time to flush their internal queue, if necessary.
setTimeout(function () {
sinon.assert.callOrder(handler1, handler2, handler3);
done();
}, 15);
});
});
});
}); });
}); });
}); });
...@@ -8065,13 +8168,14 @@ var pending = adapter.pending; ...@@ -8065,13 +8168,14 @@ var pending = adapter.pending;
var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it
var sentinel = { sentinel: "sentinel" }; // a sentinel fulfillment value to test for with strict equality var sentinel = { sentinel: "sentinel" }; // a sentinel fulfillment value to test for with strict equality
var other = { other: "other" }; // a value we don't want to be strict equal to
describe("3.2.6: `then` must return a promise: `promise2 = promise1.then(onFulfilled, onRejected)`", function () { describe("3.2.6: `then` must return a promise: `promise2 = promise1.then(onFulfilled, onRejected)`", function () {
specify("is a promise", function () { specify("is a promise", function () {
var promise1 = pending().promise; var promise1 = pending().promise;
var promise2 = promise1.then(); var promise2 = promise1.then();
assert.strictEqual(typeof promise2, "object"); assert(typeof promise2 === "object" || typeof promise2 === "function");
assert.notStrictEqual(promise2, null); assert.notStrictEqual(promise2, null);
assert.strictEqual(typeof promise2.then, "function"); assert.strictEqual(typeof promise2.then, "function");
}); });
...@@ -8345,6 +8449,7 @@ describe("3.2.6: `then` must return a promise: `promise2 = promise1.then(onFulfi ...@@ -8345,6 +8449,7 @@ describe("3.2.6: `then` must return a promise: `promise2 = promise1.then(onFulfi
testNonFunction(false, "`false`"); testNonFunction(false, "`false`");
testNonFunction(5, "`5`"); testNonFunction(5, "`5`");
testNonFunction({}, "an object"); testNonFunction({}, "an object");
testNonFunction([function () { return other; }], "an array containing a function");
}); });
describe("3.2.6.5: If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected " + describe("3.2.6.5: If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected " +
...@@ -8368,6 +8473,7 @@ describe("3.2.6: `then` must return a promise: `promise2 = promise1.then(onFulfi ...@@ -8368,6 +8473,7 @@ describe("3.2.6: `then` must return a promise: `promise2 = promise1.then(onFulfi
testNonFunction(false, "`false`"); testNonFunction(false, "`false`");
testNonFunction(5, "`5`"); testNonFunction(5, "`5`");
testNonFunction({}, "an object"); testNonFunction({}, "an object");
testNonFunction([function () { return other; }], "an array containing a function");
}); });
}); });
...@@ -8432,7 +8538,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon.js",function(requir ...@@ -8432,7 +8538,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon.js",function(requir
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -8676,7 +8782,7 @@ var sinon = (function (buster) { ...@@ -8676,7 +8782,7 @@ var sinon = (function (buster) {
calledInOrder: function (spies) { calledInOrder: function (spies) {
for (var i = 1, l = spies.length; i < l; i++) { for (var i = 1, l = spies.length; i < l; i++) {
if (!spies[i - 1].calledBefore(spies[i])) { if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
return false; return false;
} }
} }
...@@ -8718,6 +8824,13 @@ var sinon = (function (buster) { ...@@ -8718,6 +8824,13 @@ var sinon = (function (buster) {
} }
var string = Object.prototype.toString.call(value); var string = Object.prototype.toString.call(value);
return string.substring(8, string.length - 1).toLowerCase(); return string.substring(8, string.length - 1).toLowerCase();
},
createStubInstance: function (constructor) {
if (typeof constructor !== "function") {
throw new TypeError("The constructor should be a function.");
}
return sinon.stub(sinon.create(constructor.prototype));
} }
}; };
...@@ -8776,7 +8889,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/assert.js",function ...@@ -8776,7 +8889,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/assert.js",function
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -8957,7 +9070,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/collection.js",func ...@@ -8957,7 +9070,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/collection.js",func
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -9356,7 +9469,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/mock.js",function(r ...@@ -9356,7 +9469,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/mock.js",function(r
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -9725,7 +9838,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/mock.js",function(r ...@@ -9725,7 +9838,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/mock.js",function(r
} }
var callStr = sinon.spyCall.toString.call({ var callStr = sinon.spyCall.toString.call({
proxy: this.method, args: args proxy: this.method || "anonymous mock expectation",
args: args
}); });
var message = callStr.replace(", [...", "[, ...") + " " + var message = callStr.replace(", [...", "[, ...") + " " +
...@@ -9786,7 +9900,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/sandbox.js",functio ...@@ -9786,7 +9900,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/sandbox.js",functio
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -9901,19 +10015,19 @@ if (typeof module == "object" && typeof require == "function") { ...@@ -9901,19 +10015,19 @@ if (typeof module == "object" && typeof require == "function") {
require("/promises-tests/node_modules/sinon/lib/sinon/sandbox.js"); require("/promises-tests/node_modules/sinon/lib/sinon/sandbox.js");
require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(require,module,exports,__dirname,__filename,process,global){/** require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(require,module,exports,__dirname,__filename,process,global){/**
* @depend ../sinon.js * @depend ../sinon.js
* @depend match.js * @depend match.js
*/ */
/*jslint eqeqeq: false, onevar: false, plusplus: false*/ /*jslint eqeqeq: false, onevar: false, plusplus: false*/
/*global module, require, sinon*/ /*global module, require, sinon*/
/** /**
* Spy functions * Spy functions
* *
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
(function (sinon) { (function (sinon) {
...@@ -9937,7 +10051,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -9937,7 +10051,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
} }
if (!object && !property) { if (!object && !property) {
return spy.create(function () {}); return spy.create(function () { });
} }
var method = object[property]; var method = object[property];
...@@ -10010,7 +10124,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10010,7 +10124,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
var p; var p;
if (func.length) { if (func.length) {
eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) + eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
") { return p.invoke(func, this, slice.call(arguments)); });"); ") { return p.invoke(func, this, slice.call(arguments)); });");
} }
else { else {
p = function proxy() { p = function proxy() {
...@@ -10051,7 +10165,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10051,7 +10165,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
var name; var name;
if (typeof func != "function") { if (typeof func != "function") {
func = function () {}; func = function () { };
} else { } else {
name = sinon.functionName(func); name = sinon.functionName(func);
} }
...@@ -10108,8 +10222,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10108,8 +10222,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
} }
return spyCall.create(this, this.thisValues[i], this.args[i], return spyCall.create(this, this.thisValues[i], this.args[i],
this.returnValues[i], this.exceptions[i], this.returnValues[i], this.exceptions[i],
this.callIds[i]); this.callIds[i]);
}, },
calledBefore: function calledBefore(spyFn) { calledBefore: function calledBefore(spyFn) {
...@@ -10219,15 +10333,26 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10219,15 +10333,26 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
throw new Error(this.toString() + " cannot call arg since it was not yet invoked."); throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
}); });
spyApi.callArgWith = spyApi.callArg; spyApi.callArgWith = spyApi.callArg;
delegateToCalls(spyApi, "callArgOn", false, "callArgOnWith", function () {
throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
});
spyApi.callArgOnWith = spyApi.callArgOn;
delegateToCalls(spyApi, "yield", false, "yield", function () { delegateToCalls(spyApi, "yield", false, "yield", function () {
throw new Error(this.toString() + " cannot yield since it was not yet invoked."); throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
}); });
// "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode. // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
spyApi.invokeCallback = spyApi.yield; spyApi.invokeCallback = spyApi.yield;
delegateToCalls(spyApi, "yieldOn", false, "yieldOn", function () {
throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
});
delegateToCalls(spyApi, "yieldTo", false, "yieldTo", function (property) { delegateToCalls(spyApi, "yieldTo", false, "yieldTo", function (property) {
throw new Error(this.toString() + " cannot yield to '" + property + throw new Error(this.toString() + " cannot yield to '" + property +
"' since it was not yet invoked."); "' since it was not yet invoked.");
}); });
delegateToCalls(spyApi, "yieldToOn", false, "yieldToOn", function (property) {
throw new Error(this.toString() + " cannot yield to '" + property +
"' since it was not yet invoked.");
});
spyApi.formatters = { spyApi.formatters = {
"c": function (spy) { "c": function (spy) {
...@@ -10242,7 +10367,11 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10242,7 +10367,11 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
var calls = []; var calls = [];
for (var i = 0, l = spy.callCount; i < l; ++i) { for (var i = 0, l = spy.callCount; i < l; ++i) {
push.call(calls, " " + spy.getCall(i).toString()); var stringifiedCall = " " + spy.getCall(i).toString();
if (/\n/.test(calls[i - 1])) {
stringifiedCall = "\n" + stringifiedCall;
}
push.call(calls, stringifiedCall);
} }
return calls.length > 0 ? "\n" + calls.join("\n") : ""; return calls.length > 0 ? "\n" + calls.join("\n") : "";
...@@ -10314,14 +10443,14 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10314,14 +10443,14 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
}, },
calledWithMatch: function calledWithMatch() { calledWithMatch: function calledWithMatch() {
for (var i = 0, l = arguments.length; i < l; i += 1) { for (var i = 0, l = arguments.length; i < l; i += 1) {
var actual = this.args[i]; var actual = this.args[i];
var expectation = arguments[i]; var expectation = arguments[i];
if (!sinon.match || !sinon.match(expectation).test(actual)) { if (!sinon.match || !sinon.match(expectation).test(actual)) {
return false; return false;
} }
} }
return true; return true;
}, },
calledWithExactly: function calledWithExactly() { calledWithExactly: function calledWithExactly() {
...@@ -10334,7 +10463,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10334,7 +10463,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
}, },
notCalledWithMatch: function notCalledWithMatch() { notCalledWithMatch: function notCalledWithMatch() {
return !this.calledWithMatch.apply(this, arguments); return !this.calledWithMatch.apply(this, arguments);
}, },
returned: function returned(value) { returned: function returned(value) {
...@@ -10369,16 +10498,28 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10369,16 +10498,28 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
this.args[pos](); this.args[pos]();
}, },
callArgOn: function (pos, thisValue) {
this.args[pos].apply(thisValue);
},
callArgWith: function (pos) { callArgWith: function (pos) {
var args = slice.call(arguments, 1); this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
this.args[pos].apply(null, args); },
callArgOnWith: function (pos, thisValue) {
var args = slice.call(arguments, 2);
this.args[pos].apply(thisValue, args);
}, },
"yield": function () { "yield": function () {
this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
},
yieldOn: function (thisValue) {
var args = this.args; var args = this.args;
for (var i = 0, l = args.length; i < l; ++i) { for (var i = 0, l = args.length; i < l; ++i) {
if (typeof args[i] === "function") { if (typeof args[i] === "function") {
args[i].apply(null, slice.call(arguments)); args[i].apply(thisValue, slice.call(arguments, 1));
return; return;
} }
} }
...@@ -10386,10 +10527,14 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re ...@@ -10386,10 +10527,14 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/spy.js",function(re
}, },
yieldTo: function (prop) { yieldTo: function (prop) {
this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
},
yieldToOn: function (prop, thisValue) {
var args = this.args; var args = this.args;
for (var i = 0, l = args.length; i < l; ++i) { for (var i = 0, l = args.length; i < l; ++i) {
if (args[i] && typeof args[i][prop] === "function") { if (args[i] && typeof args[i][prop] === "function") {
args[i][prop].apply(null, slice.call(arguments, 1)); args[i][prop].apply(thisValue, slice.call(arguments, 2));
return; return;
} }
} }
...@@ -10453,7 +10598,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -10453,7 +10598,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -10500,7 +10645,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -10500,7 +10645,8 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
function getChangingValue(stub, property) { function getChangingValue(stub, property) {
var index = stub.callCount - 1; var index = stub.callCount - 1;
var prop = index in stub[property] ? stub[property][index] : stub[property + "Last"]; var values = stub[property];
var prop = index in values ? values[index] : values[values.length - 1];
stub[property + "Last"] = prop; stub[property + "Last"] = prop;
return prop; return prop;
...@@ -10557,8 +10703,6 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -10557,8 +10703,6 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
var nextTick = (function () { var nextTick = (function () {
if (typeof process === "object" && typeof process.nextTick === "function") { if (typeof process === "object" && typeof process.nextTick === "function") {
return process.nextTick; return process.nextTick;
} else if (typeof msSetImmediate === "function") {
return msSetImmediate.bind(window);
} else if (typeof setImmediate === "function") { } else if (typeof setImmediate === "function") {
return setImmediate; return setImmediate;
} else { } else {
...@@ -10576,8 +10720,6 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -10576,8 +10720,6 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
throw new TypeError(getCallbackError(stub, func, args)); throw new TypeError(getCallbackError(stub, func, args));
} }
var index = stub.callCount - 1;
var callbackArguments = getChangingValue(stub, "callbackArguments"); var callbackArguments = getChangingValue(stub, "callbackArguments");
var callbackContext = getChangingValue(stub, "callbackContexts"); var callbackContext = getChangingValue(stub, "callbackContexts");
...@@ -10643,6 +10785,25 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r ...@@ -10643,6 +10785,25 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/stub.js",function(r
return functionStub; return functionStub;
}, },
resetBehavior: function () {
var i;
this.callArgAts = [];
this.callbackArguments = [];
this.callbackContexts = [];
this.callArgProps = [];
delete this.returnValue;
delete this.returnArgAt;
this.returnThis = false;
if (this.fakes) {
for (i = 0; i < this.fakes.length; i++) {
this.fakes[i].resetBehavior();
}
}
},
returns: function returns(value) { returns: function returns(value) {
this.returnValue = value; this.returnValue = value;
...@@ -10814,7 +10975,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/test.js",function(r ...@@ -10814,7 +10975,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/test.js",function(r
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
...@@ -10891,7 +11052,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/test_case.js",funct ...@@ -10891,7 +11052,7 @@ require.define("/promises-tests/node_modules/sinon/lib/sinon/test_case.js",funct
* @author Christian Johansen (christian@cjohansen.no) * @author Christian Johansen (christian@cjohansen.no)
* @license BSD * @license BSD
* *
* Copyright (c) 2010-2011 Christian Johansen * Copyright (c) 2010-2013 Christian Johansen
*/ */
"use strict"; "use strict";
......
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